# -*- coding: utf-8 -*- # # tweet_quote.rb - tDiary plugin to quote tweet on twitter.com, # formaly known as blackbird-pie.rb # # Copyright (C) 2010, hb # # usage: # <%= tweet_quote "id|url" %> # or # <%= twitter_quote "id|url" %> # or # <%= blackbird_pie "id|url" %> # or # <%= bbp "id|url" %> # require 'pstore' require 'open-uri' require 'timeout' require 'time' require 'uri' require 'openssl' require 'json' def twitter_quote_option_keys %w( oauth_consumer_key oauth_consumer_secret oauth_token oauth_token_secret render_method ).map{|k| "twitter_quote.#{k}" } end def twitter_statuses_show_api( tweet_id ) url = "https://api.twitter.com/1.1/statuses/show.json" unsafe = /[^a-zA-Z0-9\-\.\_\~]/ parameters = { :id => tweet_id } oauth_parameters = { :oauth_consumer_key => @conf["twitter_quote.oauth_consumer_key"], :oauth_nonce => OpenSSL::Digest.hexdigest( "MD5", "#{Time.now.to_f}#{rand}" ), :oauth_signature_method => "HMAC-SHA1", :oauth_timestamp => Time.now.to_i.to_s, :oauth_token => @conf["twitter_quote.oauth_token"], :oauth_version => "1.0" } data = "GET&#{URI.escape( url, unsafe )}&" data << URI.escape( oauth_parameters.merge( parameters ).sort.map{|k, v| "#{k}=#{v}" }.join( "&" ), unsafe ) oauth_parameters[:oauth_signature] = [OpenSSL::HMAC.digest( OpenSSL::Digest::SHA1.new, URI.escape( "#{@conf["twitter_quote.oauth_consumer_secret"]}&#{@conf["twitter_quote.oauth_token_secret"]}" ), data )].pack( "m" ).chomp proxy = @conf['proxy'] proxy = 'http://' + proxy if proxy headers = { "Authorization" => %Q[OAuth #{oauth_parameters.map{|k ,v| "#{URI.escape( k.to_s, unsafe )}=\"#{URI.escape( v, unsafe )}\""}.join( "," )}], :proxy => proxy } Timeout.timeout( 20 ) do open( "#{url}?#{parameters.map{|k,v| "#{k}=#{v}"}.join( "&" )}", headers ) {|f| f.read } end end def render_widget(tweet_id, screen_name, name, background_url, profile_backgound_color, avatar, source, timestamp, content) <<-HTML

#{content}

— #{@name} (#{@screen_name}) #{timestamp}
HTML end def render_bbp(tweet_id, screen_name, name, background_url, profile_backgound_color, avatar, source, timestamp, content) <<-HTML

#{content} #{timestamp} Reply Retweet Favorite

HTML end def twitter_status_json_to_html( json ) tweet_id = json['id_str'] screen_name = json['user']['screen_name'] name = json['user']['name'] background_url = json['user']['profile_background_image_url'] profile_background_color = "##{json['user']['profile_background_color']}" avatar = json['user']['profile_image_url'] source = json['source'] timestamp = Time.parse( json['created_at'] ) content = json['text'] content.gsub!( URI.regexp( %w|http https| ) ){ %Q|#{$&}| } content = content.split( /(<[^>]*>)/ ).map {|s| next s if s[/\A([a-zA-Z0-9_]{1,15}))(?![a-zA-Z0-9_])/ ){ %Q|#{$&}| } s.gsub( /#([a-zA-Z0-9]{1,16})/ ){ %Q|#{$&}| } }.join if @conf['twitter_quote.render_method'] == 'widget' render_widget(tweet_id, screen_name, name, background_url, profile_backgound_color, avatar, source, timestamp, content) else render_bbp(tweet_id, screen_name, name, background_url, profile_backgound_color, avatar, source, timestamp, content) end end def tweet_quote( src ) return unless twitter_quote_option_keys.all?{|v| @options.key? v } if %r|http(?:s)?://twitter.com/(?:#!/)?[^/]{1,15}/status(?:es)?/([0-9]+)| =~ src.to_s.downcase src = $1 end return unless /\A[0-9]+\z/ =~ src.to_s cache = "#{@cache_path}/tweet_quote.pstore" json = nil db = PStore.new( cache ) db.transaction do key = src db[key] ||= {} if db[key][:json] && /\A(?:latest|day|month|nyear)\z/ =~ @mode json = db[key][:json] else begin json = twitter_statuses_show_api( src ) rescue OpenURI::HTTPError return %Q|

#$!

| end db[key][:json] = json end end twitter_status_json_to_html( JSON.parse( json ) ) end add_conf_proc( 'twitter_quote', 'Embedded Tweets' ) do if @mode == 'saveconf' twitter_quote_option_keys.each do |k| @conf[k] = @cgi.params[k][0] end end <<-HTML

Twitter OAuth settings

Consumer key

Consumer secret

Your access token

Access token

Access token secret

Render method

HTML end alias :blackbird_pie :tweet_quote alias :bbp :tweet_quote alias :twitter_quote :tweet_quote