diff --git a/app/presenters/tweet/html_presenter.rb b/app/presenters/tweet/html_presenter.rb index c7282cc..870b197 100644 --- a/app/presenters/tweet/html_presenter.rb +++ b/app/presenters/tweet/html_presenter.rb @@ -13,7 +13,20 @@ def text buffer = ActiveSupport::SafeBuffer.new buffer << tweet.tweet_text + # make links anchors + buffer = buffer.gsub(/(https?[^\s]+)/o) do |url| + require Rails.root.join('lib/expand_url') + begin + expanded_url = ExpandUrl.expand_url(url) + rescue ExpandUrl::ExpansionError => e + STDERR.puts "#{e.class}: failed expanding #{url.inspect}" + expanded_url = url + end + %Q(#{url}) + end + # link hashtags buffer.gsub! /#(\w+)/, '#\\1' + # link users buffer.gsub! /@(\w+)/, '@\\1' buffer diff --git a/config/application.example.yml b/config/application.example.yml index d999e05..c87128b 100644 --- a/config/application.example.yml +++ b/config/application.example.yml @@ -1,6 +1,7 @@ # Add application configuration variables here, as shown below. # # Rails config +debug: false SECRET_TOKEN: f79b0679785f11473630bc31e8941adc3897d8f2ca91261bb68f782c2c665b2d0d45db4c1c9ee43a50f69f620c152a3cd91029d969f2a9072bf98f7b3ee6bfb6 # Twitter config consumer_key: xxx diff --git a/lib/expand_url.rb b/lib/expand_url.rb new file mode 100644 index 0000000..d226c65 --- /dev/null +++ b/lib/expand_url.rb @@ -0,0 +1,58 @@ +require 'net/http' +require 'net/https' +require 'uri' + +# e.g. +# url = http://t.co/z4t0E1vArh +# ExpandUrl.expand_url(url) +# => "http://www.haaretz.com/news/national/israel-s-ag-impels-ministers-to-crack-down-on-exclusion-of-women.premium-1.519917" +module ExpandUrl + class ExpansionError < StandardError; end + module ExpansionErrors + class BadUrl < ExpansionError; end + class BadResponse < ExpansionError; end + end + HTTP_ERRORS = [Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, + Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError] + class BasicResponse < Struct.new(:url, :code); end + extend self + + # raises ExpandUrl::ExpansionError + def expand_url(url) + response = get_response(url) + case response.code + when '301' + log "url: #{url}\tresponse: #{response.inspect}" + expand_url(response['location']) + when '200' + log "url: #{url}\tresponse: #{response.inspect}" + url + else + log "url: #{url}\tresponse: #{response.inspect}" + expand_url(response['location']) + end + end + + def get_response(url) + uri = url_to_uri(url) + Net::HTTP.get_response(uri) + rescue EOFError => e + BasicResponse.new(url, '200') + rescue *HTTP_ERRORS => e + log url.inspect + e.inspect + raise ExpansionErrors::BadResponse.new(e) + end + + def url_to_uri(url) + begin + uri = URI.parse(url) + rescue URI::InvalidURIError, SocketError => e + raise ExpansionErrors::BadUrl.new(e) + end + end + + def log(msg) + STDOUT.puts "#{msg}\t#{caller[1]}" if (ENV['debug'] == 'true') + end + +end diff --git a/spec/lib/expand_url_spec.rb b/spec/lib/expand_url_spec.rb new file mode 100644 index 0000000..d979775 --- /dev/null +++ b/spec/lib/expand_url_spec.rb @@ -0,0 +1,7 @@ +require 'spec_helper' + +describe ExpandUrl do + + it 'should be tested' + +end diff --git a/spec/presenters/tweet/html_presenter_spec.rb b/spec/presenters/tweet/html_presenter_spec.rb index 7f21bfd..42fead8 100644 --- a/spec/presenters/tweet/html_presenter_spec.rb +++ b/spec/presenters/tweet/html_presenter_spec.rb @@ -4,13 +4,19 @@ subject { presenter } let(:presenter) { described_class.new tweet } + let(:tweet_link) { + link = 'http://t.co/cyL9StoS' + ExpandUrl.stub(:expand_url).with(link).and_return(link) + link + } let(:tweet) { - Tweet.new tweet_id: "263515718753079296", - tweet_text: "at @SteelCityRuby with @coreyhaines - one of my favorite #rubyfriends http://t.co/cyL9StoS", + Tweet.new(tweet_id: "263515718753079296", + tweet_text: "at @SteelCityRuby with @coreyhaines - one of my favorite #rubyfriends #{tweet_link}", username: "joshsusser", media_url: "http://p.twimg.com/A6gyJmlCUAA9Il2.jpg", image: "A6gyJmlCUAA9Il2.jpg", media_display_url: "pic.twitter.com/cyL9StoS" + ) } its(:username) { should == "@joshsusser" }