lib/twfy/client.rb
require 'cgi'
require 'logger'
require 'multi_json'
require 'open-uri'
require 'ostruct'
module Twfy
class Client
include API
include Commands
class Error < ::StandardError; end
class APIError < ::StandardError; end
def initialize(api_key, log_to=$stderr)
@api_key = api_key
@logger = Logger.new(log_to)
end
def log(message, level=:info)
@logger.send(level, message) if $DEBUG
end
private
def service(name, params = {}, target = OpenStruct, &block)
log "Calling service #{name}"
url = service_url(name, params)
result = MultiJson.load(url.read)
log result.inspect
unless result.kind_of?(Enumerable)
raise Error, "Could not handle result: #{result.inspect}"
end
if result.kind_of?(Hash) && result['error']
raise APIError, result['error'].to_s
else
structure result, block || target
end
end
def service_url(name, params = {})
url = BASE + name.to_s
url.query = build_query(validate(params, API::VALIDATIONS[name]))
url
end
def validate(params, against)
Validation.run(params, against)
params
end
def structure(value, target)
case value
when Array
value.map{|r| structure(r, target) }
when Hash
if target.kind_of?(Proc)
target.call(value)
elsif target == Hash
value
else
target.ancestors.include?(DataElement) ? target.new(self,value) : target.new(value)
end
else
result
end
end
def build_query(params)
params.merge(api_params).map { |set|
set.map { |i|
CGI.escape(i.to_s)
}.join('=')
}.join('&')
end
def api_params
@api_params ||= {key: @api_key, version: API::VERSION}
end
end
end