# shorturl.rb # # Created by Vincent Foley on 2005-06-02 # require "net/http" require "cgi" require "uri" class Service attr_accessor :port, :code, :method, :action, :field, :block # Intialize the service with a hostname (required parameter) and you # can override the default values for the HTTP port, expected HTTP # return code, the form method to use, the form action, the form # field which contains the long URL and the block of what to do with # the HTML code you get. def initialize(hostname) # :yield: service @hostname = hostname @port = 80 @code = 200 @method = :post @action = "/" @field = "url" @block = lambda { |body| } if block_given? yield self end end # Now that our service is set up, call it with all the parameters to # (hopefully) return only the shortened URL. def call(url) Net::HTTP.start(@hostname, @port) { |http| response = case @method when :post: http.send(@method, @action, "#@field=#{url}") when :get: http.send(@method, "#@action?#@field=#{CGI.escape(url)}") end if response.code == @code.to_s @block.call(response.read_body) end } end end class ShortURL @@services = { :rubyurl => Service.new("rubyurl.com") { |s| s.code = 302 s.method = :get s.action = "/rubyurl/create" s.field = "rubyurl[website_url]" s.block = lambda { |body| URI.extract(body)[0].gsub("rubyurl/show/", "") } }, :tinyurl => Service.new("tinyurl.com") { |s| s.action = "/create.php" s.block = lambda { |body| URI.extract(body).grep(/tinyurl/)[-1] } }, :shorl => Service.new("shorl.com") { |s| s.action = "/create.php" s.block = lambda { |body| URI.extract(body)[2] } }, :snipurl => Service.new("snipurl.com") { |s| s.action = "/index.php" s.field = "link" s.block = lambda { |body| line = body.split("\n").grep(/txt/)[0] short_url = URI.extract(line)[1][0..-2] # Remove trailing ' } }, :metamark => Service.new("metamark.net") { |s| s.action = "/add" s.field = "long_url" s.block = lambda { |body| URI.extract(body).grep(/xrl.us/)[0] } }, :makeashorterlink => Service.new("makeashorterlink.com") { |s| s.action = "/index.php" s.block = lambda { |body| URI.extract(body).grep(/makeashorterlink/)[0] } }, :skinnylink => Service.new("skinnylink.com") { |s| s.block = lambda { |body| URI.extract(body).grep(/skinnylink/)[0] } }, :linktrim => Service.new("linktrim.com") { |s| s.method = :get s.action = "/lt/generate" s.block = lambda { |body| URI.extract(body).grep(/\/linktrim/)[1] } }, :shorterlink => Service.new("shorterlink.com") { |s| s.method = :get s.action = "/add_url.html" s.block = lambda { |body| URI.extract(body).grep(/shorterlink/)[0] } } } # Array containing symbols representing all the implemented URL # shortening services @@valid_services = @@services.keys # Returns @@valid_services def self.valid_services @@valid_services end # Main method of ShortURL, its usage is quite simple, just give an # url to shorten and an optional service. If no service is # selected, RubyURL.com will be used. An invalid service symbol # will raise an ArgumentError exception # # Valid +service+ values: # # * :rubyurl # * :tinyurl # * :shorl # * :snipurl # * :metamark # * :makeashorterlink # * :skinnylink # * :linktrim # * :shorterlink # # call-seq: # ShortURL.shorten("http://mypage.com") => Uses RubyURL # ShortURL.shorten("http://mypage.com", :tinyurl) def self.shorten(url, service = :rubyurl) if @@valid_services.include? service @@services[service].call(url) else raise ArgumentError, "Invalid service" end end end