1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
# -*- coding: utf-8 -*-
require 'cgi'
class Bitly < MessageConverters
USER = 'mikutter'
APIKEY = 'R_70170ccac1099f3ae1818af3fa7bb311'
def initialize
# bit.lyの一度のリクエストでexpandできる最大数は15
# http://code.google.com/p/bitly-api/wiki/ApiDocumentation#/v3/expand
@expand_queue = TimeLimitedQueue.new(15, 0.1, Set){ |set|
Thread.new{
begin
expanded_urls = expand_url_many(set)
if expanded_urls.is_a? Enumerable
expanded_urls.each{ |pair|
shrinked, expanded = pair
ew_proc = @expand_waiting[shrinked]
if ew_proc.respond_to? :call
atomic{
ew_proc.call(expanded)
@expand_waiting.delete(shrinked) } end } end
rescue Exception => e
set.to_a.each{ |url|
ew_proc = @expand_waiting[shrinked]
if ew_proc.respond_to? :call
atomic {
ew_proc.call(url)
@expand_waiting.delete(url) } end } end } }
@expand_waiting = Hash.new # { url => Proc(url) }
end
def plugin_name
:bitly
end
# bitlyユーザ名を返す
def user
if UserConfig[:bitly_user] == '' or not UserConfig[:bitly_user]
USER
else
UserConfig[:bitly_user]
end end
# bitly API keyを返す
def apikey
if UserConfig[:bitly_apikey] == '' or not UserConfig[:bitly_apikey]
APIKEY
else
UserConfig[:bitly_apikey]
end end
# 引数urlがこのプラグインで短縮されているものならtrueを返す
def shrinked_url?(url)
url.is_a? String and Regexp.new('^http://(bit\\.ly|j\\.mp)/') === url end
# urlの配列 urls を受け取り、それら全てを短縮して返す
def shrink_url(url)
query = "login=#{user}&apiKey=#{apikey}&longUrl=#{CGI.escape(url)}"
3.times{
response = begin
JSON.parse(Net::HTTP.get("api.bit.ly", "/v3/shorten?#{query}"))
rescue Exception
nil end
if response and response['status_code'].to_i == 200
return response['data']['url'] end
sleep(1) }
nil end
# 短縮されたURL url を受け取り、それら全てを展開して返す。
def expand_url(url)
return nil unless shrinked_url? url
url.freeze
stopper = Queue.new
atomic{
if(@expand_waiting[url])
parent = @expand_waiting[url]
@expand_waiting[url] = lambda{ |url| parent.call(url); stopper << url }
else
@expand_waiting[url] = lambda{ |url| stopper << url }
end
@expand_queue.push(url) }
timeout(5){ stopper.pop }
rescue Exception => e
error e
url end
def expand_url_many(urls)
notice urls
urls = urls.select &method(:shrinked_url?)
return nil if urls.empty?
query = "login=#{user}&apiKey=#{apikey}&" + urls.map{ |url|
"shortUrl=#{CGI.escape(url)}" }.join('&')
3.times{
result = begin
JSON.parse(Net::HTTP.get("api.bit.ly", "/v3/expand?#{query}"))
rescue Exception
nil end
if result and result['status_code'].to_i == 200
return Hash[ *result['data']['expand'].map{|token|
[token['short_url'], token['long_url']] }.flatten ] end
sleep(1) }
nil end
regist
end
|