sml-twitter 0.7.3

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.
Files changed (61) hide show
  1. data/History +226 -0
  2. data/License +20 -0
  3. data/Notes +33 -0
  4. data/README.rdoc +19 -0
  5. data/Rakefile +40 -0
  6. data/VERSION.yml +5 -0
  7. data/examples/connect.rb +30 -0
  8. data/examples/friendship_existance.rb +13 -0
  9. data/examples/helpers/config_store.rb +38 -0
  10. data/examples/httpauth.rb +11 -0
  11. data/examples/ids.rb +13 -0
  12. data/examples/lists.rb +11 -0
  13. data/examples/oauth.rb +27 -0
  14. data/examples/search.rb +15 -0
  15. data/examples/timeline.rb +19 -0
  16. data/examples/unauthorized.rb +16 -0
  17. data/examples/update.rb +11 -0
  18. data/examples/user.rb +5 -0
  19. data/lib/twitter.rb +63 -0
  20. data/lib/twitter/base.rb +249 -0
  21. data/lib/twitter/httpauth.rb +35 -0
  22. data/lib/twitter/oauth.rb +56 -0
  23. data/lib/twitter/request.rb +118 -0
  24. data/lib/twitter/search.rb +111 -0
  25. data/lib/twitter/trends.rb +29 -0
  26. data/test/fixtures/firehose.json +1 -0
  27. data/test/fixtures/follower_ids.json +1 -0
  28. data/test/fixtures/friend_ids.json +1 -0
  29. data/test/fixtures/friends_timeline.json +1 -0
  30. data/test/fixtures/friendship.json +1 -0
  31. data/test/fixtures/list.json +1 -0
  32. data/test/fixtures/list_statuses.json +1 -0
  33. data/test/fixtures/list_subscriptions.json +1 -0
  34. data/test/fixtures/list_users.json +1 -0
  35. data/test/fixtures/lists.json +1 -0
  36. data/test/fixtures/memberships.json +1 -0
  37. data/test/fixtures/mentions.json +1 -0
  38. data/test/fixtures/rate_limit_exceeded.json +1 -0
  39. data/test/fixtures/search.json +1 -0
  40. data/test/fixtures/search_from_jnunemaker.json +1 -0
  41. data/test/fixtures/status.json +1 -0
  42. data/test/fixtures/status_show.json +1 -0
  43. data/test/fixtures/trends_current.json +1 -0
  44. data/test/fixtures/trends_current_exclude.json +1 -0
  45. data/test/fixtures/trends_daily.json +1 -0
  46. data/test/fixtures/trends_daily_date.json +1 -0
  47. data/test/fixtures/trends_daily_exclude.json +1 -0
  48. data/test/fixtures/trends_weekly.json +1 -0
  49. data/test/fixtures/trends_weekly_date.json +1 -0
  50. data/test/fixtures/trends_weekly_exclude.json +1 -0
  51. data/test/fixtures/user.json +1 -0
  52. data/test/fixtures/user_timeline.json +1 -0
  53. data/test/test_helper.rb +51 -0
  54. data/test/twitter/base_test.rb +214 -0
  55. data/test/twitter/httpauth_test.rb +76 -0
  56. data/test/twitter/oauth_test.rb +108 -0
  57. data/test/twitter/request_test.rb +217 -0
  58. data/test/twitter/search_test.rb +159 -0
  59. data/test/twitter/trends_test.rb +95 -0
  60. data/test/twitter_test.rb +38 -0
  61. metadata +203 -0
