Skip to content

Commit

Permalink
Moved error handling into the module so that it can be used by unauth…
Browse files Browse the repository at this point in the history
…enticated/module methods
  • Loading branch information
sferik committed Mar 24, 2010
1 parent 025be87 commit f62a150
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 106 deletions.
80 changes: 68 additions & 12 deletions lib/twitter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,39 +27,95 @@ class InformTwitter < StandardError; end
class NotFound < StandardError; end

def self.firehose
response = get("/statuses/public_timeline.json")
response.map { |tweet| Hashie::Mash.new(tweet) }
perform_get("/statuses/public_timeline.json")
end

def self.user(id)
response = get("/users/show/#{id}.json")
Hashie::Mash.new(response)
perform_get("/users/show/#{id}.json")
end

def self.status(id)
response = get("/statuses/show/#{id}.json")
Hashie::Mash.new(response)
perform_get("/statuses/show/#{id}.json")
end

def self.friend_ids(id)
get("/friends/ids/#{id}.json")
perform_get("/friends/ids/#{id}.json")
end

def self.follower_ids(id)
get("/followers/ids/#{id}.json")
perform_get("/followers/ids/#{id}.json")
end

def self.timeline(id, options={})
response = get("/statuses/user_timeline/#{id}.json", :query => options)
response.map{|tweet| Hashie::Mash.new tweet}
perform_get("/statuses/user_timeline/#{id}.json", :query => options)
end

# :per_page = max number of statues to get at once
# :page = which page of tweets you wish to get
def self.list_timeline(list_owner_username, slug, query = {})
response = get("/#{list_owner_username}/lists/#{slug}/statuses.json", :query => query)
response.map{|tweet| Hashie::Mash.new tweet}
perform_get("/#{list_owner_username}/lists/#{slug}/statuses.json", :query => query)
end

private

def self.perform_get(uri, options = {})
make_friendly(get(uri, options))
end

def self.make_friendly(response)
raise_errors(response)
data = parse(response)
# Don't mash arrays of integers
if data && data.first.is_a?(Integer)
data
else
mash(data)
end
end

def self.raise_errors(response)
case response.code.to_i
when 400
data = parse(response)
raise RateLimitExceeded.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
when 401
data = parse(response)
raise Unauthorized.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
when 403
data = parse(response)
raise General.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
when 404
raise NotFound, "(#{response.code}): #{response.message}"
when 500
raise InformTwitter, "Twitter had an internal error. Please let them know in the group. (#{response.code}): #{response.message}"
when 502..503
raise Unavailable, "(#{response.code}): #{response.message}"
end
end

def self.parse(response)
Crack::JSON.parse(response.body)
end

def self.mash(obj)
if obj.is_a?(Array)
obj.map { |item| make_mash_with_consistent_hash(item) }
elsif obj.is_a?(Hash)
make_mash_with_consistent_hash(obj)
else
obj
end
end

# Lame workaround for the fact that mash doesn't hash correctly
def self.make_mash_with_consistent_hash(obj)
m = Hashie::Mash.new(obj)
def m.hash
inspect.hash
end
return m
end

end

module Hashie
Expand Down
13 changes: 8 additions & 5 deletions lib/twitter/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def status(id)
end

# Options: count
def retweets(id, query={ })
def retweets(id, query={})
perform_get("/#{API_VERSION}/statuses/retweets/#{id}.json", :query => query)
end

Expand Down Expand Up @@ -70,7 +70,7 @@ def retweets_of_me(query={})
# options: count, page, ids_only
def retweeters_of(id, options={})
ids_only = !!(options.delete(:ids_only))
perform_get("/#{API_VERSION}/statuses/#{id}/retweeted_by#{"/ids" if ids_only}.json", :query => options, :mash => !ids_only)
perform_get("/#{API_VERSION}/statuses/#{id}/retweeted_by#{"/ids" if ids_only}.json", :query => options)
end

def status_destroy(id)
Expand Down Expand Up @@ -154,12 +154,12 @@ def friendship_show(query)

# Options: id, user_id, screen_name
def friend_ids(query={})
perform_get("/#{API_VERSION}/friends/ids.json", :query => query, :mash => false)
perform_get("/#{API_VERSION}/friends/ids.json", :query => query)
end

# Options: id, user_id, screen_name
def follower_ids(query={})
perform_get("/#{API_VERSION}/followers/ids.json", :query => query, :mash => false)
perform_get("/#{API_VERSION}/followers/ids.json", :query => query)
end

def verify_credentials
Expand Down Expand Up @@ -310,7 +310,7 @@ def blocking(options={})
perform_get("/#{API_VERSION}/blocks/blocking.json", options)
end

protected
protected

def self.mime_type(file)
case
Expand All @@ -320,9 +320,11 @@ def self.mime_type(file)
else 'application/octet-stream'
end
end

def mime_type(f) self.class.mime_type(f) end

CRLF = "\r\n"

def self.build_multipart_bodies(parts)
boundary = Time.now.to_i.to_s(16)
body = ""
Expand Down Expand Up @@ -364,5 +366,6 @@ def perform_put(path, options={})
def perform_delete(path, options={})
Twitter::Request.delete(self, path, options)
end

end
end
9 changes: 6 additions & 3 deletions lib/twitter/httpauth.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Twitter
class HTTPAuth
include HTTParty

format :plain

