diff --git a/lib/oneboxer/templates/twitter_onebox.hbrs b/lib/oneboxer/templates/twitter_onebox.hbrs index e53e550facb..6dbabe47210 100644 --- a/lib/oneboxer/templates/twitter_onebox.hbrs +++ b/lib/oneboxer/templates/twitter_onebox.hbrs @@ -8,9 +8,15 @@ {{/host}} +
- {{#user.profile_image_url}}{{/user.profile_image_url}} -

@{{user.screen_name}}

+ {{#user.profile_image_url}} + {{/user.profile_image_url}} +

+ + @{{user.screen_name}} + +

{{{text}}} @@ -18,7 +24,5 @@ {{created_at}}
-
- diff --git a/lib/oneboxer/twitter_onebox.rb b/lib/oneboxer/twitter_onebox.rb index 66fde0e2996..b242d976fc4 100644 --- a/lib/oneboxer/twitter_onebox.rb +++ b/lib/oneboxer/twitter_onebox.rb @@ -1,33 +1,29 @@ -# TODO implement per: http://meta.discourse.org/t/twitter-oneboxes-are-bust/7410/3 require_dependency 'oneboxer/handlebars_onebox' module Oneboxer class TwitterOnebox < HandlebarsOnebox + BASE_URL = 'https://api.twitter.com'.freeze - REGEX = /^https?:\/\/(?:www\.)?twitter.com\/(?[^\/]+)\/status\/(?\d+)$/ - # matcher REGEX + REGEX = + /^https?:\/\/(?:www\.)?twitter.com\/(?[^\/]+)\/status\/(?\d+)$/ + + matcher REGEX # TODO: use zocial instead favicon 'twitter.png' def fetch_html - m = @url.match(REGEX) + raise Discourse::SiteSettingMissing if twitter_credentials_missing? - if SiteSetting.twitter_consumer_key.present? && SiteSetting.twitter_consumer_secret.present? - token = prepare_access_token(SiteSetting.twitter_consumer_key, SiteSetting.twitter_consumer_secret) - token.request(:get, "https://api.twitter.com/1.1/statuses/show/#{URI::encode(m[:id])}.json") - else - # perhaps? - raise Discourse::SiteSettingMissing - end + tweet_for @url.match(REGEX)[:id] end def parse(data) result = JSON.parse(data) - result["created_at"] = Time.parse(result["created_at"]).strftime("%I:%M%p - %d %b %y") + result['created_at'] = + Time.parse(result['created_at']).strftime("%I:%M%p - %d %b %y") - # Hyperlink URLs URI.extract(result['text'], %w(http https)).each do |url| result['text'].gsub!(url, "#{url}") end @@ -35,13 +31,61 @@ module Oneboxer result end - protected + private - def get_message_json(consumer_key, consumer_secret) - raise "NOT IMPLEMENTED" - # implement per http://meta.discourse.org/t/twitter-oneboxes-are-bust/7410/3 + def tweet_for(id) + request = Net::HTTP::Get.new(tweet_uri_for id) + + request.add_field 'Authorization', "Bearer #{bearer_token}" + + http(tweet_uri_for id).request(request).body end + def authorization + request = Net::HTTP::Post.new(auth_uri) + request.add_field 'Authorization', + "Basic #{bearer_token_credentials}" + request.add_field 'Content-Type', + 'application/x-www-form-urlencoded;charset=UTF-8' + + request.set_form_data 'grant_type' => 'client_credentials' + + http(auth_uri).request(request).body + end + + def bearer_token + @access_token ||= JSON.parse(authorization).fetch('access_token') + end + + def bearer_token_credentials + Base64.strict_encode64( + "#{URI::encode(consumer_key)}:#{URI::encode(consumer_secret)}" + ) + end + + def auth_uri + URI.parse "#{BASE_URL}/oauth2/token" + end + + def tweet_uri_for(id) + URI.parse "#{BASE_URL}/1.1/statuses/show.json?id=#{id}" + end + + def http(uri) + Net::HTTP.new(uri.host, uri.port).tap { |http| http.use_ssl = true } + end + + def consumer_key + SiteSetting.twitter_consumer_key + end + + def consumer_secret + SiteSetting.twitter_consumer_secret + end + + def twitter_credentials_missing? + consumer_key.blank? || consumer_secret.blank? + end end end