data/examples/ids.rb ADDED
@@ -0,0 +1,13 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
2
+ require File.join(File.dirname(__FILE__), 'helpers', 'config_store')
3
+ require 'pp'
4
+
5
+ config = ConfigStore.new("#{ENV['HOME']}/.twitter")
6
+
7
+ oauth = Twitter::OAuth.new(config['token'], config['secret'])
8
+ oauth.authorize_from_access(config['atoken'], config['asecret'])
9
+
10
+ client = Twitter::Base.new(oauth)
11
+
12
+ puts client.friend_ids
13
+ puts client.follower_ids
data/examples/lists.rb ADDED
@@ -0,0 +1,11 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
2
+ require File.join(File.dirname(__FILE__), 'helpers', 'config_store')
3
+ require 'pp'
4
+
5
+ config = ConfigStore.new("#{ENV['HOME']}/.twitter")
6
+
7
+ httpauth = Twitter::HTTPAuth.new(config['email'], config['password'])
8
+ base = Twitter::Base.new(httpauth)
9
+
10
+ pp base.lists('pengwynn')
11
+ pp base.list_members('pengwynn', 'rubyists')
data/examples/oauth.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'pp'
2
+ require 'pathname'
3
+ dir = Pathname(__FILE__).dirname.expand_path
4
+ require (dir + '..' + 'lib' + 'twitter').expand_path
5
+ require dir + 'helpers' + 'config_store'
6
+
7
+ config = ConfigStore.new("#{ENV['HOME']}/.twitter")
8
+ oauth = Twitter::OAuth.new(config['token'], config['secret'])
9
+ rtoken = oauth.request_token.token
10
+ rsecret = oauth.request_token.secret
11
+
12
+ puts "> redirecting you to twitter to authorize..."
13
+ %x(open #{oauth.request_token.authorize_url})
14
+
15
+ print "> what was the PIN twitter provided you with? "
16
+ pin = gets.chomp
17
+
18
+ begin
19
+ oauth.authorize_from_request(rtoken, rsecret, pin)
20
+
21
+ twitter = Twitter::Base.new(oauth)
22
+ twitter.user_timeline.each do |tweet|
23
+ puts "#{tweet.user.screen_name}: #{tweet.text}"
24
+ end
25
+ rescue OAuth::Unauthorized
26
+ puts "> FAIL!"
27
+ end
@@ -0,0 +1,15 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
2
+ require 'pp'
3
+
4
+ search = Twitter::Search.new.from('jnunemaker')
5
+
6
+ puts '*'*50, 'First Run', '*'*50
7
+ search.each { |result| pp result }
8
+
9
+ puts '*'*50, 'Second Run', '*'*50
10
+ search.each { |result| pp result }
11
+
12
+ puts '*'*50, 'Parameter Check', '*'*50
13
+ pp Twitter::Search.new('#austineats').fetch().results.first
14
+ pp Twitter::Search.new('#austineats').page(2).fetch().results.first
15
+ pp Twitter::Search.new('#austineats').since(1412737343).fetch().results.first
@@ -0,0 +1,19 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
2
+ require File.join(File.dirname(__FILE__), 'helpers', 'config_store')
3
+ require 'pp'
4
+
5
+ config = ConfigStore.new("#{ENV['HOME']}/.twitter")
6
+
7
+ oauth = Twitter::OAuth.new(config['token'], config['secret'])
8
+ oauth.authorize_from_access(config['atoken'], config['asecret'])
9
+
10
+ client = Twitter::Base.new(oauth)
11
+
12
+ pp client.friends_timeline
13
+ puts '*'*50
14
+
15
+ pp client.user_timeline
16
+ puts '*'*50
17
+
18
+ pp client.replies
19
+ puts '*'*50
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
2
+ require 'pp'
3
+
4
+ puts 'User', '*'*50
5
+ pp Twitter.user('jnunemaker')
6
+ pp Twitter.user('snitch_test')
7
+
8
+ puts 'Status', '*'*50
9
+ pp Twitter.status(1533815199)
10
+
11
+ puts 'Friend Ids', '*'*50
12
+ pp Twitter.friend_ids('jnunemaker')
13
+
14
+ puts 'Follower Ids', '*'*50
15
+ pp Twitter.follower_ids('jnunemaker')
16
+
@@ -0,0 +1,11 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
2
+ require File.join(File.dirname(__FILE__), 'helpers', 'config_store')
3
+ require 'pp'
4
+
5
+ config = ConfigStore.new("#{ENV['HOME']}/.twitter")
6
+
7
+ oauth = Twitter::OAuth.new(config['token'], config['secret'])
8
+ oauth.authorize_from_access(config['atoken'], config['asecret'])
9
+
10
+ client = Twitter::Base.new(oauth)
11
+ pp client.update('This is an update from the twitter gem')
data/examples/user.rb ADDED
@@ -0,0 +1,5 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
2
+ require 'pp'
3
+
4
+ pp Twitter.user('jnunemaker')
5
+ pp Twitter.user('snitch_test')
data/lib/twitter.rb ADDED
@@ -0,0 +1,63 @@
1
+ require 'forwardable'
2
+ require 'rubygems'
3
+
4
+ gem 'oauth', '~> 0.3.5'
5
+ require 'oauth'
6
+
7
+ gem 'mash', '~> 0.1.1'
8
+ require 'mash'
9
+
10
+ gem 'httparty', '~> 0.4.3'
11
+ require 'httparty'
12
+
13
+ module Twitter
14
+ class TwitterError < StandardError
15
+ attr_reader :data
16
+
17
+ def initialize(data)
18
+ @data = data
19
+ super
20
+ end
21
+ end
22
+
23
+ class RateLimitExceeded < TwitterError; end
24
+ class Unauthorized < TwitterError; end
25
+ class General < TwitterError; end
26
+
27
+ class Unavailable < StandardError; end
28
+ class InformTwitter < StandardError; end
29
+ class NotFound < StandardError; end
30
+
31
+
32
+ def self.firehose
33
+ response = HTTParty.get('http://twitter.com/statuses/public_timeline.json', :format => :json)
34
+ response.map { |tweet| Mash.new(tweet) }
35
+ end
36
+
37
+ def self.user(id)
38
+ response = HTTParty.get("http://twitter.com/users/show/#{id}.json", :format => :json)
39
+ Mash.new(response)
40
+ end
41
+
42
+ def self.status(id)
43
+ response = HTTParty.get("http://twitter.com/statuses/show/#{id}.json", :format => :json)
44
+ Mash.new(response)
45
+ end
46
+
47
+ def self.friend_ids(id)
48
+ HTTParty.get("http://twitter.com/friends/ids/#{id}.json", :format => :json)
49
+ end
50
+
51
+ def self.follower_ids(id)
52
+ HTTParty.get("http://twitter.com/followers/ids/#{id}.json", :format => :json)
53
+ end
54
+ end
55
+
56
+ directory = File.expand_path(File.dirname(__FILE__))
57
+
58
+ require File.join(directory, 'twitter', 'oauth')
59
+ require File.join(directory, 'twitter', 'httpauth')
60
+ require File.join(directory, 'twitter', 'request')
61
+ require File.join(directory, 'twitter', 'base')
62
+ require File.join(directory, 'twitter', 'search')
63
+ require File.join(directory, 'twitter', 'trends')
@@ -0,0 +1,249 @@
1
+ module Twitter
2
+ class Base
3
+ extend Forwardable
4
+
5
+ def_delegators :client, :get, :post, :put, :delete
6
+
7
+ attr_reader :client
8
+
9
+ def initialize(client)
10
+ @client = client
11
+ end
12
+
13
+ # Options: since_id, max_id, count, page, since
14
+ def friends_timeline(query={})
15
+ perform_get('/statuses/friends_timeline.json', :query => query)
16
+ end
17
+
18
+ # Options: id, user_id, screen_name, since_id, max_id, page, since, count
19
+
20
+ def user_timeline(query={})
21
+ perform_get('/statuses/user_timeline.json', :query => query)
22
+ end
23
+
24
+ def status(id)
25
+ perform_get("/statuses/show/#{id}.json")
26
+ end
27
+
28
+ # Options: in_reply_to_status_id
29
+ def update(status, query={})
30
+ perform_post("/statuses/update.json", :body => {:status => status}.merge(query))
31
+ end
32
+
33
+ # DEPRECATED: Use #mentions instead
34
+ #
35
+ # Options: since_id, max_id, since, page
36
+ def replies(query={})
37
+ warn("DEPRECATED: #replies is deprecated by Twitter; use #mentions instead")
38
+ perform_get('/statuses/replies.json', :query => query)
39
+ end
40
+
41
+ # Options: since_id, max_id, count, page
42
+ def mentions(query={})
43
+ perform_get('/statuses/mentions.json', :query => query)
44
+ end
45
+
46
+ def status_destroy(id)
47
+ perform_post("/statuses/destroy/#{id}.json")
48
+ end
49
+
50
+ # Options: id, user_id, screen_name, page
51
+ def friends(query={})
52
+ perform_get('/statuses/friends.json', :query => query)
53
+ end
54
+
55
+ # Options: id, user_id, screen_name, page
56
+ def followers(query={})
57
+ perform_get('/statuses/followers.json', :query => query)
58
+ end
59
+
60
+ def user(id, query={})
61
+ perform_get("/users/show/#{id}.json", :query => query)
62
+ end
63
+
64
+ # Options: since, since_id, page
65
+ def direct_messages(query={})
66
+ perform_get("/direct_messages.json", :query => query)
67
+ end
68
+
69
+ # Options: since, since_id, page
70
+ def direct_messages_sent(query={})
71
+ perform_get("/direct_messages/sent.json", :query => query)
72
+ end
73
+
74
+ def direct_message_create(user, text)
75
+ perform_post("/direct_messages/new.json", :body => {:user => user, :text => text})
76
+ end
77
+
78
+ def direct_message_destroy(id)
79
+ perform_post("/direct_messages/destroy/#{id}.json")
80
+ end
81
+
82
+ def friendship_create(id, follow=false)
83
+ body = {}
84
+ body.merge!(:follow => follow) if follow
85
+ perform_post("/friendships/create/#{id}.json", :body => body)
86
+ end
87
+
88
+ def friendship_destroy(id)
89
+ perform_post("/friendships/destroy/#{id}.json")
90
+ end
91
+
92
+ def friendship_exists?(a, b)
93
+ perform_get("/friendships/exists.json", :query => {:user_a => a, :user_b => b})
94
+ end
95
+
96
+ def friendship_show(query)
97
+ perform_get("/friendships/show.json", :query => query)
98
+ end
99
+
100
+ # Options: id, user_id, screen_name
101
+ def friend_ids(query={})
102
+ perform_get("/friends/ids.json", :query => query, :mash => false)
103
+ end
104
+
105
+ # Options: id, user_id, screen_name
106
+ def follower_ids(query={})
107
+ perform_get("/followers/ids.json", :query => query, :mash => false)
108
+ end
109
+
110
+ def verify_credentials
111
+ perform_get("/account/verify_credentials.json")
112
+ end
113
+
114
+ # Device must be sms, im or none
115
+ def update_delivery_device(device)
116
+ perform_post('/account/update_delivery_device.json', :body => {:device => device})
117
+ end
118
+
119
+ # One or more of the following must be present:
120
+ # profile_background_color, profile_text_color, profile_link_color,
121
+ # profile_sidebar_fill_color, profile_sidebar_border_color
122
+ def update_profile_colors(colors={})
123
+ perform_post('/account/update_profile_colors.json', :body => colors)
124
+ end
125
+
126
+ def rate_limit_status
127
+ perform_get('/account/rate_limit_status.json')
128
+ end
129
+
130
+ # One or more of the following must be present:
131
+ # name, email, url, location, description
132
+ def update_profile(body={})
133
+ perform_post('/account/update_profile.json', :body => body)
134
+ end
135
+
136
+ # Options: id, page
137
+ def favorites(query={})
138
+ perform_get('/favorites.json', :query => query)
139
+ end
140
+
141
+ def favorite_create(id)
142
+ perform_post("/favorites/create/#{id}.json")
143
+ end
144
+
145
+ def favorite_destroy(id)
146
+ perform_post("/favorites/destroy/#{id}.json")
147
+ end
148
+
149
+ def enable_notifications(id)
150
+ perform_post("/notifications/follow/#{id}.json")
151
+ end
152
+
153
+ def disable_notifications(id)
154
+ perform_post("/notifications/leave/#{id}.json")
155
+ end
156
+
157
+ def block(id)
158
+ perform_post("/blocks/create/#{id}.json")
159
+ end
160
+
161
+ def unblock(id)
162
+ perform_post("/blocks/destroy/#{id}.json")
163
+ end
164
+
165
+ def help
166
+ perform_get('/help/test.json')
167
+ end
168
+
169
+ def list_create(list_owner_username, options)
170
+ perform_post("/#{list_owner_username}/lists.json", :body => {:user => list_owner_username}.merge(options))
171
+ end
172
+
173
+ def list_update(list_owner_username, slug, options)
174
+ perform_put("/#{list_owner_username}/lists/#{slug}.json", :body => options)
175
+ end
176
+
177
+ def list_delete(list_owner_username, slug)
178
+ perform_delete("/#{list_owner_username}/lists/#{slug}.json")
179
+ end
180
+
181
+ def lists(list_owner_username=nil)
182
+ path = "http://api.twitter.com/1"
183
+ path += "/#{list_owner_username}" if list_owner_username
184
+ path += "/lists.json"
185
+ perform_get(path)
186
+ end
187
+
188
+ def list(list_owner_username, slug)
189
+ perform_get("/#{list_owner_username}/lists/#{slug}.json")
190
+ end
191
+
192
+ def list_timeline(list_owner_username, slug)
193
+ perform_get("/#{list_owner_username}/lists/#{slug}/statuses.json")
194
+ end
195
+
196
+ def memberships(list_owner_username)
197
+ perform_get("/#{list_owner_username}/lists/memberships.json")
198
+ end
199
+
200
+ def list_members(list_owner_username, slug)
201
+ perform_get("/#{list_owner_username}/#{slug}/members.json")
202
+ end
203
+
204
+ def list_add_member(list_owner_username, slug, new_id)
205
+ perform_post("/#{list_owner_username}/#{slug}/members.json", :body => {:id => new_id})
206
+ end
207
+
208
+ def list_remove_member(list_owner_username, slug, id)
209
+ perform_delete("/#{list_owner_username}/#{slug}/members.json", :body => {:id => id})
210
+ end
211
+
212
+ def is_list_member?(list_owner_username, slug, id)
213
+ perform_get("/#{list_owner_username}/#{slug}/members/#{id}.json").error.nil?
214
+ end
215
+
216
+ def list_subscribers(list_owner_username, slug)
217
+ perform_get("/#{list_owner_username}/#{slug}/subscribers.json")
218
+ end
219
+
220
+ def list_subscribe(list_owner_username, slug)
221
+ perform_post("/#{list_owner_username}/#{slug}/subscribers.json")
222
+ end
223
+
224
+ def list_unsubscribe(list_owner_username, slug)
225
+ perform_delete("/#{list_owner_username}/#{slug}/subscribers.json")
226
+ end
227
+
228
+ def list_subscriptions(list_owner_username)
229
+ perform_get("/#{list_owner_username}/lists/subscriptions.json")
230
+ end
231
+
232
+ private
233
+ def perform_get(path, options={})
234
+ Twitter::Request.get(self, path, options)
235
+ end
236
+
237
+ def perform_post(path, options={})
238
+ Twitter::Request.post(self, path, options)
239
+ end
240
+
241
+ def perform_put(path, options={})
242
+ Twitter::Request.put(self, path, options)
243
+ end
244
+
245
+ def perform_delete(path, options={})
246
+ Twitter::Request.delete(self, path, options)
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,35 @@
1
+ module Twitter
2
+ class HTTPAuth
3
+ include HTTParty
4
+ format :plain
5
+
6
+ attr_reader :username, :password, :options
7
+
8
+ def initialize(username, password, options={})
9
+ @username, @password = username, password
10
+ @options = {:ssl => false}.merge(options)
11
+ self.class.base_uri "http#{'s' if options[:ssl]}://twitter.com"
12
+ end
13
+
14
+ def get(uri, headers={})
15
+ self.class.get(uri, :headers => headers, :basic_auth => basic_auth)
16
+ end
17
+
18
+ def post(uri, body={}, headers={})
19
+ self.class.post(uri, :body => body, :headers => headers, :basic_auth => basic_auth)
20
+ end
21
+
22
+ def put(uri, body={}, headers={})
23
+ self.class.put(uri, :body => body, :headers => headers, :basic_auth => basic_auth)
24
+ end
25
+
26
+ def delete(uri, body={}, headers={})
27
+ self.class.delete(uri, :body => body, :headers => headers, :basic_auth => basic_auth)
28
+ end
29
+
30
+ private
31
+ def basic_auth
32
+ @basic_auth ||= {:username => @username, :password => @password}
33
+ end
34
+ end
35
+ end