attr_reader :username, :password, :options
Expand Down Expand Up @@ -29,8 +30,10 @@ def delete(uri, body={}, headers={})
end

private
def basic_auth
@basic_auth ||= {:username => @username, :password => @password}
end

def basic_auth
@basic_auth ||= {:username => @username, :password => @password}
end

end
end
10 changes: 6 additions & 4 deletions lib/twitter/oauth.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Twitter
class OAuth
extend Forwardable

def_delegators :access_token, :get, :post, :put, :delete

attr_reader :ctoken, :csecret, :consumer_options
Expand All @@ -10,7 +11,6 @@ class OAuth
# (http://apiwiki.twitter.com/Sign-in-with-Twitter)
def initialize(ctoken, csecret, options={})
@ctoken, @csecret, @consumer_options = ctoken, csecret, {}

if options[:sign_in]
@consumer_options[:authorize_path] = '/oauth/authenticate'
end
Expand Down Expand Up @@ -49,8 +49,10 @@ def authorize_from_access(atoken, asecret)
end

private
def clear_request_token
@request_token = nil
end

def clear_request_token
@request_token = nil
end

end
end
87 changes: 20 additions & 67 deletions lib/twitter/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def self.delete(client, path, options={})
def_delegators :client, :get, :post, :put, :delete

def initialize(client, method, path, options={})
@client, @method, @path, @options = client, method, path, {:mash => true}.merge(options)
@client, @method, @path, @options = client, method, path, options
end

def uri
Expand All @@ -39,80 +39,33 @@ def uri
end

def perform
make_friendly(send("perform_#{method}"))
Twitter.make_friendly(send("perform_#{method}"))
end

private
def perform_get
send(:get, uri, options[:headers])
end

def perform_post
send(:post, uri, options[:body], options[:headers])
end

def perform_put
send(:put, uri, options[:body], options[:headers])
end

def perform_delete
send(:delete, uri, options[:headers])
end

def make_friendly(response)
raise_errors(response)
data = parse(response)
options[:mash] ? mash(data) : data
end
def perform_get
get(uri, options[:headers])
end

def raise_errors(response)
case response.code.to_i
when 400
data = parse(response)
raise RateLimitExceeded.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
when 401
data = parse(response)
raise Unauthorized.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
when 403
data = parse(response)
raise General.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
when 404
raise NotFound, "(#{response.code}): #{response.message}"
when 500
raise InformTwitter, "Twitter had an internal error. Please let them know in the group. (#{response.code}): #{response.message}"
when 502..503
raise Unavailable, "(#{response.code}): #{response.message}"
end
end
def perform_post
post(uri, options[:body], options[:headers])
end

def parse(response)
Crack::JSON.parse(response.body)
end
def perform_put
put(uri, options[:body], options[:headers])
end

def mash(obj)
if obj.is_a?(Array)
obj.map { |item| make_mash_with_consistent_hash(item) }
elsif obj.is_a?(Hash)
make_mash_with_consistent_hash(obj)
else
obj
end
end
def perform_delete
delete(uri, options[:headers])
end

# Lame workaround for the fact that mash doesn't hash correctly
def make_mash_with_consistent_hash(obj)
m = Hashie::Mash.new(obj)
def m.hash
inspect.hash
end
return m
end
def to_query(options)
options.inject([]) do |collection, opt|
collection << "#{opt[0]}=#{opt[1]}"
collection
end * '&'
end

def to_query(options)
options.inject([]) do |collection, opt|
collection << "#{opt[0]}=#{opt[1]}"
collection
end * '&'
end
end
end
22 changes: 12 additions & 10 deletions lib/twitter/search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,31 @@ def user_agent
@options[:user_agent] || "Ruby Twitter Gem"
end

def from(user,exclude=false)
def from(user, exclude=false)
@query[:q] << "#{exclude ? "-" : ""}from:#{user}"
self
end

def to(user,exclude=false)
def to(user, exclude=false)
@query[:q] << "#{exclude ? "-" : ""}to:#{user}"
self
end

def referencing(user,exclude=false)
def referencing(user, exclude=false)
@query[:q] << "#{exclude ? "-" : ""}@#{user}"
self
end
alias :references :referencing
alias :ref :referencing

def containing(word,exclude=false)
def containing(word, exclude=false)
@query[:q] << "#{exclude ? "-" : ""}#{word}"
self
end
alias :contains :containing

# adds filtering based on hash tag ie: #twitter
def hashed(tag,exclude=false)
def hashed(tag, exclude=false)
@query[:q] << "#{exclude ? "-" : ""}\##{tag}"
self
end
Expand Down Expand Up @@ -131,7 +131,7 @@ def fetch(force=false)
end

def each
fetch()["results"].each { |r| yield r }
fetch()["results"].each{|r| yield r}
end

def next_page?
Expand All @@ -147,9 +147,11 @@ def fetch_next_page
end

protected
def perform_get(query)
response = self.class.get("http://api.twitter.com/#{API_VERSION}/search.json", :query => query, :format => :json, :headers => {"User-Agent" => user_agent})
@fetch = Hashie::Mash.new(response)
end

def perform_get(query)
response = self.class.get("http://api.twitter.com/#{API_VERSION}/search.json", :query => query, :format => :json, :headers => {"User-Agent" => user_agent})
@fetch = Twitter.mash(response)
end

end
end
Loading

0 comments on commit f62a150

Please sign in to comment.