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" }