tweetstream 1.1.0.rc1 → 1.1.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of tweetstream might be problematic. Click here for more details.
- data/README.md +31 -6
- data/Rakefile +2 -0
- data/examples/growl_daemon.rb +10 -2
- data/examples/oauth.rb +6 -2
- data/examples/userstream.rb +27 -0
- data/lib/tweetstream.rb +18 -28
- data/lib/tweetstream/client.rb +146 -41
- data/lib/tweetstream/configuration.rb +3 -0
- data/lib/tweetstream/daemon.rb +11 -3
- data/lib/tweetstream/direct_message.rb +6 -0
- data/lib/tweetstream/error.rb +15 -0
- data/lib/tweetstream/status.rb +1 -1
- data/lib/tweetstream/version.rb +1 -1
- data/spec/data/direct_messages.json +1 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/tweetstream/client_spec.rb +121 -2
- data/spec/tweetstream/direct_message_spec.rb +21 -0
- data/spec/tweetstream/status_spec.rb +5 -5
- data/spec/tweetstream_spec.rb +9 -3
- metadata +31 -24
data/README.md
CHANGED
@@ -51,6 +51,33 @@ user ids:
|
|
51
51
|
The methods available to TweetStream::Client will be kept in parity
|
52
52
|
with the methods available on the Streaming API wiki page.
|
53
53
|
|
54
|
+
Using the Twitter Userstream
|
55
|
+
----------------------------
|
56
|
+
|
57
|
+
Using the Twitter userstream works similarly to the regular streaming, except you use the userstream method.
|
58
|
+
|
59
|
+
# Use 'userstream' to get message from your stream
|
60
|
+
TweetStream::Client.new.userstream do |status|
|
61
|
+
puts status.text
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
You also can use method hooks for both regular timeline statuses and direct messages.
|
66
|
+
|
67
|
+
client = TweetStream::Client.new
|
68
|
+
|
69
|
+
client.on_direct_message do |direct_message|
|
70
|
+
puts "direct message"
|
71
|
+
puts direct_message.text
|
72
|
+
end
|
73
|
+
|
74
|
+
client.on_timeline_status do |status|
|
75
|
+
puts "timeline status"
|
76
|
+
puts status.text
|
77
|
+
end
|
78
|
+
|
79
|
+
client.userstream
|
80
|
+
|
54
81
|
Configuration and Changes in 1.1.0
|
55
82
|
----------------------------------
|
56
83
|
|
@@ -96,8 +123,7 @@ specify a parser during configuration:
|
|
96
123
|
config.parser = :yajl
|
97
124
|
end.
|
98
125
|
|
99
|
-
Available options are `:yajl`, `:json_gem
|
100
|
-
`:json_pure`, and `:active_support`.
|
126
|
+
Available options are `:yajl`, `:json_gem`, `:json_pure`, and `:ok_json`.
|
101
127
|
|
102
128
|
Handling Deletes and Rate Limitations
|
103
129
|
-------------------------------------
|
@@ -189,17 +215,16 @@ It is also possible to create a daemonized script quite easily
|
|
189
215
|
using the TweetStream library:
|
190
216
|
|
191
217
|
# The third argument is an optional process name
|
192
|
-
TweetStream::Daemon.new('
|
218
|
+
TweetStream::Daemon.new('tracker').track('term1', 'term2') do |status|
|
193
219
|
# do something in the background
|
194
220
|
end
|
195
221
|
|
196
|
-
If you put the above into a script and run the script with `ruby scriptname.rb`,
|
197
|
-
as start, stop, and run.
|
222
|
+
If you put the above into a script and run the script with `ruby scriptname.rb`,
|
223
|
+
you will see a list of daemonization commands such as start, stop, and run.
|
198
224
|
|
199
225
|
TODO
|
200
226
|
----
|
201
227
|
|
202
|
-
* UserStream support
|
203
228
|
* SiteStream support
|
204
229
|
|
205
230
|
Note on Patches/Pull Requests
|
data/Rakefile
CHANGED
data/examples/growl_daemon.rb
CHANGED
@@ -4,11 +4,19 @@ require 'ruby-growl'
|
|
4
4
|
|
5
5
|
if args_start = ARGV.index('--')
|
6
6
|
username, password = ARGV[args_start + 1].split(':')
|
7
|
-
tracks = ARGV[args_start + 2 .. -1]
|
7
|
+
tracks = ARGV[args_start + 2 .. -1]
|
8
8
|
puts "Starting a GrowlTweet to track: #{tracks.inspect}"
|
9
9
|
end
|
10
10
|
|
11
|
-
TweetStream
|
11
|
+
TweetStream.configure do |config|
|
12
|
+
config.consumer_key = 'abcdefghijklmnopqrstuvwxyz'
|
13
|
+
config.consumer_secret = '0123456789'
|
14
|
+
config.oauth_token = 'abcdefghijklmnopqrstuvwxyz'
|
15
|
+
config.oauth_token_secret = '0123456789'
|
16
|
+
config.auth_method = :oauth
|
17
|
+
end
|
18
|
+
|
19
|
+
TweetStream::Daemon.new('tracker').track(*tracks) do |status|
|
12
20
|
g = Growl.new 'localhost', 'growltweet', ['tweet']
|
13
21
|
g.notify 'tweet', status.user.screen_name, status.text
|
14
22
|
end
|
data/examples/oauth.rb
CHANGED
@@ -10,8 +10,12 @@ TweetStream.configure do |config|
|
|
10
10
|
config.parser = :yajl
|
11
11
|
end
|
12
12
|
|
13
|
-
TweetStream::Client.new
|
13
|
+
client = TweetStream::Client.new
|
14
|
+
|
15
|
+
client.on_error do |message|
|
14
16
|
puts message
|
15
|
-
end
|
17
|
+
end
|
18
|
+
|
19
|
+
client.track("yankees") do |status|
|
16
20
|
puts "#{status.text}"
|
17
21
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'yajl'
|
2
|
+
require 'tweetstream'
|
3
|
+
|
4
|
+
TweetStream.configure do |config|
|
5
|
+
config.consumer_key = 'abcdefghijklmnopqrstuvwxyz'
|
6
|
+
config.consumer_secret = '0123456789'
|
7
|
+
config.oauth_token = 'abcdefghijklmnopqrstuvwxyz'
|
8
|
+
config.oauth_token_secret = '0123456789'
|
9
|
+
config.auth_method = :oauth
|
10
|
+
config.parser = :yajl
|
11
|
+
end
|
12
|
+
|
13
|
+
client = TweetStream::Client.new
|
14
|
+
|
15
|
+
client.on_error do |message|
|
16
|
+
puts message
|
17
|
+
end
|
18
|
+
|
19
|
+
client.on_direct_message do |direct_message|
|
20
|
+
puts direct_message.text
|
21
|
+
end
|
22
|
+
|
23
|
+
client.on_timeline_status do |status|
|
24
|
+
puts status.text
|
25
|
+
end
|
26
|
+
|
27
|
+
client.userstream
|
data/lib/tweetstream.rb
CHANGED
@@ -2,41 +2,31 @@ require 'tweetstream/configuration'
|
|
2
2
|
require 'tweetstream/client'
|
3
3
|
require 'tweetstream/hash'
|
4
4
|
require 'tweetstream/status'
|
5
|
+
require 'tweetstream/direct_message'
|
5
6
|
require 'tweetstream/user'
|
7
|
+
require 'tweetstream/error'
|
6
8
|
require 'tweetstream/daemon'
|
7
9
|
|
8
10
|
module TweetStream
|
9
11
|
extend Configuration
|
10
12
|
|
11
|
-
class
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
attr_accessor :timeout, :retries
|
18
|
-
def initialize(timeout, retries)
|
19
|
-
self.timeout = timeout
|
20
|
-
self.retries = retries
|
21
|
-
super("Failed to reconnect after #{retries} tries.")
|
13
|
+
class << self
|
14
|
+
# Alias for TweetStream::Client.new
|
15
|
+
#
|
16
|
+
# @return [TweetStream::Client]
|
17
|
+
def new(options={})
|
18
|
+
TweetStream::Client.new(options)
|
22
19
|
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# Alias for TweetStream::Client.new
|
26
|
-
#
|
27
|
-
# @return [TweetStream::Client]
|
28
|
-
def self.client(options={})
|
29
|
-
TweetStream::Client.new(options)
|
30
|
-
end
|
31
20
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
21
|
+
# Delegate to TweetStream::Client
|
22
|
+
def method_missing(method, *args, &block)
|
23
|
+
return super unless new.respond_to?(method)
|
24
|
+
new.send(method, *args, &block)
|
25
|
+
end
|
37
26
|
|
38
|
-
|
39
|
-
|
40
|
-
|
27
|
+
# Delegate to TweetStream::Client
|
28
|
+
def respond_to?(method, include_private = false)
|
29
|
+
new.respond_to?(method, include_private) || super(method, include_private)
|
30
|
+
end
|
41
31
|
end
|
42
|
-
end
|
32
|
+
end
|
data/lib/tweetstream/client.rb
CHANGED
@@ -13,18 +13,17 @@ module TweetStream
|
|
13
13
|
# methods and provide a block that will perform actions on
|
14
14
|
# a yielded TweetStream::Status. For example:
|
15
15
|
#
|
16
|
-
# TweetStream::Client.new
|
16
|
+
# TweetStream::Client.new.track('fail') do |status|
|
17
17
|
# puts "[#{status.user.screen_name}] #{status.text}"
|
18
18
|
# end
|
19
19
|
#
|
20
20
|
# For information about a daemonized TweetStream client,
|
21
21
|
# view the TweetStream::Daemon class.
|
22
22
|
class Client
|
23
|
-
attr_accessor :username, :password
|
24
|
-
attr_reader :parser
|
25
23
|
|
26
24
|
# @private
|
27
25
|
attr_accessor *Configuration::VALID_OPTIONS_KEYS
|
26
|
+
attr_accessor :timer
|
28
27
|
|
29
28
|
# Creates a new API
|
30
29
|
def initialize(options={})
|
@@ -39,16 +38,6 @@ module TweetStream
|
|
39
38
|
parser_from(parser)
|
40
39
|
end
|
41
40
|
|
42
|
-
# Create a new client with the Twitter credentials
|
43
|
-
# of the account you want to be using its API quota.
|
44
|
-
# You may also set the JSON parsing library as specified
|
45
|
-
# in the #parser= setter.
|
46
|
-
# def initialize(ouser, pass, parser = :json_gem)
|
47
|
-
# self.username = user
|
48
|
-
# self.password = pass
|
49
|
-
# self.parser = parser
|
50
|
-
# end
|
51
|
-
|
52
41
|
# Returns all public statuses. The Firehose is not a generally
|
53
42
|
# available resource. Few applications require this level of access.
|
54
43
|
# Creative use of a combination of other resources and various access
|
@@ -122,10 +111,15 @@ module TweetStream
|
|
122
111
|
start('statuses/filter', query_params.merge(:method => :post), &block)
|
123
112
|
end
|
124
113
|
|
114
|
+
# Make a call to the userstream api for currently authenticated user
|
115
|
+
def userstream(&block)
|
116
|
+
start('', :extra_stream_parameters => {:host => "userstream.twitter.com", :path => "/2/user.json"}, &block)
|
117
|
+
end
|
118
|
+
|
125
119
|
# Set a Proc to be run when a deletion notice is received
|
126
120
|
# from the Twitter stream. For example:
|
127
121
|
#
|
128
|
-
# @client = TweetStream::Client.new
|
122
|
+
# @client = TweetStream::Client.new
|
129
123
|
# @client.on_delete do |status_id, user_id|
|
130
124
|
# Tweet.delete(status_id)
|
131
125
|
# end
|
@@ -146,7 +140,7 @@ module TweetStream
|
|
146
140
|
# Set a Proc to be run when a rate limit notice is received
|
147
141
|
# from the Twitter stream. For example:
|
148
142
|
#
|
149
|
-
# @client = TweetStream::Client.new
|
143
|
+
# @client = TweetStream::Client.new
|
150
144
|
# @client.on_limit do |discarded_count|
|
151
145
|
# # Make note of discarded count
|
152
146
|
# end
|
@@ -168,7 +162,7 @@ module TweetStream
|
|
168
162
|
# processing of the stream. Note that TweetStream will automatically
|
169
163
|
# try to reconnect, this is for reference only. Don't panic!
|
170
164
|
#
|
171
|
-
# @client = TweetStream::Client.new
|
165
|
+
# @client = TweetStream::Client.new
|
172
166
|
# @client.on_error do |message|
|
173
167
|
# # Make note of error message
|
174
168
|
# end
|
@@ -186,10 +180,73 @@ module TweetStream
|
|
186
180
|
end
|
187
181
|
end
|
188
182
|
|
183
|
+
# Set a Proc to be run when a direct message is encountered in the
|
184
|
+
# processing of the stream.
|
185
|
+
#
|
186
|
+
# @client = TweetStream::Client.new
|
187
|
+
# @client.on_direct_message do |direct_message|
|
188
|
+
# # do something with the direct message
|
189
|
+
# end
|
190
|
+
#
|
191
|
+
# Block must take one argument: the direct message.
|
192
|
+
# If no block is given, it will return the currently set
|
193
|
+
# direct message proc. When a block is given, the TweetStream::Client
|
194
|
+
# object is returned to allow for chaining.
|
195
|
+
def on_direct_message(&block)
|
196
|
+
if block_given?
|
197
|
+
@on_direct_message = block
|
198
|
+
self
|
199
|
+
else
|
200
|
+
@on_direct_message
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Set a Proc to be run whenever anything is encountered in the
|
205
|
+
# processing of the stream.
|
206
|
+
#
|
207
|
+
# @client = TweetStream::Client.new
|
208
|
+
# @client.on_anything do |status|
|
209
|
+
# # do something with the status
|
210
|
+
# end
|
211
|
+
#
|
212
|
+
# Block can take one or two arguments. |status (, client)|
|
213
|
+
# If no block is given, it will return the currently set
|
214
|
+
# timeline status proc. When a block is given, the TweetStream::Client
|
215
|
+
# object is returned to allow for chaining.
|
216
|
+
def on_anything(&block)
|
217
|
+
if block_given?
|
218
|
+
@on_anything = block
|
219
|
+
self
|
220
|
+
else
|
221
|
+
@on_anything
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Set a Proc to be run when a regular timeline message is encountered in the
|
226
|
+
# processing of the stream.
|
227
|
+
#
|
228
|
+
# @client = TweetStream::Client.new
|
229
|
+
# @client.on_timeline_message do |status|
|
230
|
+
# # do something with the status
|
231
|
+
# end
|
232
|
+
#
|
233
|
+
# Block can take one or two arguments. |status (, client)|
|
234
|
+
# If no block is given, it will return the currently set
|
235
|
+
# timeline status proc. When a block is given, the TweetStream::Client
|
236
|
+
# object is returned to allow for chaining.
|
237
|
+
def on_timeline_status(&block)
|
238
|
+
if block_given?
|
239
|
+
@on_timeline_status = block
|
240
|
+
self
|
241
|
+
else
|
242
|
+
@on_timeline_status
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
189
246
|
# Set a Proc to be run when connection established.
|
190
247
|
# Called in EventMachine::Connection#post_init
|
191
248
|
#
|
192
|
-
# @client = TweetStream::Client.new
|
249
|
+
# @client = TweetStream::Client.new
|
193
250
|
# @client.on_inited do
|
194
251
|
# puts 'Connected...'
|
195
252
|
# end
|
@@ -203,27 +260,59 @@ module TweetStream
|
|
203
260
|
end
|
204
261
|
end
|
205
262
|
|
263
|
+
# Set a Proc to be run on a regular interval
|
264
|
+
# independent of timeline status updates
|
265
|
+
#
|
266
|
+
# @client = TweetStream::Client.new
|
267
|
+
# @client.on_interval(20) do
|
268
|
+
# # do something every 20 seconds
|
269
|
+
# end
|
270
|
+
#
|
271
|
+
def on_interval(time_interval=nil, &block)
|
272
|
+
if block_given?
|
273
|
+
@on_interval_time = time_interval
|
274
|
+
@on_interval_proc = block
|
275
|
+
self
|
276
|
+
else
|
277
|
+
[@on_interval_time, @on_interval_proc]
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
206
281
|
def start(path, query_parameters = {}, &block) #:nodoc:
|
207
282
|
method = query_parameters.delete(:method) || :get
|
208
283
|
delete_proc = query_parameters.delete(:delete) || self.on_delete
|
209
284
|
limit_proc = query_parameters.delete(:limit) || self.on_limit
|
210
285
|
error_proc = query_parameters.delete(:error) || self.on_error
|
211
286
|
inited_proc = query_parameters.delete(:inited) || self.on_inited
|
287
|
+
direct_message_proc = query_parameters.delete(:direct_message) || self.on_direct_message
|
288
|
+
timeline_status_proc = query_parameters.delete(:timeline_status) || self.on_timeline_status
|
289
|
+
anything_proc = query_parameters.delete(:anything) || self.on_anything
|
212
290
|
|
213
291
|
params = normalize_filter_parameters(query_parameters)
|
214
292
|
|
293
|
+
extra_stream_parameters = query_parameters.delete(:extra_stream_parameters) || {}
|
294
|
+
|
215
295
|
uri = method == :get ? build_uri(path, params) : build_uri(path)
|
216
296
|
|
297
|
+
stream_params = {
|
298
|
+
:path => uri,
|
299
|
+
:method => method.to_s.upcase,
|
300
|
+
:user_agent => user_agent,
|
301
|
+
:on_inited => inited_proc,
|
302
|
+
:filters => params.delete(:track),
|
303
|
+
:params => params,
|
304
|
+
:ssl => true
|
305
|
+
}.merge(auth_params).merge(extra_stream_parameters)
|
306
|
+
|
307
|
+
EventMachine.epoll
|
308
|
+
EventMachine.kqueue
|
309
|
+
|
217
310
|
EventMachine::run {
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
:filters => params.delete(:track),
|
224
|
-
:params => params,
|
225
|
-
:ssl => true
|
226
|
-
}.merge(auth_params)
|
311
|
+
if @on_interval_proc.is_a?(Proc)
|
312
|
+
interval = @on_interval_time || Configuration::DEFAULT_TIMER_INTERVAL
|
313
|
+
proc = @on_interval_proc
|
314
|
+
@timer = EM.add_periodic_timer(interval, &proc)
|
315
|
+
end
|
227
316
|
|
228
317
|
@stream = Twitter::JSONStream.connect(stream_params)
|
229
318
|
@stream.each_item do |item|
|
@@ -240,23 +329,31 @@ module TweetStream
|
|
240
329
|
end
|
241
330
|
|
242
331
|
hash = TweetStream::Hash.new(raw_hash)
|
243
|
-
|
244
332
|
if hash[:delete] && hash[:delete][:status]
|
245
333
|
delete_proc.call(hash[:delete][:status][:id], hash[:delete][:status][:user_id]) if delete_proc.is_a?(Proc)
|
246
334
|
elsif hash[:limit] && hash[:limit][:track]
|
247
335
|
limit_proc.call(hash[:limit][:track]) if limit_proc.is_a?(Proc)
|
336
|
+
|
337
|
+
elsif hash[:direct_message]
|
338
|
+
yield_message_to direct_message_proc, TweetStream::DirectMessage.new(hash[:direct_message])
|
339
|
+
|
248
340
|
elsif hash[:text] && hash[:user]
|
249
341
|
@last_status = TweetStream::Status.new(hash)
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
342
|
+
yield_message_to timeline_status_proc, @last_status
|
343
|
+
|
344
|
+
if block_given?
|
345
|
+
# Give the block the option to receive either one
|
346
|
+
# or two arguments, depending on its arity.
|
347
|
+
case block.arity
|
348
|
+
when 1
|
349
|
+
yield @last_status
|
350
|
+
when 2
|
351
|
+
yield @last_status, self
|
352
|
+
end
|
258
353
|
end
|
259
354
|
end
|
355
|
+
|
356
|
+
yield_message_to anything_proc, hash
|
260
357
|
end
|
261
358
|
|
262
359
|
@stream.on_error do |message|
|
@@ -292,14 +389,11 @@ module TweetStream
|
|
292
389
|
|
293
390
|
def build_post_body(query) #:nodoc:
|
294
391
|
return '' unless query && query.is_a?(::Hash) && query.size > 0
|
295
|
-
pairs = []
|
296
392
|
|
297
|
-
query.
|
393
|
+
query.map do |k, v|
|
298
394
|
v = v.flatten.collect { |q| q.to_s }.join(',') if v.is_a?(Array)
|
299
|
-
|
300
|
-
end
|
301
|
-
|
302
|
-
pairs.join('&')
|
395
|
+
"#{k.to_s}=#{CGI.escape(v.to_s)}"
|
396
|
+
end.join('&')
|
303
397
|
end
|
304
398
|
|
305
399
|
def normalize_filter_parameters(query_parameters = {})
|
@@ -326,5 +420,16 @@ module TweetStream
|
|
326
420
|
}
|
327
421
|
end
|
328
422
|
end
|
423
|
+
|
424
|
+
def yield_message_to(procedure, message)
|
425
|
+
if procedure.is_a?(Proc)
|
426
|
+
case procedure.arity
|
427
|
+
when 1
|
428
|
+
procedure.call(message)
|
429
|
+
when 2
|
430
|
+
procedure.call(message, self)
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|
329
434
|
end
|
330
435
|
end
|
data/lib/tweetstream/daemon.rb
CHANGED
@@ -8,7 +8,15 @@ require 'daemons'
|
|
8
8
|
# require 'rubygems'
|
9
9
|
# require 'tweetstream'
|
10
10
|
#
|
11
|
-
# TweetStream
|
11
|
+
# TweetStream.configure do |config|
|
12
|
+
# config.consumer_key = 'abcdefghijklmnopqrstuvwxyz'
|
13
|
+
# config.consumer_secret = '0123456789'
|
14
|
+
# config.oauth_token = 'abcdefghijklmnopqrstuvwxyz'
|
15
|
+
# config.oauth_token_secret = '0123456789'
|
16
|
+
# config.auth_method = :oauth
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# TweetStream::Daemon.new('tracker').track('intridea') do |status|
|
12
20
|
# # do something here
|
13
21
|
# end
|
14
22
|
#
|
@@ -26,9 +34,9 @@ class TweetStream::Daemon < TweetStream::Client
|
|
26
34
|
# Twitter account you wish to use. The daemon has
|
27
35
|
# an optional process name for use when querying
|
28
36
|
# running processes.
|
29
|
-
def initialize(
|
37
|
+
def initialize(app_name=nil)
|
30
38
|
@app_name = app_name
|
31
|
-
super(
|
39
|
+
super({})
|
32
40
|
end
|
33
41
|
|
34
42
|
def start(path, query_parameters = {}, &block) #:nodoc:
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module TweetStream
|
2
|
+
class Terminated < ::StandardError; end
|
3
|
+
class Error < ::StandardError; end
|
4
|
+
class ConnectionError < TweetStream::Error; end
|
5
|
+
# A ReconnectError is raised when the maximum number of retries has
|
6
|
+
# failed to re-establish a connection.
|
7
|
+
class ReconnectError < StandardError
|
8
|
+
attr_accessor :timeout, :retries
|
9
|
+
def initialize(timeout, retries)
|
10
|
+
self.timeout = timeout
|
11
|
+
self.retries = retries
|
12
|
+
super("Failed to reconnect after #{retries} tries.")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/tweetstream/status.rb
CHANGED
data/lib/tweetstream/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
{"direct_message":{"created_at":"Sat Sep 24 18:59:38 +0000 2011", "id_str":"4227325281", "sender_screen_name":"coreyhaines", "sender":{"name":"Corey Haines", "profile_sidebar_fill_color":"DAECF4", "profile_sidebar_border_color":"C6E2EE", "profile_background_tile":false, "profile_image_url":"http://a0.twimg.com/profile_images/1508969901/Photo_on_2011-08-22_at_19.15__3_normal.jpg", "created_at":"Sun Dec 23 18:11:29 +0000 2007", "location":"Chicago, IL", "follow_request_sent":false, "id_str":"11458102", "is_translator":false, "profile_link_color":"1F98C7", "default_profile":false, "favourites_count":122, "contributors_enabled":false, "url":"http://www.coreyhaines.com", "id":11458102, "profile_image_url_https":"https://si0.twimg.com/profile_images/1508969901/Photo_on_2011-08-22_at_19.15__3_normal.jpg", "utc_offset":-21600, "profile_use_background_image":true, "listed_count":593, "lang":"en", "followers_count":5764, "protected":false, "profile_text_color":"663B12", "notifications":false, "description":"Software Journeyman, Coderetreat Facilitator, Cofounder of MercuryApp.com, Awesome....\r\nI make magic!", "verified":false, "profile_background_color":"C6E2EE", "geo_enabled":false, "profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme2/bg.gif", "time_zone":"Central Time (US & Canada)", "profile_background_image_url":"http://a1.twimg.com/images/themes/theme2/bg.gif", "default_profile_image":false, "friends_count":423, "statuses_count":35950, "following":false, "screen_name":"coreyhaines", "show_all_inline_media":false}, "recipient_screen_name":"coreyhainestest", "text":"waddup gain", "id":4227325281, "recipient":{"name":"Corey's Test Account", "profile_sidebar_fill_color":"DDEEF6", "profile_sidebar_border_color":"C0DEED", "profile_background_tile":false, "profile_image_url":"http://a2.twimg.com/sticky/default_profile_images/default_profile_3_normal.png", "created_at":"Sat Sep 24 13:04:56 +0000 2011", "location":null, "follow_request_sent":false, "id_str":"379145826", "is_translator":false, "profile_link_color":"0084B4", "default_profile":true, "favourites_count":0, "contributors_enabled":false, "url":null, "id":379145826, "profile_image_url_https":"https://si0.twimg.com/sticky/default_profile_images/default_profile_3_normal.png", "utc_offset":null, "profile_use_background_image":true, "listed_count":0, "lang":"en", "followers_count":1, "protected":false, "profile_text_color":"333333", "notifications":false, "description":null, "verified":false, "profile_background_color":"C0DEED", "geo_enabled":false, "profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme1/bg.png", "time_zone":null, "profile_background_image_url":"http://a0.twimg.com/images/themes/theme1/bg.png", "default_profile_image":true, "friends_count":1, "statuses_count":21, "following":true, "screen_name":"coreyhainestest", "show_all_inline_media":false}, "recipient_id":379145826, "sender_id":11458102}}
|
data/spec/spec_helper.rb
CHANGED
@@ -24,3 +24,13 @@ def sample_tweets
|
|
24
24
|
@tweets
|
25
25
|
end
|
26
26
|
end
|
27
|
+
|
28
|
+
def sample_direct_messages
|
29
|
+
return @direct_messages if @direct_messages
|
30
|
+
|
31
|
+
@direct_messages = []
|
32
|
+
Yajl::Parser.parse(File.open(File.dirname(__FILE__) + '/data/direct_messages.json', 'r')) do |hash|
|
33
|
+
@direct_messages << hash
|
34
|
+
end
|
35
|
+
@direct_messages
|
36
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe TweetStream::Client do
|
4
4
|
before(:each) do
|
@@ -12,7 +12,7 @@ describe TweetStream::Client do
|
|
12
12
|
|
13
13
|
describe '#build_uri' do
|
14
14
|
it 'should return a URI' do
|
15
|
-
@client.send(:build_uri, '').
|
15
|
+
@client.send(:build_uri, '').should be_kind_of(URI)
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'should have the specified path with the version prefix and a json extension' do
|
@@ -123,6 +123,81 @@ describe TweetStream::Client do
|
|
123
123
|
end.track('abc')
|
124
124
|
end
|
125
125
|
|
126
|
+
context "using on_anything" do
|
127
|
+
it "yields the raw hash" do
|
128
|
+
hash = {:id => 1234}
|
129
|
+
@stream.should_receive(:each_item).and_yield(hash.to_json)
|
130
|
+
yielded_hash = nil
|
131
|
+
@client.on_anything do |hash|
|
132
|
+
yielded_hash = hash
|
133
|
+
end.track('abc')
|
134
|
+
yielded_hash.should_not be_nil
|
135
|
+
yielded_hash.id.should == 1234
|
136
|
+
end
|
137
|
+
it 'yields itself if block has an arity of 2' do
|
138
|
+
hash = {:id => 1234}
|
139
|
+
@stream.should_receive(:each_item).and_yield(hash.to_json)
|
140
|
+
yielded_client = nil
|
141
|
+
@client.on_anything do |_, client|
|
142
|
+
yielded_client = client
|
143
|
+
end.track('abc')
|
144
|
+
yielded_client.should_not be_nil
|
145
|
+
yielded_client.should == @client
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'using on_timeline_status' do
|
150
|
+
it 'yields a Status' do
|
151
|
+
tweet = sample_tweets[0]
|
152
|
+
tweet[:id] = 123
|
153
|
+
tweet[:user][:screen_name] = 'monkey'
|
154
|
+
tweet[:text] = "Oo oo aa aa"
|
155
|
+
@stream.should_receive(:each_item).and_yield(tweet.to_json)
|
156
|
+
yielded_status = nil
|
157
|
+
@client.on_timeline_status do |status|
|
158
|
+
yielded_status = status
|
159
|
+
end.track('abc')
|
160
|
+
yielded_status.should_not be_nil
|
161
|
+
yielded_status[:id].should == 123
|
162
|
+
yielded_status.user.screen_name.should == 'monkey'
|
163
|
+
yielded_status.text.should == 'Oo oo aa aa'
|
164
|
+
end
|
165
|
+
it 'yields itself if block has an arity of 2' do
|
166
|
+
@stream.should_receive(:each_item).and_yield(sample_tweets[0].to_json)
|
167
|
+
yielded_client = nil
|
168
|
+
@client.on_timeline_status do |_, client|
|
169
|
+
yielded_client = client
|
170
|
+
end.track('abc')
|
171
|
+
yielded_client.should_not be_nil
|
172
|
+
yielded_client.should == @client
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context 'using on_direct_message' do
|
177
|
+
it 'yields a DirectMessage' do
|
178
|
+
direct_message = sample_direct_messages[0]
|
179
|
+
direct_message["direct_message"]["id"] = 1234
|
180
|
+
direct_message["direct_message"]["sender"]["screen_name"] = "coder"
|
181
|
+
@stream.should_receive(:each_item).and_yield(direct_message.to_json)
|
182
|
+
yielded_dm = nil
|
183
|
+
@client.on_direct_message do |dm|
|
184
|
+
yielded_dm = dm
|
185
|
+
end.userstream
|
186
|
+
yielded_dm.should_not be_nil
|
187
|
+
yielded_dm.id.should == 1234
|
188
|
+
yielded_dm.user.screen_name.should == "coder"
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'yields itself if block has an arity of 2' do
|
192
|
+
@stream.should_receive(:each_item).and_yield(sample_direct_messages[0].to_json)
|
193
|
+
yielded_client = nil
|
194
|
+
@client.on_direct_message do |_, client|
|
195
|
+
yielded_client = client
|
196
|
+
end.userstream
|
197
|
+
yielded_client.should == @client
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
126
201
|
it 'should call on_error if a non-hash response is received' do
|
127
202
|
@stream.should_receive(:each_item).and_yield('["favorited"]')
|
128
203
|
@client.on_error do |message|
|
@@ -145,6 +220,17 @@ describe TweetStream::Client do
|
|
145
220
|
m.should == 'Uh oh'
|
146
221
|
end.track('abc')
|
147
222
|
end
|
223
|
+
|
224
|
+
it 'should return the block when defined' do
|
225
|
+
@client.on_error do |m|
|
226
|
+
puts 'ohai'
|
227
|
+
end
|
228
|
+
@client.on_error.should be_kind_of(Proc)
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'should return nil when undefined' do
|
232
|
+
@client.on_error.should be_nil
|
233
|
+
end
|
148
234
|
end
|
149
235
|
|
150
236
|
describe '#on_max_reconnects' do
|
@@ -208,6 +294,27 @@ describe TweetStream::Client do
|
|
208
294
|
@client.send(proc_setter, &proc)
|
209
295
|
@client.send(proc_setter).should == proc
|
210
296
|
end
|
297
|
+
|
298
|
+
it 'should return nil when undefined' do
|
299
|
+
@client.send(proc_setter).should be_nil
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
describe '#on_interval' do
|
305
|
+
it 'should set when a block is given' do
|
306
|
+
@client.on_interval(5) { puts 'hi' }
|
307
|
+
@client.on_interval[0].should == 5
|
308
|
+
@client.on_interval[1].should be_kind_of(Proc)
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'should should create a periodic timer' do
|
312
|
+
# need to figure out a better way to test this
|
313
|
+
# for now, using on_inited to stop the reactor
|
314
|
+
proc = Proc.new{ puts 'hi' }
|
315
|
+
EM.should_receive(:add_periodic_timer).once.with(5)
|
316
|
+
@client.on_inited { EM.stop }.on_interval(5, &proc)
|
317
|
+
@client.track('go')
|
211
318
|
end
|
212
319
|
end
|
213
320
|
|
@@ -287,6 +394,18 @@ describe TweetStream::Client do
|
|
287
394
|
|
288
395
|
@client.track('monday')
|
289
396
|
end
|
397
|
+
|
398
|
+
context "when calling #userstream" do
|
399
|
+
it "sends the userstream host" do
|
400
|
+
Twitter::JSONStream.should_receive(:connect).with(hash_including(:host => "userstream.twitter.com")).and_return(@stream)
|
401
|
+
@client.userstream
|
402
|
+
end
|
403
|
+
|
404
|
+
it "uses the userstream uri" do
|
405
|
+
Twitter::JSONStream.should_receive(:connect).with(hash_including(:path => "/2/user.json")).and_return(@stream)
|
406
|
+
@client.userstream
|
407
|
+
end
|
408
|
+
end
|
290
409
|
end
|
291
410
|
end
|
292
411
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TweetStream::DirectMessage do
|
4
|
+
it 'modifies the :sender key into a TweetStream::User object called #user' do
|
5
|
+
@status = TweetStream::DirectMessage.new({:sender => {:screen_name => 'bob'}})
|
6
|
+
@status.user.should be_kind_of(TweetStream::User)
|
7
|
+
@status.user.screen_name.should == 'bob'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'transforms the sender into a TweetStream::User object called #sender' do
|
11
|
+
@status = TweetStream::DirectMessage.new({:sender => {:screen_name => 'bob'}})
|
12
|
+
@status.sender.should be_kind_of(TweetStream::User)
|
13
|
+
@status.sender.screen_name.should == 'bob'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'overrides the #id method for itself and the user' do
|
17
|
+
@status = TweetStream::DirectMessage.new({:id => 123, :sender => {:id => 345}})
|
18
|
+
@status.id.should == 123
|
19
|
+
@status.user.id.should == 345
|
20
|
+
end
|
21
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe TweetStream::Status do
|
4
4
|
it 'should modify the :user key into a TweetStream::User object' do
|
5
|
-
@status = TweetStream::Status.new(:user => {:screen_name => 'bob'})
|
6
|
-
@status.user.
|
5
|
+
@status = TweetStream::Status.new({:user => {:screen_name => 'bob'}})
|
6
|
+
@status.user.should be_kind_of(TweetStream::User)
|
7
7
|
@status.user.screen_name.should == 'bob'
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
it 'should override the #id method for itself and the user' do
|
11
|
-
@status = TweetStream::Status.new(:id => 123, :user => {:id => 345})
|
11
|
+
@status = TweetStream::Status.new({:id => 123, :user => {:id => 345}})
|
12
12
|
@status.id.should == 123
|
13
13
|
@status.user.id.should == 345
|
14
14
|
end
|
data/spec/tweetstream_spec.rb
CHANGED
@@ -22,13 +22,19 @@ describe TweetStream do
|
|
22
22
|
it "should return the same results as a client" do
|
23
23
|
MultiJson.should_receive(:decode).and_return({})
|
24
24
|
@stream.should_receive(:each_item).and_yield(sample_tweets[0].to_json)
|
25
|
-
TweetStream.track('abc','def').should == TweetStream::Client.new.track('abc','def')
|
25
|
+
TweetStream.new.track('abc','def').should == TweetStream::Client.new.track('abc','def')
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
describe ".
|
29
|
+
describe ".new" do
|
30
30
|
it "should be a TweetStream::Client" do
|
31
|
-
TweetStream.
|
31
|
+
TweetStream.new.should be_a TweetStream::Client
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.respond_to?' do
|
36
|
+
it "should take an optional argument" do
|
37
|
+
TweetStream.respond_to?(:new, true).should be_true
|
32
38
|
end
|
33
39
|
end
|
34
40
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tweetstream
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.0.
|
4
|
+
version: 1.1.0.rc2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
12
|
+
date: 2011-09-26 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: twitter-stream
|
16
|
-
requirement: &
|
16
|
+
requirement: &2153824280 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.1.14
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2153824280
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: daemons
|
27
|
-
requirement: &
|
27
|
+
requirement: &2153823820 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.1.2
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2153823820
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: multi_json
|
38
|
-
requirement: &
|
38
|
+
requirement: &2153823360 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 1.0.3
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2153823360
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rake
|
49
|
-
requirement: &
|
49
|
+
requirement: &2153822900 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0.9'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2153822900
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: simplecov
|
60
|
-
requirement: &
|
60
|
+
requirement: &2153822440 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0.4'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2153822440
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yard
|
71
|
-
requirement: &
|
71
|
+
requirement: &2153821980 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0.7'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *2153821980
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rdiscount
|
82
|
-
requirement: &
|
82
|
+
requirement: &2153821520 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '1.6'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *2153821520
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rspec
|
93
|
-
requirement: &
|
93
|
+
requirement: &2153821060 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ~>
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: 2.6.0
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *2153821060
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: yajl-ruby
|
104
|
-
requirement: &
|
104
|
+
requirement: &2153820600 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '1.0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *2153820600
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: json
|
115
|
-
requirement: &
|
115
|
+
requirement: &2153820140 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ~>
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: 1.5.1
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *2153820140
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: guard-rspec
|
126
|
-
requirement: &
|
126
|
+
requirement: &2153819680 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ~>
|
@@ -131,7 +131,7 @@ dependencies:
|
|
131
131
|
version: 0.4.3
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *2153819680
|
135
135
|
description: TweetStream allows you to easily consume the Twitter Streaming API utilizing
|
136
136
|
the YAJL Ruby gem.
|
137
137
|
email:
|
@@ -153,17 +153,22 @@ files:
|
|
153
153
|
- Rakefile
|
154
154
|
- examples/growl_daemon.rb
|
155
155
|
- examples/oauth.rb
|
156
|
+
- examples/userstream.rb
|
156
157
|
- lib/tweetstream.rb
|
157
158
|
- lib/tweetstream/client.rb
|
158
159
|
- lib/tweetstream/configuration.rb
|
159
160
|
- lib/tweetstream/daemon.rb
|
161
|
+
- lib/tweetstream/direct_message.rb
|
162
|
+
- lib/tweetstream/error.rb
|
160
163
|
- lib/tweetstream/hash.rb
|
161
164
|
- lib/tweetstream/status.rb
|
162
165
|
- lib/tweetstream/user.rb
|
163
166
|
- lib/tweetstream/version.rb
|
167
|
+
- spec/data/direct_messages.json
|
164
168
|
- spec/data/statuses.json
|
165
169
|
- spec/spec_helper.rb
|
166
170
|
- spec/tweetstream/client_spec.rb
|
171
|
+
- spec/tweetstream/direct_message_spec.rb
|
167
172
|
- spec/tweetstream/hash_spec.rb
|
168
173
|
- spec/tweetstream/parser_spec.rb
|
169
174
|
- spec/tweetstream/status_spec.rb
|
@@ -194,9 +199,11 @@ signing_key:
|
|
194
199
|
specification_version: 3
|
195
200
|
summary: TweetStream is a simple wrapper for consuming the Twitter Streaming API.
|
196
201
|
test_files:
|
202
|
+
- spec/data/direct_messages.json
|
197
203
|
- spec/data/statuses.json
|
198
204
|
- spec/spec_helper.rb
|
199
205
|
- spec/tweetstream/client_spec.rb
|
206
|
+
- spec/tweetstream/direct_message_spec.rb
|
200
207
|
- spec/tweetstream/hash_spec.rb
|
201
208
|
- spec/tweetstream/parser_spec.rb
|
202
209
|
- spec/tweetstream/status_spec.rb
|