require 'net/http'
# Tinifies a URL. That is, take a long URL and makes it shorter using an API
# for a service like TinyURL.
class Tinifier
# TODO Refine this regular expression, or find one that someone smarter has already come up with.
@@url_matcher = /(https?)[\w\.\/\+\@\#\$\%\&\=\?\|\:\-\~\[\]]+[\w\/\+\@\#\$\%\&\=\?\|\:\-\~\[\]]/
@@apis = {
:tinyurl => "http://tinyurl.com/api-create.php?url=%s",
:snipurl => "http://snipr.com/site/snip?r=simple&link=%s",
:is_gd => "http://is.gd/api.php?longurl=%s",
}
@@default_api = :tinyurl
cattr_accessor :url_matcher, :apis, :default_api
def initialize(api=Tinifier.default_api)
@api = api
end
# Tinifies a single URL using the specified API. Returns the short URL,
# or the original URL if the API call fails.
def tinify_url(long_url, api=nil, &block)
tinify_url!(long_url, api, &block) rescue long_url
end
# Tinifies a single URL, raising an error if the URL could not be
# tinified.
def tinify_url!(long_url, api=nil)
api ||= @api
if block_given?
block.call(long_url)
else
api_template = Tinifier.apis[api]
raise "Unknown API specified: #{api}" if api_template.nil?
uri = URI.parse(api_template % long_url)
response = Net::HTTP.get_response(uri)
if response.class == Net::HTTPOK
short_url = response.body
logger.debug "Tinified #{long_url} => #{short_url}"
return short_url
else
raise "Failed to tinify #{long_url} via #{api}"
end
end
end
# Turns all urls found in +text+ string into tinified urls. Calls out
# to tinyurl API to replace the url. If a block is given, each url is
# yielded and the result replaces the url.
#
# tinify_urls('Visit http://www.mylongurl.com for more details.')
# tinify_urls('Visit http://www.mylongurl.com for more details.') { |url| MyUrlTinifier.tinify(url) }
def tinify_urls(text, api=nil, &block)
text.gsub(Tinifier.url_matcher) do |url|
tinify_url(url, api, &block)
end
end
def tinify_urls!(text, api=nil, &block)
text.gsub(Tinifier.url_matcher) do |url|
tinify_url!(url, api, &block)
end
end
protected
def logger
RAILS_DEFAULT_LOGGER
end
end