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.
- data/VERSION.yml +1 -1
- data/lib/tweetsy.rb +1 -0
- data/lib/tweetsy/client.rb +44 -14
- data/spec/client_spec.rb +57 -2
- metadata +2 -2
data/VERSION.yml
CHANGED
data/lib/tweetsy.rb
CHANGED
data/lib/tweetsy/client.rb
CHANGED
@@ -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
|
-
|
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?(
|
133
|
-
|
134
|
-
|
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
|
-
|
173
|
+
raise_errors(response)
|
144
174
|
end
|
145
175
|
end
|
146
176
|
|
data/spec/client_spec.rb
CHANGED
@@ -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
|
+
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-
|
12
|
+
date: 2009-04-28 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|