# -*- coding: utf-8 -*-
# vim:tabstop=4:expandtab:sw=4:softtabstop=4
require 'rubygems'
require 'json'
require 'net/http'
require 'uri'
require 'cgi'
# == MalformedURLError
#
# Raised when the user submits a malformed URL to whit.me
#
class MalformedURLError < ArgumentError
end
# == MalformedAliasError
#
# Raised when the user submits a malformed alias/hash to whit.me
#
class MalformedAliasError < ArgumentError
end
# == WhitmeURL
#
# Object that holds the different results of a Whit.me response
#
class WhitmeURL
SHORT_URL = 'http://www.whit.me/api/short?'
EXPAND_URL = 'http://www.whit.me/api/expand?'
# The list of urls
attr_accessor :url
# The list of url notes. Should be the same size of urls
attr_accessor :urlnote
# The note associated with this url
attr_accessor :note
# Contains the shortened URL
attr_accessor :hash
def initialize
self.url = []
self.urlnote = []
end
def to_short_url
params = self.url.map { |u| "url=#{CGI.escape(u)}" }
params |= self.urlnote.map { |u| "urlnote=#{CGI.escape(u)}" }
params << "note=#{CGI.escape(self.note)}" if self.note
params << "hash=#{CGI.escape(self.hash)}" if self.hash
SHORT_URL + params.join('&')
end
def to_expand_url
EXPAND_URL + "hash=#{CGI.escape(self.hash)}"
end
end
# == Whitme
#
# Holds the methods available on the Whit.me API
#
# (see http://www.whit.me/api/docs)
#
class Whitme
# Shortens a URL
#
# Returns a Whitme instance with the shortened version under the
# hash property.
#
# === Parameters
#
# * :url - a single string or an array of strings containing urls to shorten
# * :urlnote - a single string or an array of strings containing notes associated with the urls
# * :note - a general note to be associated with all the urls shortened
# * :hash - a custom URL alias (for readable shortened URLs). whit.me will return a generated alias if the supplied parameter already exists or is invalid
#
# The only really required field is :url. If :urlnotes is
# supplied, it must have the same size of :url. Otherwise an
# ArgumentError is raised.
#
# === Example
#
# require 'whitme'
# url = Whitme.short(:url => 'http://www.google.com', :note => 'foo')
# puts url.hash.inspect
#
# url = Whitme.short(:url => ['http://google.com', 'http://sapo.pt'])
# puts url.hash.inspect
#
def self.short(options = {})
# we must have at least on url to short
raise ArgumentError unless options[:url]
# if we have multiple notes, we should have the same number of urls
if options[:urlnote]
raise ArgumentError unless options[:urlnote].class == options[:url].class
if(options[:url].class == Array)
raise ArgumentError unless options[:url].size == options[:urlnote].size
end
end
url = WhitmeURL.new
url.url << options[:url] if options[:url].class == String
url.url |= options[:url] if options[:url].class == Array
if options[:urlnote]
url.urlnote << options[:urlnote] if options[:urlnote].class == String
url.urlnote |= options[:urlnote] if options[:urlnote].class == Array
end
url.note = options[:note]
url.hash = options[:hash]
uri = URI.parse(url.to_short_url)
res = Net::HTTP.start(uri.host, uri.port) do |http|
http.get(uri.request_uri, { 'Accept' => 'application/json' })
end
json = JSON.parse(res.body) rescue nil
if json
if json['error']
case json['error']
when 0
raise MalformedURLError
when 1
raise MalformedAliasError
else
raise ArgumentError
end
else
url.hash = json['url']
return url
end
end
end
# Expands an URL
#
# Returns a Whitme instance with all the (possible) fields filled. Accepts
# a unique argument with either a hash (e.g. XP45xe3) or a full whit.me
# URL.
#
# === Example
#
# require 'whitme'
# url = Whitme.expand('HQX4P9')
# puts url.url.inspect
#
def self.expand(hash)
url = WhitmeURL.new
if(hash.include? 'http://')
hash =~ /hash=(.+)/
hash = $1
end
url.hash = hash
json = JSON.parse(Net::HTTP.get(URI.parse(url.to_expand_url)))
url.url = json['urls']
url.urlnote = json['urlnotes']
url.note = json['note']
url
end
end