atig 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. data/.gitignore +24 -0
  2. data/Gemfile +3 -0
  3. data/README.mkdn +52 -0
  4. data/Rakefile +15 -0
  5. data/atig.gemspec +25 -0
  6. data/bin/atig +74 -0
  7. data/docs/OMakefile +32 -0
  8. data/docs/OMakeroot +45 -0
  9. data/docs/_static/allow.png +0 -0
  10. data/docs/_static/emacs.png +0 -0
  11. data/docs/_static/irc_setting.png +0 -0
  12. data/docs/_static/irssi.png +0 -0
  13. data/docs/_static/limechat.png +0 -0
  14. data/docs/_static/limechat_s.png +0 -0
  15. data/docs/_static/oauth_channel.png +0 -0
  16. data/docs/_static/screenshot.png +0 -0
  17. data/docs/_static/structure.png +0 -0
  18. data/docs/_static/verify.png +0 -0
  19. data/docs/changelog.rst +96 -0
  20. data/docs/commandline_options.rst +21 -0
  21. data/docs/commands.rst +84 -0
  22. data/docs/conf.py +194 -0
  23. data/docs/config.rst +159 -0
  24. data/docs/feature.rst +41 -0
  25. data/docs/graphics.graffle +1995 -0
  26. data/docs/hacking_guide.rst +43 -0
  27. data/docs/index.rst +109 -0
  28. data/docs/irc.rst +31 -0
  29. data/docs/options.rst +75 -0
  30. data/docs/quickstart.rst +89 -0
  31. data/docs/resize.sh +7 -0
  32. data/docs/tiarra.rst +2 -0
  33. data/docs/tig.rst +21 -0
  34. data/lib/atig.rb +19 -0
  35. data/lib/atig/agent.rb +8 -0
  36. data/lib/atig/agent/agent.rb +38 -0
  37. data/lib/atig/agent/clenup.rb +23 -0
  38. data/lib/atig/agent/dm.rb +35 -0
  39. data/lib/atig/agent/following.rb +45 -0
  40. data/lib/atig/agent/full_list.rb +20 -0
  41. data/lib/atig/agent/list.rb +55 -0
  42. data/lib/atig/agent/list_status.rb +46 -0
  43. data/lib/atig/agent/mention.rb +13 -0
  44. data/lib/atig/agent/other_list.rb +18 -0
  45. data/lib/atig/agent/own_list.rb +18 -0
  46. data/lib/atig/agent/stream_follow.rb +38 -0
  47. data/lib/atig/agent/timeline.rb +13 -0
  48. data/lib/atig/agent/user_stream.rb +31 -0
  49. data/lib/atig/basic_twitter.rb +116 -0
  50. data/lib/atig/bitly.rb +52 -0
  51. data/lib/atig/channel.rb +5 -0
  52. data/lib/atig/channel/channel.rb +17 -0
  53. data/lib/atig/channel/dm.rb +14 -0
  54. data/lib/atig/channel/list.rb +76 -0
  55. data/lib/atig/channel/mention.rb +20 -0
  56. data/lib/atig/channel/retweet.rb +28 -0
  57. data/lib/atig/channel/timeline.rb +74 -0
  58. data/lib/atig/command.rb +21 -0
  59. data/lib/atig/command/autofix.rb +58 -0
  60. data/lib/atig/command/command.rb +24 -0
  61. data/lib/atig/command/command_helper.rb +95 -0
  62. data/lib/atig/command/destroy.rb +44 -0
  63. data/lib/atig/command/dm.rb +31 -0
  64. data/lib/atig/command/favorite.rb +27 -0
  65. data/lib/atig/command/info.rb +50 -0
  66. data/lib/atig/command/limit.rb +15 -0
  67. data/lib/atig/command/location.rb +23 -0
  68. data/lib/atig/command/name.rb +18 -0
  69. data/lib/atig/command/option.rb +37 -0
  70. data/lib/atig/command/refresh.rb +18 -0
  71. data/lib/atig/command/reply.rb +37 -0
  72. data/lib/atig/command/retweet.rb +63 -0
  73. data/lib/atig/command/search.rb +51 -0
  74. data/lib/atig/command/spam.rb +26 -0
  75. data/lib/atig/command/status.rb +41 -0
  76. data/lib/atig/command/thread.rb +44 -0
  77. data/lib/atig/command/time.rb +32 -0
  78. data/lib/atig/command/uptime.rb +32 -0
  79. data/lib/atig/command/user.rb +42 -0
  80. data/lib/atig/command/user_info.rb +27 -0
  81. data/lib/atig/command/version.rb +49 -0
  82. data/lib/atig/command/whois.rb +39 -0
  83. data/lib/atig/db/db.rb +60 -0
  84. data/lib/atig/db/followings.rb +131 -0
  85. data/lib/atig/db/listenable.rb +22 -0
  86. data/lib/atig/db/lists.rb +76 -0
  87. data/lib/atig/db/roman.rb +30 -0
  88. data/lib/atig/db/sized_uniq_array.rb +62 -0
  89. data/lib/atig/db/sql.rb +35 -0
  90. data/lib/atig/db/statuses.rb +147 -0
  91. data/lib/atig/db/transaction.rb +47 -0
  92. data/lib/atig/exception_util.rb +26 -0
  93. data/lib/atig/gateway.rb +62 -0
  94. data/lib/atig/gateway/channel.rb +99 -0
  95. data/lib/atig/gateway/session.rb +326 -0
  96. data/lib/atig/http.rb +95 -0
  97. data/lib/atig/ifilter.rb +7 -0
  98. data/lib/atig/ifilter/expand_url.rb +74 -0
  99. data/lib/atig/ifilter/retweet.rb +14 -0
  100. data/lib/atig/ifilter/retweet_time.rb +16 -0
  101. data/lib/atig/ifilter/sanitize.rb +18 -0
  102. data/lib/atig/ifilter/strip.rb +15 -0
  103. data/lib/atig/ifilter/utf7.rb +26 -0
  104. data/lib/atig/ifilter/xid.rb +36 -0
  105. data/lib/atig/levenshtein.rb +49 -0
  106. data/lib/atig/monkey.rb +4 -0
  107. data/lib/atig/oauth-patch.rb +40 -0
  108. data/lib/atig/oauth.rb +55 -0
  109. data/lib/atig/ofilter.rb +4 -0
  110. data/lib/atig/ofilter/escape_url.rb +102 -0
  111. data/lib/atig/ofilter/footer.rb +20 -0
  112. data/lib/atig/ofilter/geo.rb +17 -0
  113. data/lib/atig/ofilter/short_url.rb +47 -0
  114. data/lib/atig/option.rb +90 -0
  115. data/lib/atig/scheduler.rb +79 -0
  116. data/lib/atig/search.rb +22 -0
  117. data/lib/atig/search_twitter.rb +21 -0
  118. data/lib/atig/sized_hash.rb +33 -0
  119. data/lib/atig/stream.rb +66 -0
  120. data/lib/atig/twitter.rb +79 -0
  121. data/lib/atig/twitter_struct.rb +63 -0
  122. data/lib/atig/unu.rb +27 -0
  123. data/lib/atig/update_checker.rb +53 -0
  124. data/lib/atig/url_escape.rb +62 -0
  125. data/lib/atig/util.rb +16 -0
  126. data/lib/atig/version.rb +3 -0
  127. data/lib/memory_profiler.rb +77 -0
  128. data/spec/command/autofix_spec.rb +35 -0
  129. data/spec/command/destroy_spec.rb +98 -0
  130. data/spec/command/dm_spec.rb +28 -0
  131. data/spec/command/favorite_spec.rb +55 -0
  132. data/spec/command/limit_spec.rb +27 -0
  133. data/spec/command/location_spec.rb +25 -0
  134. data/spec/command/name_spec.rb +19 -0
  135. data/spec/command/option_spec.rb +133 -0
  136. data/spec/command/refresh_spec.rb +22 -0
  137. data/spec/command/reply_spec.rb +79 -0
  138. data/spec/command/retweet_spec.rb +66 -0
  139. data/spec/command/spam_spec.rb +27 -0
  140. data/spec/command/status_spec.rb +44 -0
  141. data/spec/command/thread_spec.rb +91 -0
  142. data/spec/command/time_spec.rb +52 -0
  143. data/spec/command/uptime_spec.rb +55 -0
  144. data/spec/command/user_info_spec.rb +42 -0
  145. data/spec/command/user_spec.rb +50 -0
  146. data/spec/command/version_spec.rb +67 -0
  147. data/spec/command/whois_spec.rb +78 -0
  148. data/spec/db/followings_spec.rb +100 -0
  149. data/spec/db/listenable_spec.rb +32 -0
  150. data/spec/db/lists_spec.rb +104 -0
  151. data/spec/db/roman_spec.rb +17 -0
  152. data/spec/db/sized_uniq_array_spec.rb +63 -0
  153. data/spec/db/statuses_spec.rb +180 -0
  154. data/spec/ifilter/expand_url_spec.rb +44 -0
  155. data/spec/ifilter/retweet_spec.rb +28 -0
  156. data/spec/ifilter/retweet_time_spec.rb +25 -0
  157. data/spec/ifilter/sanitize_spec.rb +25 -0
  158. data/spec/ifilter/sid_spec.rb +29 -0
  159. data/spec/ifilter/strip_spec.rb +23 -0
  160. data/spec/ifilter/tid_spec.rb +29 -0
  161. data/spec/ifilter/utf7_spec.rb +30 -0
  162. data/spec/levenshtein_spec.rb +24 -0
  163. data/spec/ofilter/escape_url_spec.rb +50 -0
  164. data/spec/ofilter/footer_spec.rb +32 -0
  165. data/spec/ofilter/geo_spec.rb +33 -0
  166. data/spec/ofilter/short_url_spec.rb +127 -0
  167. data/spec/option_spec.rb +91 -0
  168. data/spec/sized_hash_spec.rb +45 -0
  169. data/spec/spec_helper.rb +35 -0
  170. data/spec/update_checker_spec.rb +55 -0
  171. metadata +326 -0
