# 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