mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
prettier twitter links, extracted mini api
This commit is contained in:
parent
6ab740aa1c
commit
172a85ae14
@ -1,4 +1,5 @@
|
|||||||
require_dependency 'oneboxer/handlebars_onebox'
|
require_dependency 'oneboxer/handlebars_onebox'
|
||||||
|
require_dependency 'twitter_api'
|
||||||
|
|
||||||
module Oneboxer
|
module Oneboxer
|
||||||
class TwitterOnebox < HandlebarsOnebox
|
class TwitterOnebox < HandlebarsOnebox
|
||||||
@ -17,9 +18,10 @@ module Oneboxer
|
|||||||
favicon 'twitter.png'
|
favicon 'twitter.png'
|
||||||
|
|
||||||
def fetch_html
|
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
|
end
|
||||||
|
|
||||||
def parse(data)
|
def parse(data)
|
||||||
@ -28,103 +30,10 @@ module Oneboxer
|
|||||||
result['created_at'] =
|
result['created_at'] =
|
||||||
Time.parse(result['created_at']).strftime("%I:%M%p - %d %b %y")
|
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
|
result
|
||||||
end
|
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, "<a href='#{url}' target='_blank'>#{url}</a>")
|
|
||||||
end
|
|
||||||
|
|
||||||
text
|
|
||||||
end
|
|
||||||
|
|
||||||
def link_handles_in(text)
|
|
||||||
text.scan(/\s@(\w+)/).flatten.uniq.each do |handle|
|
|
||||||
text.gsub!("@#{handle}", [
|
|
||||||
"<a href='https://twitter.com/#{handle}' target='_blank'>",
|
|
||||||
"@#{handle}",
|
|
||||||
"</a>"
|
|
||||||
].join)
|
|
||||||
end
|
|
||||||
|
|
||||||
text
|
|
||||||
end
|
|
||||||
|
|
||||||
def link_hashtags_in(text)
|
|
||||||
text.scan(/\s#(\w+)/).flatten.uniq.each do |hashtag|
|
|
||||||
text.gsub!("##{hashtag}", [
|
|
||||||
"<a href='https://twitter.com/search?q=%23#{hashtag}' ",
|
|
||||||
"target='_blank'>",
|
|
||||||
"##{hashtag}",
|
|
||||||
"</a>"
|
|
||||||
].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
|
||||||
end
|
end
|
||||||
|
123
lib/twitter_api.rb
Normal file
123
lib/twitter_api.rb
Normal file
@ -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"], "<a target='_blank' href='#{url["expanded_url"]}'>#{url["display_url"]}</a>")
|
||||||
|
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}", [
|
||||||
|
"<a href='https://twitter.com/#{handle}' target='_blank'>",
|
||||||
|
"@#{handle}",
|
||||||
|
"</a>"
|
||||||
|
].join)
|
||||||
|
end
|
||||||
|
|
||||||
|
text
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_hashtags_in(text)
|
||||||
|
text.scan(/\s#(\w+)/).flatten.uniq.each do |hashtag|
|
||||||
|
text.gsub!("##{hashtag}", [
|
||||||
|
"<a href='https://twitter.com/search?q=%23#{hashtag}' ",
|
||||||
|
"target='_blank'>",
|
||||||
|
"##{hashtag}",
|
||||||
|
"</a>"
|
||||||
|
].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
|
@ -19,7 +19,7 @@ describe Oneboxer::TwitterOnebox do
|
|||||||
it 'wraps eack url in a link' do
|
it 'wraps eack url in a link' do
|
||||||
expect(subject.parse(data)['text']).to eq([
|
expect(subject.parse(data)['text']).to eq([
|
||||||
"Twitter ",
|
"Twitter ",
|
||||||
"<a href='http://twitter.com' target='_blank'>",
|
'<a href="http://twitter.com" target="_blank">',
|
||||||
"http://twitter.com",
|
"http://twitter.com",
|
||||||
"</a>"
|
"</a>"
|
||||||
].join)
|
].join)
|
||||||
|
Loading…
Reference in New Issue
Block a user