# shorturl.rb # # Created by Vincent Foley on 2005-06-02 # require "net/http" require "cgi" require "uri" class InvalidService < Exception end 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.post(@action, "#{@field}=#{url}") when :get: http.get("#{@action}?#{@field}=#{CGI.escape(url)}") end if response.code == @code.to_s @block.call(response.read_body) end } end end class ShortURL # Hash table of all the supported services. The key is a symbol # representing the service (usually the hostname minus the .com, # .net, etc.) The value is an instance of Service with all the # parameters set so that when +instance+.call is invoked, the # shortened URL is returned. @@services = { :rubyurl => Service.new("rubyurl.com") { |s| s.action = "/rubyurl/remote" s.field = "website_url" s.block = lambda { |body| URI.extract(body).grep(/rubyurl/)[0] } }, :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] } }, :minilink => Service.new("minilink.org") { |s| s.method = :get s.block = lambda { |body| URI.extract(body)[-1] } }, :lns => Service.new("ln-s.net") { |s| s.method = :get s.action = "/home/api.jsp" s.block = lambda { |body| URI.extract(body)[0] } }, :fyad => Service.new("fyad.org") { |s| s.method = :get s.block = lambda { |body| URI.extract(body).grep(/fyad.org/)[2] } }, :d62 => Service.new("d62.net") { |s| s.method = :get s.block = lambda { |body| URI.extract(body)[0] } }, :shiturl => Service.new("shiturl.com") { |s| s.method = :get s.action = "/make.php" s.block = lambda { |body| URI.extract(body).grep(/shiturl/)[0] } }, :littlink => Service.new("littlink.com") { |s| s.block = lambda { |body| URI.extract(body).grep(/littlink/)[0] } }, :clipurl => Service.new("clipurl.com") { |s| s.action = "/create.asp" s.block = lambda { |body| URI.extract(body).grep(/clipurl/)[0] } }, :shortify => Service.new("shortify.com") { |s| s.method = :get s.action = "/shorten.php" s.block = lambda { |body| URI.extract(body).grep(/shortify/)[0] } }, :orz => Service.new("0rz.net") { |s| s.action = "/create.php" s.block = lambda { |body| URI.extract(body).grep(/0rz/)[0] } }, :moourl => Service.new("moourl.com") { |s| s.code = 302 s.action = "/create/" s.method = :get s.field = "source" s.block = lambda { |body| body.gsub('Location/woot/?moo=','http://moourl.com/') } }, :urltea => Service.new("urltea.com") { |s| s.method = :get s.action = "/create/" s.block = lambda { |body| URI.extract(body).grep(/urltea/)[6] } } } # 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: # # * <tt>:rubyurl</tt> # * <tt>:tinyurl</tt> # * <tt>:shorl</tt> # * <tt>:snipurl</tt> # * <tt>:metamark</tt> # * <tt>:makeashorterlink</tt> # * <tt>:skinnylink</tt> # * <tt>:linktrim</tt> # * <tt>:shorterlink</tt> # * <tt>:minlink</tt> # * <tt>:lns</tt> # * <tt>:fyad</tt> # * <tt>:d62</tt> # * <tt>:shiturl</tt> # * <tt>:littlink</tt> # * <tt>:clipurl</tt> # * <tt>:shortify</tt> # * <tt>:orz</tt> # # 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 InvalidService end end end