atig 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/Gemfile +3 -0
- data/README.mkdn +52 -0
- data/Rakefile +15 -0
- data/atig.gemspec +25 -0
- data/bin/atig +74 -0
- data/docs/OMakefile +32 -0
- data/docs/OMakeroot +45 -0
- data/docs/_static/allow.png +0 -0
- data/docs/_static/emacs.png +0 -0
- data/docs/_static/irc_setting.png +0 -0
- data/docs/_static/irssi.png +0 -0
- data/docs/_static/limechat.png +0 -0
- data/docs/_static/limechat_s.png +0 -0
- data/docs/_static/oauth_channel.png +0 -0
- data/docs/_static/screenshot.png +0 -0
- data/docs/_static/structure.png +0 -0
- data/docs/_static/verify.png +0 -0
- data/docs/changelog.rst +96 -0
- data/docs/commandline_options.rst +21 -0
- data/docs/commands.rst +84 -0
- data/docs/conf.py +194 -0
- data/docs/config.rst +159 -0
- data/docs/feature.rst +41 -0
- data/docs/graphics.graffle +1995 -0
- data/docs/hacking_guide.rst +43 -0
- data/docs/index.rst +109 -0
- data/docs/irc.rst +31 -0
- data/docs/options.rst +75 -0
- data/docs/quickstart.rst +89 -0
- data/docs/resize.sh +7 -0
- data/docs/tiarra.rst +2 -0
- data/docs/tig.rst +21 -0
- data/lib/atig.rb +19 -0
- data/lib/atig/agent.rb +8 -0
- data/lib/atig/agent/agent.rb +38 -0
- data/lib/atig/agent/clenup.rb +23 -0
- data/lib/atig/agent/dm.rb +35 -0
- data/lib/atig/agent/following.rb +45 -0
- data/lib/atig/agent/full_list.rb +20 -0
- data/lib/atig/agent/list.rb +55 -0
- data/lib/atig/agent/list_status.rb +46 -0
- data/lib/atig/agent/mention.rb +13 -0
- data/lib/atig/agent/other_list.rb +18 -0
- data/lib/atig/agent/own_list.rb +18 -0
- data/lib/atig/agent/stream_follow.rb +38 -0
- data/lib/atig/agent/timeline.rb +13 -0
- data/lib/atig/agent/user_stream.rb +31 -0
- data/lib/atig/basic_twitter.rb +116 -0
- data/lib/atig/bitly.rb +52 -0
- data/lib/atig/channel.rb +5 -0
- data/lib/atig/channel/channel.rb +17 -0
- data/lib/atig/channel/dm.rb +14 -0
- data/lib/atig/channel/list.rb +76 -0
- data/lib/atig/channel/mention.rb +20 -0
- data/lib/atig/channel/retweet.rb +28 -0
- data/lib/atig/channel/timeline.rb +74 -0
- data/lib/atig/command.rb +21 -0
- data/lib/atig/command/autofix.rb +58 -0
- data/lib/atig/command/command.rb +24 -0
- data/lib/atig/command/command_helper.rb +95 -0
- data/lib/atig/command/destroy.rb +44 -0
- data/lib/atig/command/dm.rb +31 -0
- data/lib/atig/command/favorite.rb +27 -0
- data/lib/atig/command/info.rb +50 -0
- data/lib/atig/command/limit.rb +15 -0
- data/lib/atig/command/location.rb +23 -0
- data/lib/atig/command/name.rb +18 -0
- data/lib/atig/command/option.rb +37 -0
- data/lib/atig/command/refresh.rb +18 -0
- data/lib/atig/command/reply.rb +37 -0
- data/lib/atig/command/retweet.rb +63 -0
- data/lib/atig/command/search.rb +51 -0
- data/lib/atig/command/spam.rb +26 -0
- data/lib/atig/command/status.rb +41 -0
- data/lib/atig/command/thread.rb +44 -0
- data/lib/atig/command/time.rb +32 -0
- data/lib/atig/command/uptime.rb +32 -0
- data/lib/atig/command/user.rb +42 -0
- data/lib/atig/command/user_info.rb +27 -0
- data/lib/atig/command/version.rb +49 -0
- data/lib/atig/command/whois.rb +39 -0
- data/lib/atig/db/db.rb +60 -0
- data/lib/atig/db/followings.rb +131 -0
- data/lib/atig/db/listenable.rb +22 -0
- data/lib/atig/db/lists.rb +76 -0
- data/lib/atig/db/roman.rb +30 -0
- data/lib/atig/db/sized_uniq_array.rb +62 -0
- data/lib/atig/db/sql.rb +35 -0
- data/lib/atig/db/statuses.rb +147 -0
- data/lib/atig/db/transaction.rb +47 -0
- data/lib/atig/exception_util.rb +26 -0
- data/lib/atig/gateway.rb +62 -0
- data/lib/atig/gateway/channel.rb +99 -0
- data/lib/atig/gateway/session.rb +326 -0
- data/lib/atig/http.rb +95 -0
- data/lib/atig/ifilter.rb +7 -0
- data/lib/atig/ifilter/expand_url.rb +74 -0
- data/lib/atig/ifilter/retweet.rb +14 -0
- data/lib/atig/ifilter/retweet_time.rb +16 -0
- data/lib/atig/ifilter/sanitize.rb +18 -0
- data/lib/atig/ifilter/strip.rb +15 -0
- data/lib/atig/ifilter/utf7.rb +26 -0
- data/lib/atig/ifilter/xid.rb +36 -0
- data/lib/atig/levenshtein.rb +49 -0
- data/lib/atig/monkey.rb +4 -0
- data/lib/atig/oauth-patch.rb +40 -0
- data/lib/atig/oauth.rb +55 -0
- data/lib/atig/ofilter.rb +4 -0
- data/lib/atig/ofilter/escape_url.rb +102 -0
- data/lib/atig/ofilter/footer.rb +20 -0
- data/lib/atig/ofilter/geo.rb +17 -0
- data/lib/atig/ofilter/short_url.rb +47 -0
- data/lib/atig/option.rb +90 -0
- data/lib/atig/scheduler.rb +79 -0
- data/lib/atig/search.rb +22 -0
- data/lib/atig/search_twitter.rb +21 -0
- data/lib/atig/sized_hash.rb +33 -0
- data/lib/atig/stream.rb +66 -0
- data/lib/atig/twitter.rb +79 -0
- data/lib/atig/twitter_struct.rb +63 -0
- data/lib/atig/unu.rb +27 -0
- data/lib/atig/update_checker.rb +53 -0
- data/lib/atig/url_escape.rb +62 -0
- data/lib/atig/util.rb +16 -0
- data/lib/atig/version.rb +3 -0
- data/lib/memory_profiler.rb +77 -0
- data/spec/command/autofix_spec.rb +35 -0
- data/spec/command/destroy_spec.rb +98 -0
- data/spec/command/dm_spec.rb +28 -0
- data/spec/command/favorite_spec.rb +55 -0
- data/spec/command/limit_spec.rb +27 -0
- data/spec/command/location_spec.rb +25 -0
- data/spec/command/name_spec.rb +19 -0
- data/spec/command/option_spec.rb +133 -0
- data/spec/command/refresh_spec.rb +22 -0
- data/spec/command/reply_spec.rb +79 -0
- data/spec/command/retweet_spec.rb +66 -0
- data/spec/command/spam_spec.rb +27 -0
- data/spec/command/status_spec.rb +44 -0
- data/spec/command/thread_spec.rb +91 -0
- data/spec/command/time_spec.rb +52 -0
- data/spec/command/uptime_spec.rb +55 -0
- data/spec/command/user_info_spec.rb +42 -0
- data/spec/command/user_spec.rb +50 -0
- data/spec/command/version_spec.rb +67 -0
- data/spec/command/whois_spec.rb +78 -0
- data/spec/db/followings_spec.rb +100 -0
- data/spec/db/listenable_spec.rb +32 -0
- data/spec/db/lists_spec.rb +104 -0
- data/spec/db/roman_spec.rb +17 -0
- data/spec/db/sized_uniq_array_spec.rb +63 -0
- data/spec/db/statuses_spec.rb +180 -0
- data/spec/ifilter/expand_url_spec.rb +44 -0
- data/spec/ifilter/retweet_spec.rb +28 -0
- data/spec/ifilter/retweet_time_spec.rb +25 -0
- data/spec/ifilter/sanitize_spec.rb +25 -0
- data/spec/ifilter/sid_spec.rb +29 -0
- data/spec/ifilter/strip_spec.rb +23 -0
- data/spec/ifilter/tid_spec.rb +29 -0
- data/spec/ifilter/utf7_spec.rb +30 -0
- data/spec/levenshtein_spec.rb +24 -0
- data/spec/ofilter/escape_url_spec.rb +50 -0
- data/spec/ofilter/footer_spec.rb +32 -0
- data/spec/ofilter/geo_spec.rb +33 -0
- data/spec/ofilter/short_url_spec.rb +127 -0
- data/spec/option_spec.rb +91 -0
- data/spec/sized_hash_spec.rb +45 -0
- data/spec/spec_helper.rb +35 -0
- data/spec/update_checker_spec.rb +55 -0
- 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
|
data/lib/atig/ifilter.rb
ADDED
@@ -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("<", "<").
|
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
|
data/lib/atig/monkey.rb
ADDED
@@ -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
|