data/lib/atig/http.rb ADDED
@@ -0,0 +1,95 @@
1
+ require "net/https"
2
+ require 'atig/util'
3
+
4
+ module Atig
5
+ class Http
6
+ include Util
7
+
8
+ @@proxy = nil
9
+ def self.proxy=(proxy)
10
+ if proxy =~ /\A(?:([^:@]+)(?::([^@]+))?@)?([^:]+)(?::(\d+))?\z/ then
11
+ @@proxy = OpenStruct.new({
12
+ :user => $1,
13
+ :password => $2,
14
+ :address => $3,
15
+ :port => $4.to_i,
16
+ })
17
+ end
18
+ end
19
+
20
+ def initialize(logger=nil)
21
+ @log = logger
22
+ @cert_store = OpenSSL::X509::Store.new
23
+ @cert_store.set_default_paths
24
+ end
25
+
26
+ def server_name
27
+ "twittergw"
28
+ end
29
+
30
+ def server_version
31
+ @server_version ||= instance_eval {
32
+ head = `git rev-parse HEAD 2>/dev/null`.chomp
33
+ head.empty?? "unknown" : head
34
+ }
35
+ end
36
+
37
+ def http(uri, open_timeout = nil, read_timeout = 60)
38
+ http = case
39
+ when @@proxy
40
+ Net::HTTP.new(uri.host, uri.port, @@proxy.address, @@proxy.port,
41
+ @@proxy.user, @@proxy.password)
42
+ when ENV["HTTP_PROXY"], ENV["http_proxy"]
43
+ proxy = URI(ENV["HTTP_PROXY"] || ENV["http_proxy"])
44
+ Net::HTTP.new(uri.host, uri.port, proxy.host, proxy.port,
45
+ proxy.user, proxy.password)
46
+ else
47
+ Net::HTTP.new(uri.host, uri.port)
48
+ end
49
+ http.open_timeout = open_timeout if open_timeout # nil by default
50
+ http.read_timeout = read_timeout if read_timeout # 60 by default
51
+ if uri.is_a? URI::HTTPS
52
+ http.use_ssl = true
53
+ http.cert_store = @cert_store
54
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
55
+ end
56
+ http
57
+ rescue => e
58
+ log(:error, e) if @log
59
+ end
60
+
61
+ def req(method, uri, header = {}, credentials = nil)
62
+ accepts = ["*/*"]
63
+ types = { "json" => "application/json", "txt" => "text/plain" }
64
+ ext = uri.path[/[^.]+\z/]
65
+ accepts.unshift types[ext] if types.key?(ext)
66
+ user_agent = "#{self.class}/#{server_version} (#{File.basename(__FILE__)}; net-irc) Ruby/#{RUBY_VERSION} (#{RUBY_PLATFORM})"
67
+
68
+ header["User-Agent"] ||= user_agent
69
+ header["Accept"] ||= accepts.join(",")
70
+ header["Accept-Charset"] ||= "UTF-8,*;q=0.0" if ext != "json"
71
+
72
+ req = case method.to_s.downcase.to_sym
73
+ when :get
74
+ Net::HTTP::Get.new uri.request_uri, header
75
+ when :head
76
+ Net::HTTP::Head.new uri.request_uri, header
77
+ when :post
78
+ Net::HTTP::Post.new uri.path, header
79
+ when :put
80
+ Net::HTTP::Put.new uri.path, header
81
+ when :delete
82
+ Net::HTTP::Delete.new uri.request_uri, header
83
+ else # raise ""
84
+ end
85
+ if req.request_body_permitted?
86
+ req["Content-Type"] ||= "application/x-www-form-urlencoded"
87
+ req.body = uri.query
88
+ end
89
+ req.basic_auth(*credentials) if credentials
90
+ req
91
+ rescue => e
92
+ log(:error, e) if @log
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,7 @@
1
+ require 'atig/ifilter/retweet'
2
+ require 'atig/ifilter/retweet_time'
3
+ require 'atig/ifilter/utf7'
4
+ require 'atig/ifilter/sanitize'
5
+ require 'atig/ifilter/expand_url'
6
+ require 'atig/ifilter/strip'
7
+ require 'atig/ifilter/xid'
@@ -0,0 +1,74 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+
3
+ require 'atig/util'
4
+ require 'atig/http'
5
+ require 'atig/sized_hash'
6
+
7
+ module Atig
8
+ module IFilter
9
+ class ExpandUrl
10
+ include Util
11
+ def initialize(context)
12
+ @log = context.log
13
+ @opts = context.opts
14
+ @http = Atig::Http.new @log
15
+ @cache = Atig::SizedHash.new 100
16
+ end
17
+
18
+ def call(status)
19
+ target = if @opts.untiny_whole_urls then
20
+ URI.regexp(%w[http https])
21
+ else
22
+ %r{
23
+ http:// (?:
24
+ (?: bit\.ly | (?: tin | rub) yurl\.com | j\.mp | t\.co
25
+ | htn.to
26
+ | is\.gd | cli\.gs | tr\.im | u\.nu | airme\.us
27
+ | ff\.im | twurl.nl | bkite\.com | tumblr\.com
28
+ | pic\.gd | sn\.im | digg\.com | goo\.gl)
29
+ / [0-9a-z=-]+ |
30
+ blip\.fm/~ (?> [0-9a-z]+) (?! /) |
31
+ flic\.kr/[a-z0-9/]+
32
+ )
33
+ }ix
34
+ end
35
+
36
+ status.merge :text => status.text.gsub(target) {|url|
37
+ x = @cache[url]
38
+ if x then
39
+ x
40
+ else
41
+ @cache[url] = resolve_http_redirect(URI(url)).to_s || url
42
+ end
43
+ }
44
+ end
45
+
46
+ def resolve_http_redirect(uri, limit = 3)
47
+ return uri if limit.zero? or uri.nil?
48
+ log :debug, uri.inspect
49
+ req = @http.req :head, uri
50
+ @http.http(uri, 3, 2).request(req) do |res|
51
+ break if not res.is_a?(Net::HTTPRedirection) or
52
+ not res.key?("Location")
53
+ begin
54
+ location = URI(res["Location"])
55
+ rescue URI::InvalidURIError
56
+ end
57
+ unless location.is_a? URI::HTTP
58
+ begin
59
+ location = URI.join(uri.to_s, res["Location"])
60
+ rescue URI::InvalidURIError, URI::BadURIError
61
+ # FIXME
62
+ end
63
+ end
64
+ uri = resolve_http_redirect(location, limit - 1)
65
+ end
66
+
67
+ uri
68
+ rescue Errno::ETIMEDOUT, IOError, Timeout::Error, Errno::ECONNRESET => e
69
+ log :error, e.inspect
70
+ uri
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,14 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+
3
+ module Atig
4
+ module IFilter
5
+ module Retweet
6
+ Prefix = "\00310♺ \017"
7
+ def self.call(status)
8
+ return status unless status.retweeted_status
9
+ rt = status.retweeted_status
10
+ status.merge :text => "#{Prefix}RT @#{rt.user.screen_name}: #{rt.text}"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+
3
+ module Atig
4
+ module IFilter
5
+ module RetweetTime
6
+ def self.call(status)
7
+ unless status.retweeted_status then
8
+ status
9
+ else
10
+ t = Time.gm(*Time.parse(status.retweeted_status.created_at).to_a)
11
+ status.merge :text => "#{status.text} \x0310[#{t.strftime "%Y-%m-%d %H:%M"}]\x0F"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+
3
+ module Atig
4
+ module IFilter
5
+ WSP_REGEX = Regexp.new("\\r\\n|[\\r\\n\\t#{"\\u00A0\\u1680\\u180E\\u2002-\\u200D\\u202F\\u205F\\u2060\\uFEFF" if "\u0000" == "\000"}]")
6
+
7
+ Sanitize = lambda{|status|
8
+ text = status.text.
9
+ delete("\000\001").
10
+ gsub(">", ">").
11
+ gsub(""", '"').
12
+ gsub("&lt;", "<").
13
+ gsub(WSP_REGEX, " ")
14
+ status.merge :text => text
15
+ }
16
+ end
17
+ end
18
+
@@ -0,0 +1,15 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+
3
+ module Atig
4
+ module IFilter
5
+ class Strip
6
+ def initialize(suffix=[])
7
+ @rsuffix = /#{Regexp.union(*suffix)}\z/
8
+ end
9
+
10
+ def call(status)
11
+ status.merge :text => status.text.sub(@rsuffix, "").strip
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+
3
+ require 'atig/util'
4
+ require "iconv"
5
+
6
+ module Atig
7
+ module IFilter
8
+ class Utf7
9
+ include Util
10
+ def initialize(context)
11
+ @log = context.log
12
+ end
13
+
14
+ def call(status)
15
+ return status unless defined? ::Iconv and status.text.include?("+")
16
+
17
+ status.merge :text => status.text.sub(/\A(?:.+ > |.+\z)/) { Iconv.iconv("UTF-8", "UTF-7", $&).join }
18
+ rescue Iconv::IllegalSequence
19
+ status
20
+ rescue => e
21
+ log :error,e
22
+ status
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+
2
+ module Atig
3
+ module IFilter
4
+ class Xid
5
+ def initialize(context)
6
+ @opts = context.opts
7
+ c = @opts.send name # expect: 0..15, true, "0,1"
8
+ b = nil
9
+ c, b = c.split(",", 2).map {|i| i.to_i } if c.respond_to? :split
10
+ c = 10 unless (0 .. 15).include? c # 10: teal
11
+ if (0 .. 15).include?(b)
12
+ @format = "\003%.2d,%.2d[%%s]\017" % [c, b]
13
+ else
14
+ @format = "\003%.2d[%%s]\017" % c
15
+ end
16
+ end
17
+
18
+ def call(status)
19
+ xid = status.send name
20
+ unless xid and @opts.send(name)
21
+ status
22
+ else
23
+ status.merge :text => "#{status.text} #{@format % xid}"
24
+ end
25
+ end
26
+ end
27
+
28
+ class Sid < Xid
29
+ def name; :sid end
30
+ end
31
+
32
+ class Tid < Xid
33
+ def name; :tid end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,49 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+ # http://subtech.g.hatena.ne.jp/cho45/20091008/1254934083
3
+
4
+ module Atig
5
+ module Levenshtein
6
+ def levenshtein(a, b)
7
+ PureRuby.levenshtein(a, b)
8
+ end
9
+ module_function :levenshtein
10
+
11
+ module PureRuby
12
+ def levenshtein(a, b)
13
+ case
14
+ when a.empty?
15
+ b.length
16
+ when b.empty?
17
+ a.length
18
+ else
19
+ d = Array.new(a.length + 1) { |s|
20
+ Array.new(b.length + 1, 0)
21
+ }
22
+
23
+ (0..a.length).each do |i|
24
+ d[i][0] = i
25
+ end
26
+
27
+ (0..b.length).each do |j|
28
+ d[0][j] = j
29
+ end
30
+
31
+ (1..a.length).each do |i|
32
+ (1..b.length).each do |j|
33
+ cost = (a[i - 1] == b[j - 1]) ? 0 : 1
34
+ d[i][j] = [
35
+ d[i-1][j ] + 1,
36
+ d[i ][j-1] + 1,
37
+ d[i-1][j-1] + cost
38
+ ].min
39
+ end
40
+ end
41
+
42
+ d[a.length][b.length]
43
+ end
44
+ end
45
+
46
+ module_function :levenshtein
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,4 @@
1
+ # monkey hack
2
+ module Net::IRC
3
+ module_function :low_quote, :low_dequote
4
+ end
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+ if defined? ::Encoding
3
+ # エンコーディングの違いのせいで、
4
+ # 日本語の文字列をpostパラメータに含めようとするとエラーが出ます。
5
+ # 無理矢理エンコーディングをUTF-8に変えて再試行することで回避。
6
+ module OAuth
7
+ module Helper
8
+ def escape(value)
9
+ begin
10
+ URI::escape(value.to_s, OAuth::RESERVED_CHARACTERS)
11
+ rescue ArgumentError
12
+ URI::escape(
13
+ value.to_s.force_encoding(Encoding::UTF_8),
14
+ OAuth::RESERVED_CHARACTERS
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ # 1.9から文字列がEnumerableでなくなりましたので、
22
+ # その対応をしています。
23
+ module HMAC
24
+ class Base
25
+ def set_key(key)
26
+ key = @algorithm.digest(key) if key.size > @block_size
27
+ key_xor_ipad = Array.new(@block_size, 0x36)
28
+ key_xor_opad = Array.new(@block_size, 0x5c)
29
+ key.bytes.each_with_index do |value, index|
30
+ key_xor_ipad[index] ^= value
31
+ key_xor_opad[index] ^= value
32
+ end
33
+ @key_xor_ipad = key_xor_ipad.pack('c*')
34
+ @key_xor_opad = key_xor_opad.pack('c*')
35
+ @md = @algorithm.new
36
+ @initialized = true
37
+ end
38
+ end
39
+ end
40
+ end
data/lib/atig/oauth.rb ADDED
@@ -0,0 +1,55 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+ require 'atig/oauth-patch'
3
+
4
+ module Atig
5
+ class OAuth
6
+ CONSUMER_KEY = 'TO9wbD379qmFSJp6pFs5w'
7
+ CONSUMER_SECRET = 'Gap8ishP3J3JrjH4JEspcii4poiZgMowHRazWGM1cYg'
8
+
9
+ @@profiles = {}
10
+ class << self
11
+ def dump
12
+ @@profiles
13
+ end
14
+
15
+ def load(profiles)
16
+ @@profiles = profiles
17
+ end
18
+ end
19
+
20
+ attr_reader :access
21
+ def initialize(context, nick)
22
+ uri = URI(context.opts.api_base)
23
+ site = "http://#{uri.host}"
24
+
25
+ @nick = nick
26
+ @oauth = ::OAuth::Consumer.new(CONSUMER_KEY, CONSUMER_SECRET, {
27
+ :site => site,
28
+ :proxy => ENV["HTTP_PROXY"] || ENV["http_proxy"]
29
+ })
30
+
31
+ if @@profiles.key? @nick
32
+ token,secret = @@profiles[@nick]
33
+ @access = ::OAuth::AccessToken.new(@oauth, token, secret)
34
+ end
35
+ end
36
+
37
+ def verified?
38
+ @access != nil
39
+ end
40
+
41
+ def url
42
+ @request = @oauth.get_request_token
43
+ @request.authorize_url
44
+ end
45
+
46
+ def verify(code)
47
+ @access = @request.get_access_token(:oauth_verifier => code)
48
+ if @access then
49
+ @@profiles[@nick] = [ @access.token , @access.secret ]
50
+ end
51
+ rescue
52
+ false
53
+ end
54
+ end
55
+ end