dschn-tweetsy 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 4
2
+ :patch: 5
3
3
  :major: 0
4
4
  :minor: 1
@@ -6,6 +6,7 @@ module Tweetsy
6
6
  class Unauthorized < CantConnect; end
7
7
  class BadRequest < CantConnect; end
8
8
  class NotFound < CantConnect; end
9
+ class Forbidden < CantConnect; end
9
10
  end
10
11
 
11
12
  require File.dirname(__FILE__) + '/tweetsy/user'
@@ -1,9 +1,11 @@
1
1
  module Tweetsy
2
2
  class Client
3
3
  API_HOST = "http://twitter.com"
4
-
4
+ attr_reader :rate_limits
5
+
5
6
  def initialize(login, password, options = {})
6
7
  @config = options.merge(:auth => [login, password].join(':'))
8
+ @rate_limits = {}
7
9
  end
8
10
 
9
11
  def authenticate_as(login, password)
@@ -105,12 +107,47 @@ module Tweetsy
105
107
  path
106
108
  end
107
109
  end
110
+
111
+ def parse(response)
112
+ Hpricot.XML(response.body_str)
113
+ end
114
+
115
+ def parse_error(response)
116
+ (parse(response)/:hash/:error).inner_text
117
+ end
118
+
119
+ def parse_rate_limit(response)
120
+ response.header_str.scan(/^X-RateLimit-([a-zA-Z]+): (\d+)/) do |match|
121
+ @rate_limits[match.first.downcase.to_sym] = match.last.to_i
122
+ end
123
+ end
124
+
125
+ def raise_errors(response)
126
+ case response.response_code
127
+ when 400
128
+ error_msg = parse_error(response)
129
+ raise BadRequest.new(error_msg)
130
+ when 401
131
+ error_msg = parse_error(response)
132
+ raise Unauthorized.new(error_msg)
133
+ when 403
134
+ error_msg = parse_error(response)
135
+ raise Forbidden.new(error_msg)
136
+ when 404
137
+ error_msg = parse_error(response)
138
+ raise NotFound.new(error_msg)
139
+ when 503
140
+ raise CantConnect, "Service unavailable"
141
+ else
142
+ raise CantConnect, "#{response.response_code}"
143
+ end
144
+ end
108
145
 
109
146
  def request(method, endpoint, options = {})
110
147
  raise ArgumentError, "#{method} is not a valid request method" unless [:get, :post].include?(method)
111
148
 
112
149
  begin
113
- result = case method
150
+ response = case method
114
151
  when :get
115
152
  Curl::Easy.perform("#{API_HOST}/#{endpoint}") do |curl|
116
153
  default_curl_options(curl)
@@ -128,19 +165,12 @@ module Tweetsy
128
165
  rescue => e
129
166
  raise CantConnect, "#{e.message}"
130
167
  end
131
-
132
- if [200, 304].include?(result.response_code)
133
- Hpricot(result.body_str)
134
- elsif result.response_code == 401
135
- raise Unauthorized
136
- elsif result.response_code == 403
137
- raise BadRequest
138
- elsif result.response_code == 404
139
- raise NotFound
140
- elsif result.response_code == 503
141
- raise CantConnect, "Service unavailable"
168
+
169
+ if [200, 304].include?(response.response_code)
170
+ parse_rate_limit(response)
171
+ parse(response)
142
172
  else
143
- raise CantConnect, "#{result.response_code}"
173
+ raise_errors(response)
144
174
  end
145
175
  end
146
176
 
@@ -4,6 +4,12 @@ describe "Tweetsy::Client" do
4
4
  before do
5
5
  @base = Tweetsy::Client.new('foo', 'bar')
6
6
  end
7
+
8
+ describe "on initialization" do
9
+ it "should have empty rate_limit hash" do
10
+ @base.rate_limits.should == {}
11
+ end
12
+ end
7
13
 
8
14
  describe "authenticated?" do
9
15
  it "should return true on successful authentication (200)" do
@@ -54,6 +60,16 @@ describe "Tweetsy::Client" do
54
60
  end
55
61
  end
56
62
 
63
+ def create_error_response(message)
64
+ "
65
+ <?xml version=\"1.0\" encoding=\"UTF-8\"?>
66
+ <hash>
67
+ <request>/users/show/genevate.xml</request>
68
+ <error>#{message}</error>
69
+ </hash>
70
+ "
71
+ end
72
+
57
73
  describe "request" do
58
74
  it "should raise ArgumentError on bad arguments" do
59
75
  lambda {
@@ -62,7 +78,7 @@ describe "Tweetsy::Client" do
62
78
  end
63
79
 
64
80
  it "should raise Unauthorized on 401" do
65
- response = mock(:response, :response_code => 401)
81
+ response = mock(:response, :response_code => 401, :header_str => "", :body_str => create_error_response("test"))
66
82
  Curl::Easy.stub!(:perform).and_return(response)
67
83
 
68
84
  lambda {
@@ -73,10 +89,36 @@ describe "Tweetsy::Client" do
73
89
  @base.request(:get, 'blah')
74
90
  }.should raise_error(Tweetsy::CantConnect)
75
91
  end
92
+
93
+ it "should raise BadRequest on 400" do
94
+ response = mock(:response, :response_code => 400, :header_str => "", :body_str => create_error_response("test"))
95
+ Curl::Easy.stub!(:perform).and_return(response)
96
+
97
+ lambda {
98
+ @base.request(:get, 'blah')
99
+ }.should raise_error(Tweetsy::BadRequest)
100
+
101
+ lambda {
102
+ @base.request(:get, 'blah')
103
+ }.should raise_error(Tweetsy::CantConnect)
104
+ end
105
+
106
+ it "should raise Forbidden on 403" do
107
+ response = mock(:response, :response_code => 403, :header_str => "", :body_str => create_error_response("test"))
108
+ Curl::Easy.stub!(:perform).and_return(response)
109
+
110
+ lambda {
111
+ @base.request(:get, 'blah')
112
+ }.should raise_error(Tweetsy::Forbidden)
113
+
114
+ lambda {
115
+ @base.request(:get, 'blah')
116
+ }.should raise_error(Tweetsy::CantConnect)
117
+ end
76
118
 
77
119
  it "should raise CantConnect on anything that isn't 200 or 304 response" do
78
120
  [401, 503, 504, 505, nil].each do |code|
79
- response = mock(:response, :response_code => code)
121
+ response = mock(:response, :response_code => code, :header_str => "", :body_str => create_error_response("test"))
80
122
  Curl::Easy.stub!(:perform).and_return(response)
81
123
 
82
124
  lambda {
@@ -84,5 +126,18 @@ describe "Tweetsy::Client" do
84
126
  }.should raise_error(Tweetsy::CantConnect)
85
127
  end
86
128
  end
129
+
130
+ it "should return rate limit status" do
131
+ response = mock(:response,
132
+ :body_str => "Hello World",
133
+ :response_code => 200,
134
+ :header_str => "X-RateLimit-Limit: 100\r\nX-RateLimit-Remaining: 98\r\nX-RateLimit-Reset: 12345678")
135
+ Curl::Easy.stub!(:perform).and_return(response)
136
+
137
+ @base.request(:get, 'blah')
138
+ @base.rate_limits[:limit].should == 100
139
+ @base.rate_limits[:remaining].should == 98
140
+ @base.rate_limits[:reset].should == 12345678
141
+ end
87
142
  end
88
143
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dschn-tweetsy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dustin Schneider
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-09 00:00:00 -07:00
12
+ date: 2009-04-28 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15