webco-tuiter 0.0.3 → 0.0.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/CHANGELOG +59 -32
- data/lib/tuiter/client.rb +15 -189
- data/lib/tuiter/methods/account.rb +35 -0
- data/lib/tuiter/methods/direct_message.rb +55 -0
- data/lib/tuiter/methods/friendship.rb +55 -0
- data/lib/tuiter/methods/social_graph.rb +20 -0
- data/lib/tuiter/methods/status.rb +66 -0
- data/lib/tuiter/methods/user.rb +59 -0
- data/lib/tuiter/version.rb +1 -1
- data/lib/tuiter.rb +10 -2
- data/test/test_helper.rb +3 -12
- data/test/unit/client_test.rb +49 -24
- data/test/unit/rate_limit_test.rb +15 -0
- metadata +10 -3
data/CHANGELOG
CHANGED
|
@@ -1,36 +1,63 @@
|
|
|
1
|
+
== v0.0.5
|
|
2
|
+
* Version bump and gemspec update
|
|
3
|
+
* Improvements on parse_options
|
|
4
|
+
* direct_messages_sent method implemented and small namespace fix
|
|
5
|
+
* Small fix in Tuiter Client test
|
|
6
|
+
* Merging thomaz/master
|
|
7
|
+
* bug fix on statuses_show
|
|
8
|
+
* tests for client
|
|
9
|
+
* removed quietbacktrace configurations
|
|
10
|
+
* modified tests for new method names, bug fix in Client#statuses_update
|
|
11
|
+
* social_graph/direct_message methods moved to modules
|
|
12
|
+
* status/user/account methods moved to modules
|
|
13
|
+
* friendship methods moved to module
|
|
14
|
+
|
|
15
|
+
== v0.0.4
|
|
16
|
+
* Adding remove friendship method
|
|
17
|
+
|
|
18
|
+
== v0.0.3
|
|
19
|
+
* Resolving a simple conflict and adding get_followers_ids method
|
|
20
|
+
* alterando gemspec
|
|
21
|
+
* adding get_friends call to api
|
|
22
|
+
* Autotest configuration file
|
|
23
|
+
* Adding followers ids retrieval method
|
|
24
|
+
* Testing client on try update message and result http response status error
|
|
25
|
+
* Added RCOV rake task
|
|
26
|
+
* Tests for rate_limit and shoulda macro should_load_attribute_on_initialize
|
|
27
|
+
|
|
1
28
|
== v0.0.2
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
* Added github profile path on AUTHORS
|
|
30
|
+
* Bumping version, including direct message files
|
|
31
|
+
* Updating AUTHORS. Giving credit where is due
|
|
32
|
+
* Adding DirectMessage data structure and listing method. Bumping tiny version one up
|
|
33
|
+
* Fixing the installation instructions on the README file
|
|
34
|
+
* Refactoring client tests to use fakeweb and less expectations
|
|
35
|
+
* Tests for StatusBasic and Status
|
|
36
|
+
* Tests for User, UserBasic and UserExtended - 100% tests coverage
|
|
37
|
+
* Added rake tasks to execute rcov
|
|
38
|
+
* Adding some json fixtures for testing
|
|
39
|
+
* Fixing a false cognate on README
|
|
40
|
+
* Added initial tests
|
|
41
|
+
* Namespace done right
|
|
42
|
+
* Fixed requires definitely
|
|
43
|
+
* Fixed requires again
|
|
44
|
+
* Fixed requires
|
|
45
|
+
* Updating README
|
|
46
|
+
* Updating tuiter.gemspec
|
|
47
|
+
* Adding a rake task to publish tuiter on Rubyforge
|
|
48
|
+
* Added http proxy support to all operations
|
|
49
|
+
* Added check RUBY_PLATFORM because JRuby does not support native extensions
|
|
50
|
+
* Rakefile and gemspec updated, it should work fine now
|
|
51
|
+
* Trying to fix the gemspec
|
|
52
|
+
* Small fix on tuiter gemspec
|
|
53
|
+
* Adding the gemspec to allow Github to generate and publish a tuiter gem
|
|
54
|
+
* Adding the most simple and obvious example ever
|
|
55
|
+
* The most simple and basic example that could ever be
|
|
56
|
+
* Updating .gitignore
|
|
57
|
+
* Adding a README, just for kicks
|
|
58
|
+
* Moving the requires out of the client
|
|
59
|
+
* Cleaning up some stuff, organizing things, the plumbing
|
|
60
|
+
* Adding authors, license and changelog files
|
|
34
61
|
|
|
35
62
|
== v0.0.1
|
|
36
63
|
* Extracting tuiter from tuitersfera
|
data/lib/tuiter/client.rb
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
module Tuiter
|
|
2
2
|
|
|
3
3
|
class Client
|
|
4
|
+
include Tuiter::StatusMethods
|
|
5
|
+
include Tuiter::UserMethods
|
|
6
|
+
include Tuiter::DirectMessageMethods
|
|
7
|
+
include Tuiter::FriendshipMethods
|
|
8
|
+
include Tuiter::SocialGraphMethods
|
|
9
|
+
include Tuiter::AccountMethods
|
|
10
|
+
|
|
4
11
|
attr_accessor :username, :password
|
|
5
12
|
|
|
6
13
|
def initialize(options = {})
|
|
@@ -11,188 +18,13 @@ module Tuiter
|
|
|
11
18
|
@use_proxy = setup_a_proxy?
|
|
12
19
|
log("initialize()")
|
|
13
20
|
end
|
|
14
|
-
|
|
15
|
-
def update(status, in_reply_to_status_id = nil)
|
|
16
|
-
log("update() sending: #{status}")
|
|
17
|
-
url = URI.parse('http://twitter.com/statuses/update.json')
|
|
18
|
-
req = Net::HTTP::Post.new(url.path)
|
|
19
|
-
req.basic_auth @username, @password
|
|
20
|
-
req.set_form_data({'status'=>status, 'in_reply_to_status_id'=>in_reply_to_status_id })
|
|
21
|
-
res = new_http_for(url).start {|http| http.request(req) }
|
|
22
|
-
case res
|
|
23
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
|
24
|
-
log("update() success: OK")
|
|
25
|
-
return res # OK
|
|
26
|
-
else
|
|
27
|
-
log("update() error: #{res.to_s}")
|
|
28
|
-
res.error!
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def direct_new(user, text)
|
|
33
|
-
log("direct_new() sending: #{text} to #{user}")
|
|
34
|
-
url = URI.parse('http://twitter.com/direct_messages/new.json')
|
|
35
|
-
req = Net::HTTP::Post.new(url.path)
|
|
36
|
-
req.basic_auth @username, @password
|
|
37
|
-
req.set_form_data({'user'=>user, 'text'=>text })
|
|
38
|
-
res = new_http_for(url).start {|http| http.request(req) }
|
|
39
|
-
case res
|
|
40
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
|
41
|
-
log("direct_new() success: OK")
|
|
42
|
-
return res # OK
|
|
43
|
-
else
|
|
44
|
-
log("direct_new() error: #{res.error!}")
|
|
45
|
-
res.error!
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def direct_list(options = {})
|
|
50
|
-
url = 'http://twitter.com/direct_messages.json'
|
|
51
|
-
params = parse_options(options) || ""
|
|
52
|
-
|
|
53
|
-
if res = request(url+params)
|
|
54
|
-
data = JSON.parse(res)
|
|
55
|
-
return data.map { |d| DirectMessage.new(d) }
|
|
56
|
-
else
|
|
57
|
-
return nil
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
21
|
|
|
61
|
-
def friendship_new(user, follow = nil)
|
|
62
|
-
log("friendship_new() following: #{user}")
|
|
63
|
-
url = URI.parse("http://twitter.com/friendships/create/#{user}.json")
|
|
64
|
-
req = Net::HTTP::Post.new(url.path)
|
|
65
|
-
req.basic_auth @username, @password
|
|
66
|
-
req.set_form_data({'follow'=>"true"}) if follow
|
|
67
|
-
res = new_http_for(url).start {|http| http.request(req) }
|
|
68
|
-
case res
|
|
69
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
|
70
|
-
log("friendship_new() success: OK")
|
|
71
|
-
return res # OK
|
|
72
|
-
else
|
|
73
|
-
log("friendship_new() error: #{res.error!}")
|
|
74
|
-
res.error!
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def verify_credentials?
|
|
79
|
-
if res = request("http://twitter.com/account/verify_credentials.json")
|
|
80
|
-
return UserExtended.new(JSON.parse(res))
|
|
81
|
-
else
|
|
82
|
-
return nil
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def get_followers(options = {})
|
|
87
|
-
if options[:id]
|
|
88
|
-
query = "http://twitter.com/statuses/followers/#{options[:id]}.json"
|
|
89
|
-
else
|
|
90
|
-
query = "http://twitter.com/statuses/followers.json"
|
|
91
|
-
end
|
|
92
|
-
if options[:page]
|
|
93
|
-
params = "?page=#{options[:page]}"
|
|
94
|
-
else
|
|
95
|
-
params = ""
|
|
96
|
-
end
|
|
97
|
-
if res = request(query+params)
|
|
98
|
-
data = JSON.parse(res)
|
|
99
|
-
return data.map { |d| User.new(d) }
|
|
100
|
-
else
|
|
101
|
-
return nil
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def get_friends(options = {})
|
|
106
|
-
if options[:id]
|
|
107
|
-
query = "http://twitter.com/statuses/friends/#{options[:id]}.json"
|
|
108
|
-
else
|
|
109
|
-
query = "http://twitter.com/statuses/friends.json"
|
|
110
|
-
end
|
|
111
|
-
if options[:page]
|
|
112
|
-
params = "?page=#{options[:page]}"
|
|
113
|
-
else
|
|
114
|
-
params = ""
|
|
115
|
-
end
|
|
116
|
-
if res = request(query+params)
|
|
117
|
-
data = JSON.parse(res)
|
|
118
|
-
return data.map { |d| User.new(d) }
|
|
119
|
-
else
|
|
120
|
-
return nil
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def get_replies(options = {})
|
|
125
|
-
query = "http://twitter.com/statuses/replies.json"
|
|
126
|
-
if options[:since]
|
|
127
|
-
params = "?since=#{options[:since]}"
|
|
128
|
-
elsif options[:since_id]
|
|
129
|
-
params = "?since_id=#{options[:since_id]}"
|
|
130
|
-
else
|
|
131
|
-
params = ""
|
|
132
|
-
end
|
|
133
|
-
if options[:page]
|
|
134
|
-
if params == ""
|
|
135
|
-
params = "?page=#{options[:page]}"
|
|
136
|
-
else
|
|
137
|
-
params = params + "&" + "page=#{options[:page]}"
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
if res = request(query+params)
|
|
141
|
-
data = JSON.parse(res)
|
|
142
|
-
return data.map { |d| Status.new(d) }
|
|
143
|
-
else
|
|
144
|
-
return nil
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def get_client
|
|
149
|
-
if res = request("http://twitter.com/users/show/#{@username}.json")
|
|
150
|
-
return UserExtended.new(JSON.parse(res))
|
|
151
|
-
else
|
|
152
|
-
return nil
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def get_user(id)
|
|
157
|
-
if res = request("http://twitter.com/users/show/#{id}.json")
|
|
158
|
-
return UserExtended.new(JSON.parse(res))
|
|
159
|
-
else
|
|
160
|
-
return nil
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
def get_status(id)
|
|
165
|
-
if res = request("http://twitter.com/statuses/show/#{id}.json")
|
|
166
|
-
return Status.new(JSON.parse(res))
|
|
167
|
-
else
|
|
168
|
-
return nil
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
def rate_limit
|
|
173
|
-
if res = request("http://twitter.com/account/rate_limit_status.json")
|
|
174
|
-
return RateLimit.new(JSON.parse(res))
|
|
175
|
-
else
|
|
176
|
-
return nil
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
def follows_me?(id)
|
|
181
|
-
if res = request("http://twitter.com/friendships/exists.json?user_a=#{id}&user_b=#{@username}")
|
|
182
|
-
return true if res == "true"
|
|
183
|
-
return false
|
|
184
|
-
else
|
|
185
|
-
return nil
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
22
|
private
|
|
190
|
-
|
|
191
23
|
def request(url)
|
|
192
24
|
http = nil
|
|
193
25
|
status = Timeout::timeout(10) do
|
|
194
26
|
log("request() query: #{url}")
|
|
195
|
-
http = open(url, :http_basic_authentication=>[@username, @password])
|
|
27
|
+
http = open(url, :http_basic_authentication => [@username, @password])
|
|
196
28
|
log("request() debug: http status is #{http.status.join(' ')}")
|
|
197
29
|
if http.status == ["200", "OK"]
|
|
198
30
|
res = http.read
|
|
@@ -212,21 +44,15 @@ module Tuiter
|
|
|
212
44
|
end
|
|
213
45
|
|
|
214
46
|
def parse_options(options)
|
|
215
|
-
|
|
216
|
-
params = "?since=#{options[:since]}"
|
|
217
|
-
elsif options[:since_id]
|
|
218
|
-
params = "?since_id=#{options[:since_id]}"
|
|
219
|
-
else
|
|
220
|
-
params = ""
|
|
221
|
-
end
|
|
47
|
+
params = ""
|
|
222
48
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
else
|
|
227
|
-
|
|
49
|
+
options.each do |k, v|
|
|
50
|
+
unless params.empty?
|
|
51
|
+
params = params + "&#{k}=#{v}"
|
|
52
|
+
else
|
|
53
|
+
params = "?#{k}=#{v}"
|
|
228
54
|
end
|
|
229
|
-
end
|
|
55
|
+
end if (options && !options.empty?)
|
|
230
56
|
|
|
231
57
|
return params
|
|
232
58
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Account Methods
|
|
2
|
+
# [X] account/verify_credentials
|
|
3
|
+
# [ ] account/end_session
|
|
4
|
+
# [ ] account/update_location
|
|
5
|
+
# [ ] account/update_delivery_device
|
|
6
|
+
# [ ] account/update_profile_colors
|
|
7
|
+
# [ ] account/update_profile_image
|
|
8
|
+
# [ ] account/update_profile_background_image
|
|
9
|
+
# [X] account/rate_limit_status
|
|
10
|
+
# [ ] account/update_profile
|
|
11
|
+
|
|
12
|
+
module Tuiter
|
|
13
|
+
|
|
14
|
+
module AccountMethods
|
|
15
|
+
|
|
16
|
+
def account_verify_credentials?
|
|
17
|
+
if res = request("http://twitter.com/account/verify_credentials.json")
|
|
18
|
+
return Tuiter::UserExtended.new(JSON.parse(res))
|
|
19
|
+
else
|
|
20
|
+
return nil
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def account_rate_limit_status
|
|
25
|
+
if res = request("http://twitter.com/account/rate_limit_status.json")
|
|
26
|
+
return Tuiter::RateLimit.new(JSON.parse(res))
|
|
27
|
+
else
|
|
28
|
+
return nil
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Direct Message Methods
|
|
2
|
+
# [X] direct_messages
|
|
3
|
+
# [ ] direct_messages/sent
|
|
4
|
+
# [X] direct_messages/new
|
|
5
|
+
# [ ] direct_messages/destroy
|
|
6
|
+
|
|
7
|
+
module Tuiter
|
|
8
|
+
|
|
9
|
+
module DirectMessageMethods
|
|
10
|
+
|
|
11
|
+
def direct_messages(options = {})
|
|
12
|
+
url = 'http://twitter.com/direct_messages.json'
|
|
13
|
+
params = parse_options(options) || ""
|
|
14
|
+
|
|
15
|
+
if res = request(url+params)
|
|
16
|
+
data = JSON.parse(res)
|
|
17
|
+
return data.map { |d| Tuiter::DirectMessage.new(d) }
|
|
18
|
+
else
|
|
19
|
+
return nil
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def direct_messages_sent(options = {})
|
|
24
|
+
url = 'http://twitter.com/direct_messages/sent.json'
|
|
25
|
+
params = parse_options(options) || ""
|
|
26
|
+
|
|
27
|
+
if res = request(url+params)
|
|
28
|
+
data = JSON.parse(res)
|
|
29
|
+
return data.map { |d| Tuiter::DirectMessage.new(d) }
|
|
30
|
+
else
|
|
31
|
+
return nil
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def direct_messages_new(user, text)
|
|
36
|
+
log("direct_new() sending: #{text} to #{user}")
|
|
37
|
+
url = URI.parse('http://twitter.com/direct_messages/new.json')
|
|
38
|
+
req = Net::HTTP::Post.new(url.path)
|
|
39
|
+
req.basic_auth @username, @password
|
|
40
|
+
req.set_form_data({'user'=>user, 'text'=>text })
|
|
41
|
+
res = new_http_for(url).start {|http| http.request(req) }
|
|
42
|
+
case res
|
|
43
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
|
44
|
+
log("direct_new() success: OK")
|
|
45
|
+
return res # OK
|
|
46
|
+
else
|
|
47
|
+
log("direct_new() error: #{res.error!}")
|
|
48
|
+
res.error!
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Friendship Methods
|
|
2
|
+
# [X] friendships/create
|
|
3
|
+
# [X] friendships/destroy
|
|
4
|
+
# [X] friendships/exists
|
|
5
|
+
|
|
6
|
+
module Tuiter
|
|
7
|
+
|
|
8
|
+
module FriendshipMethods
|
|
9
|
+
|
|
10
|
+
def friendships_create(user, follow = nil)
|
|
11
|
+
log("friendship_new() following: #{user}")
|
|
12
|
+
url = URI.parse("http://twitter.com/friendships/create/#{user}.json")
|
|
13
|
+
req = Net::HTTP::Post.new(url.path)
|
|
14
|
+
req.basic_auth @username, @password
|
|
15
|
+
req.set_form_data({'follow'=>"true"}) if follow
|
|
16
|
+
res = new_http_for(url).start {|http| http.request(req) }
|
|
17
|
+
case res
|
|
18
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
|
19
|
+
log("friendship_new() success: OK")
|
|
20
|
+
return res # OK
|
|
21
|
+
else
|
|
22
|
+
log("friendship_new() error: #{res.error!}")
|
|
23
|
+
res.error!
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def friendships_destroy(user, follow = nil)
|
|
28
|
+
log("friendship_new() following: #{user}")
|
|
29
|
+
url = URI.parse("http://twitter.com/friendships/destroy/#{user}.json")
|
|
30
|
+
req = Net::HTTP::Post.new(url.path)
|
|
31
|
+
req.basic_auth @username, @password
|
|
32
|
+
res = new_http_for(url).start {|http| http.request(req) }
|
|
33
|
+
case res
|
|
34
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
|
35
|
+
log("remove_friendship() success: OK")
|
|
36
|
+
return res # OK
|
|
37
|
+
else
|
|
38
|
+
log("remove_friendship() error: #{res.error!}")
|
|
39
|
+
res.error!
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def friendships_exists?(id)
|
|
44
|
+
if res = request("http://twitter.com/friendships/exists.json?user_a=#{id}&user_b=#{@username}")
|
|
45
|
+
return true if res == "true"
|
|
46
|
+
return false
|
|
47
|
+
else
|
|
48
|
+
return nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Social Graph Methods
|
|
2
|
+
# [ ] friends/ids
|
|
3
|
+
# [X] followers/ids
|
|
4
|
+
|
|
5
|
+
module Tuiter
|
|
6
|
+
|
|
7
|
+
module SocialGraphMethods
|
|
8
|
+
|
|
9
|
+
def followers_ids
|
|
10
|
+
if res = request("http://twitter.com/followers/ids/#{username}.json")
|
|
11
|
+
return JSON.parse(res)
|
|
12
|
+
else
|
|
13
|
+
return nil
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Status Methods
|
|
2
|
+
# [ ] statuses/public_timeline
|
|
3
|
+
# [ ] statuses/friends_timeline
|
|
4
|
+
# [ ] statuses/user_timeline
|
|
5
|
+
# [X] statuses/show
|
|
6
|
+
# [X] statuses/update
|
|
7
|
+
# [X] statuses/mentions
|
|
8
|
+
# [ ] statuses/destroy
|
|
9
|
+
|
|
10
|
+
module Tuiter
|
|
11
|
+
|
|
12
|
+
module StatusMethods
|
|
13
|
+
|
|
14
|
+
def statuses_show(id)
|
|
15
|
+
if res = request("http://twitter.com/statuses/show/#{id}.json")
|
|
16
|
+
return Tuiter::Status.new(JSON.parse(res))
|
|
17
|
+
else
|
|
18
|
+
return nil
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def statuses_update(status, in_reply_to_status_id = nil)
|
|
23
|
+
log("update() sending: #{status}")
|
|
24
|
+
url = URI.parse('http://twitter.com/statuses/update.json')
|
|
25
|
+
req = Net::HTTP::Post.new(url.path)
|
|
26
|
+
req.basic_auth @username, @password
|
|
27
|
+
req.set_form_data({'status'=>status, 'in_reply_to_status_id'=>in_reply_to_status_id })
|
|
28
|
+
res = new_http_for(url).start {|http| http.request(req) }
|
|
29
|
+
case res
|
|
30
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
|
31
|
+
log("update() success: OK")
|
|
32
|
+
return res # OK
|
|
33
|
+
else
|
|
34
|
+
log("update() error: #{res.to_s}")
|
|
35
|
+
res.error!
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def statuses_mentions(options = {})
|
|
40
|
+
query = "http://twitter.com/statuses/mentions.json"
|
|
41
|
+
if options[:since]
|
|
42
|
+
params = "?since=#{options[:since]}"
|
|
43
|
+
elsif options[:since_id]
|
|
44
|
+
params = "?since_id=#{options[:since_id]}"
|
|
45
|
+
else
|
|
46
|
+
params = ""
|
|
47
|
+
end
|
|
48
|
+
if options[:page]
|
|
49
|
+
if params == ""
|
|
50
|
+
params = "?page=#{options[:page]}"
|
|
51
|
+
else
|
|
52
|
+
params = params + "&" + "page=#{options[:page]}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
if res = request(query+params)
|
|
56
|
+
data = JSON.parse(res)
|
|
57
|
+
return data.map { |d| Tuiter::Status.new(d) }
|
|
58
|
+
else
|
|
59
|
+
return nil
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# User Methods
|
|
2
|
+
# [X] statuses/friends
|
|
3
|
+
# [X] statuses/followers
|
|
4
|
+
# [X] users/show
|
|
5
|
+
|
|
6
|
+
module Tuiter
|
|
7
|
+
|
|
8
|
+
module UserMethods
|
|
9
|
+
|
|
10
|
+
def statuses_friends(options = {})
|
|
11
|
+
if options[:id]
|
|
12
|
+
query = "http://twitter.com/statuses/friends/#{options[:id]}.json"
|
|
13
|
+
else
|
|
14
|
+
query = "http://twitter.com/statuses/friends.json"
|
|
15
|
+
end
|
|
16
|
+
if options[:page]
|
|
17
|
+
params = "?page=#{options[:page]}"
|
|
18
|
+
else
|
|
19
|
+
params = ""
|
|
20
|
+
end
|
|
21
|
+
if res = request(query+params)
|
|
22
|
+
data = JSON.parse(res)
|
|
23
|
+
return data.map { |d| Tuiter::User.new(d) }
|
|
24
|
+
else
|
|
25
|
+
return nil
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def statuses_followers(options = {})
|
|
30
|
+
if options[:id]
|
|
31
|
+
query = "http://twitter.com/statuses/followers/#{options[:id]}.json"
|
|
32
|
+
else
|
|
33
|
+
query = "http://twitter.com/statuses/followers.json"
|
|
34
|
+
end
|
|
35
|
+
if options[:page]
|
|
36
|
+
params = "?page=#{options[:page]}"
|
|
37
|
+
else
|
|
38
|
+
params = ""
|
|
39
|
+
end
|
|
40
|
+
if res = request(query+params)
|
|
41
|
+
data = JSON.parse(res)
|
|
42
|
+
return data.map { |d| Tuiter::User.new(d) }
|
|
43
|
+
else
|
|
44
|
+
return nil
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def users_show(id)
|
|
49
|
+
if res = request("http://twitter.com/users/show/#{id}.json")
|
|
50
|
+
return Tuiter::UserExtended.new(JSON.parse(res))
|
|
51
|
+
else
|
|
52
|
+
return nil
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
data/lib/tuiter/version.rb
CHANGED
data/lib/tuiter.rb
CHANGED
|
@@ -8,8 +8,13 @@ require 'json'
|
|
|
8
8
|
libdir = File.dirname(__FILE__)
|
|
9
9
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
|
10
10
|
|
|
11
|
-
# Tuiter
|
|
12
|
-
require 'tuiter/
|
|
11
|
+
# Tuiter API methods modules
|
|
12
|
+
require 'tuiter/methods/status'
|
|
13
|
+
require 'tuiter/methods/user'
|
|
14
|
+
require 'tuiter/methods/direct_message'
|
|
15
|
+
require 'tuiter/methods/friendship'
|
|
16
|
+
require 'tuiter/methods/social_graph'
|
|
17
|
+
require 'tuiter/methods/account'
|
|
13
18
|
|
|
14
19
|
# Tuiter data structures
|
|
15
20
|
require 'tuiter/data/user'
|
|
@@ -17,3 +22,6 @@ require 'tuiter/data/status'
|
|
|
17
22
|
require 'tuiter/data/rate_limit'
|
|
18
23
|
require 'tuiter/data/direct_message'
|
|
19
24
|
|
|
25
|
+
# Tuiter client and end points
|
|
26
|
+
require 'tuiter/client'
|
|
27
|
+
|
data/test/test_helper.rb
CHANGED
|
@@ -4,17 +4,6 @@ require "shoulda"
|
|
|
4
4
|
require "mocha"
|
|
5
5
|
require 'fakeweb'
|
|
6
6
|
|
|
7
|
-
# begin
|
|
8
|
-
# require "quietbacktrace"
|
|
9
|
-
# Test::Unit::TestCase.quiet_backtrace = true
|
|
10
|
-
# Test::Unit::TestCase.backtrace_silencers = [:test_unit, :gem_root, :e1]
|
|
11
|
-
# Test::Unit::TestCase.backtrace_filters = [:method_name]
|
|
12
|
-
# rescue LoadError
|
|
13
|
-
# # Just ignore it
|
|
14
|
-
# rescue NoMethodError
|
|
15
|
-
# # Just ignore it
|
|
16
|
-
# end
|
|
17
|
-
|
|
18
7
|
require File.dirname(__FILE__) + "/../lib/tuiter"
|
|
19
8
|
|
|
20
9
|
#Load shoulda macros
|
|
@@ -22,4 +11,6 @@ require File.dirname(__FILE__) + "/../lib/tuiter"
|
|
|
22
11
|
Dir[File.dirname(__FILE__) + "/#{dirname}/*.rb"].each do |file|
|
|
23
12
|
require file
|
|
24
13
|
end
|
|
25
|
-
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Logger.any_instance.stubs(:info)
|
data/test/unit/client_test.rb
CHANGED
|
@@ -2,11 +2,11 @@ require File.dirname(__FILE__) + '/../test_helper'
|
|
|
2
2
|
|
|
3
3
|
class ClientTest < Test::Unit::TestCase
|
|
4
4
|
|
|
5
|
-
def
|
|
6
|
-
FakeWeb.register_uri(:post,
|
|
5
|
+
def fake_web_on_post(url, options = {:string => "OK", :status => "200"})
|
|
6
|
+
FakeWeb.register_uri(:post, url, options)
|
|
7
7
|
end
|
|
8
|
-
|
|
9
|
-
context "A valid Tuiter client" do
|
|
8
|
+
|
|
9
|
+
context "A valid Tuiter client without proxy" do
|
|
10
10
|
|
|
11
11
|
setup do
|
|
12
12
|
@username = "username"
|
|
@@ -14,17 +14,14 @@ class ClientTest < Test::Unit::TestCase
|
|
|
14
14
|
@client = Tuiter::Client.new(:username => @username, :password => @password)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
context "
|
|
17
|
+
context "on POST to statuses/update" do
|
|
18
18
|
setup do
|
|
19
|
+
@update_message = "I'm fine"
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
context "successfully" do
|
|
22
|
-
|
|
22
|
+
context "with successfully response" do
|
|
23
23
|
setup do
|
|
24
|
-
@update_message
|
|
25
|
-
FakeWeb.register_uri(:post, "http://twitter.com/statuses/update.json",
|
|
26
|
-
:string => @update_message,
|
|
27
|
-
:status => "200")
|
|
24
|
+
fake_web_on_post("http://twitter.com/statuses/update.json", :string => @update_message, :status => "200")
|
|
28
25
|
end
|
|
29
26
|
|
|
30
27
|
should "allow the user to post an update to Twitter" do
|
|
@@ -32,35 +29,63 @@ class ClientTest < Test::Unit::TestCase
|
|
|
32
29
|
Net::HTTP::Post.any_instance.expects(:basic_auth).with(@username, @password)
|
|
33
30
|
Net::HTTP::Post.any_instance.expects(:set_form_data).with('status' => @update_message, 'in_reply_to_status_id' => nil)
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
assert_nothing_raised do
|
|
33
|
+
@response = @client.statuses_update(@update_message)
|
|
34
|
+
end
|
|
35
|
+
assert_instance_of Net::HTTPOK, @response
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
should "allow the user to post a reply to Twitter" do
|
|
39
|
+
# basic authentication and form data
|
|
40
|
+
Net::HTTP::Post.any_instance.expects(:basic_auth).with(@username, @password)
|
|
41
|
+
Net::HTTP::Post.any_instance.expects(:set_form_data).with('status' => @update_message, 'in_reply_to_status_id' => "1234567890")
|
|
42
|
+
|
|
43
|
+
assert_nothing_raised do
|
|
44
|
+
@response = @client.statuses_update(@update_message, "1234567890")
|
|
45
|
+
end
|
|
37
46
|
assert_instance_of Net::HTTPOK, @response
|
|
38
47
|
end
|
|
39
48
|
|
|
40
|
-
end # context "successfully"
|
|
49
|
+
end # context "with successfully response"
|
|
41
50
|
|
|
42
|
-
context "
|
|
51
|
+
context "with error response" do
|
|
43
52
|
setup do
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
:string => "503 Service unavailable",
|
|
47
|
-
:status => ["503", "Service unavailable"])
|
|
53
|
+
response_status = ["503", "Service unavailable"]
|
|
54
|
+
fake_web_on_post("http://twitter.com/statuses/update.json", :string => response_status.join(" "), :status => response_status)
|
|
48
55
|
end
|
|
49
56
|
|
|
50
57
|
should "raise for http response status on 503" do
|
|
51
58
|
Net::HTTP::Post.any_instance.expects(:basic_auth).with(@username, @password)
|
|
52
59
|
Net::HTTP::Post.any_instance.expects(:set_form_data).with('status' => @update_message, 'in_reply_to_status_id' => nil)
|
|
60
|
+
|
|
53
61
|
assert_raises Net::HTTPFatalError do
|
|
54
|
-
@
|
|
62
|
+
@client.statuses_update(@update_message)
|
|
55
63
|
end
|
|
56
|
-
# assert_instance_of Net::HTTPServiceUnavailable, @response
|
|
57
64
|
end
|
|
58
65
|
|
|
59
|
-
end # context "
|
|
66
|
+
end # context "with error response"
|
|
60
67
|
|
|
61
68
|
|
|
62
|
-
end # context "
|
|
69
|
+
end # context "on POST to statuses/update"
|
|
70
|
+
|
|
71
|
+
context "on POST to direct_messages/new" do
|
|
72
|
+
setup do
|
|
73
|
+
fake_web_on_post("http://twitter.com/direct_messages/new.json")
|
|
74
|
+
@anoter_user = "1234567890"
|
|
75
|
+
@text = "Hello World!"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
should "allow the user to post a direct message to another Twitter's user" do
|
|
79
|
+
Net::HTTP::Post.any_instance.expects(:basic_auth).with(@username, @password)
|
|
80
|
+
Net::HTTP::Post.any_instance.expects(:set_form_data).with('user'=>@another_user, 'text'=>@text )
|
|
81
|
+
|
|
82
|
+
assert_nothing_raised do
|
|
83
|
+
@response = @client.direct_messages_new(@another_user, @text)
|
|
84
|
+
end
|
|
85
|
+
assert_instance_of(Net::HTTPOK, @response)
|
|
86
|
+
end
|
|
87
|
+
end # context "on POST to direct_messages/new"
|
|
63
88
|
|
|
64
89
|
|
|
65
90
|
end # context "A valid Tuiter client"
|
|
66
|
-
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../test_helper"
|
|
2
|
+
|
|
3
|
+
class RateLimitTest < Test::Unit::TestCase
|
|
4
|
+
RATE_LIMIT_ATTRIBUTES = %w(reset_time reset_time_in_seconds reset_window remaining_hits hourly_limit)
|
|
5
|
+
|
|
6
|
+
context "RateLimit" do
|
|
7
|
+
should_attr_accessor_for Tuiter::RateLimit, RATE_LIMIT_ATTRIBUTES
|
|
8
|
+
|
|
9
|
+
should_load_attribute_on_initialize Tuiter::RateLimit, "reset_time_in_seconds", Time.at(1234567890), 1234567890
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
end # context "RateLimit"
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: webco-tuiter
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Manoel Lemos
|
|
@@ -10,7 +10,7 @@ autorequire:
|
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
12
|
|
|
13
|
-
date: 2009-04-
|
|
13
|
+
date: 2009-04-24 00:00:00 -07:00
|
|
14
14
|
default_executable:
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
@@ -44,8 +44,14 @@ files:
|
|
|
44
44
|
- lib/tuiter/data/rate_limit.rb
|
|
45
45
|
- lib/tuiter/data/status.rb
|
|
46
46
|
- lib/tuiter/data/user.rb
|
|
47
|
+
- lib/tuiter/methods
|
|
48
|
+
- lib/tuiter/methods/account.rb
|
|
49
|
+
- lib/tuiter/methods/direct_message.rb
|
|
50
|
+
- lib/tuiter/methods/friendship.rb
|
|
51
|
+
- lib/tuiter/methods/social_graph.rb
|
|
52
|
+
- lib/tuiter/methods/status.rb
|
|
53
|
+
- lib/tuiter/methods/user.rb
|
|
47
54
|
- lib/tuiter/version.rb
|
|
48
|
-
- lib/tuiter.log
|
|
49
55
|
- lib/tuiter.rb
|
|
50
56
|
- examples/basic_example.rb
|
|
51
57
|
- test/fixtures
|
|
@@ -59,6 +65,7 @@ files:
|
|
|
59
65
|
- test/test_helper.rb
|
|
60
66
|
- test/unit
|
|
61
67
|
- test/unit/client_test.rb
|
|
68
|
+
- test/unit/rate_limit_test.rb
|
|
62
69
|
- test/unit/status_test.rb
|
|
63
70
|
- test/unit/user_test.rb
|
|
64
71
|
has_rdoc: false
|