diff --git a/lib/oneboxer/twitter_onebox.rb b/lib/oneboxer/twitter_onebox.rb
index a0a292e6a..aef467a58 100644
--- a/lib/oneboxer/twitter_onebox.rb
+++ b/lib/oneboxer/twitter_onebox.rb
@@ -1,4 +1,5 @@
require_dependency 'oneboxer/handlebars_onebox'
+require_dependency 'twitter_api'
module Oneboxer
class TwitterOnebox < HandlebarsOnebox
@@ -17,9 +18,10 @@ module Oneboxer
favicon 'twitter.png'
def fetch_html
- raise Discourse::SiteSettingMissing if twitter_credentials_missing?
+ raise Discourse::SiteSettingMissing if TwitterApi.twitter_credentials_missing?
- tweet_for @url.match(REGEX)[:id]
+ # a bit odd, but I think the api expects html
+ TwitterApi.raw_tweet_for(@url.match(REGEX)[:id])
end
def parse(data)
@@ -28,103 +30,10 @@ module Oneboxer
result['created_at'] =
Time.parse(result['created_at']).strftime("%I:%M%p - %d %b %y")
- result['text'] = link_all_the_things_in result['text']
+ result['text'] = TwitterApi.prettify_tweet(result)
result
end
- private
-
- def link_all_the_things_in(text)
- link_hashtags_in link_handles_in link_urls_in(text)
- end
-
- def link_urls_in(text)
- URI.extract(text, %w(http https)).each do |url|
- text.gsub!(url, "#{url}")
- end
-
- text
- end
-
- def link_handles_in(text)
- text.scan(/\s@(\w+)/).flatten.uniq.each do |handle|
- text.gsub!("@#{handle}", [
- "",
- "@#{handle}",
- ""
- ].join)
- end
-
- text
- end
-
- def link_hashtags_in(text)
- text.scan(/\s#(\w+)/).flatten.uniq.each do |hashtag|
- text.gsub!("##{hashtag}", [
- "",
- "##{hashtag}",
- ""
- ].join)
- end
-
- text
- end
-
- 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
diff --git a/lib/twitter_api.rb b/lib/twitter_api.rb
new file mode 100644
index 000000000..8b5cac53a
--- /dev/null
+++ b/lib/twitter_api.rb
@@ -0,0 +1,123 @@
+# lightweight Twitter api calls
+require_dependency 'rinku'
+
+class TwitterApi
+
+ class << self
+
+ def prettify_tweet(tweet)
+ text = tweet["text"].dup
+ if entities = tweet["entities"] and urls = entities["urls"]
+ urls.each do |url|
+ text.gsub!(url["url"], "#{url["display_url"]}")
+ end
+ end
+
+ text = link_hashtags_in link_handles_in text
+
+ Rinku.auto_link(text, :all, 'target="_blank"').to_s
+ end
+
+ def user_timeline(screen_name)
+ JSON.parse(twitter_get(user_timeline_uri_for screen_name))
+ end
+
+ def tweet_for(id)
+ JSON.parse(twitter_get(tweet_uri_for id))
+ end
+
+ def raw_tweet_for(id)
+ twitter_get(tweet_uri_for id)
+ end
+
+ def twitter_credentials_missing?
+ consumer_key.blank? || consumer_secret.blank?
+ end
+
+ protected
+
+ def link_handles_in(text)
+ text.scan(/\s@(\w+)/).flatten.uniq.each do |handle|
+ text.gsub!("@#{handle}", [
+ "",
+ "@#{handle}",
+ ""
+ ].join)
+ end
+
+ text
+ end
+
+ def link_hashtags_in(text)
+ text.scan(/\s#(\w+)/).flatten.uniq.each do |hashtag|
+ text.gsub!("##{hashtag}", [
+ "",
+ "##{hashtag}",
+ ""
+ ].join)
+ end
+
+ text
+ end
+
+ def user_timeline_uri_for(screen_name)
+ URI.parse "#{BASE_URL}/1.1/statuses/user_timeline.json?screen_name=#{screen_name}&count=50&include_rts=false&exclude_replies=true"
+ end
+
+ def tweet_uri_for(id)
+ URI.parse "#{BASE_URL}/1.1/statuses/show.json?id=#{id}"
+ end
+
+ unless defined? BASE_URL
+ BASE_URL = 'https://api.twitter.com'.freeze
+ end
+
+ def twitter_get(uri)
+ request = Net::HTTP::Get.new(uri)
+ request.add_field 'Authorization', "Bearer #{bearer_token}"
+ http(uri).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 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
+
+ end
+end
diff --git a/spec/components/oneboxer/twitter_onebox_spec.rb b/spec/components/oneboxer/twitter_onebox_spec.rb
index e0e8d1276..b65e2d739 100644
--- a/spec/components/oneboxer/twitter_onebox_spec.rb
+++ b/spec/components/oneboxer/twitter_onebox_spec.rb
@@ -19,7 +19,7 @@ describe Oneboxer::TwitterOnebox do
it 'wraps eack url in a link' do
expect(subject.parse(data)['text']).to eq([
"Twitter ",
- "",
+ '',
"http://twitter.com",
""
].join)