tweetstream 2.1.0 → 2.2.0

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 CHANGED
@@ -1,8 +1,9 @@
1
- # TweetStream [![Build Status](https://secure.travis-ci.org/intridea/tweetstream.png?branch=master)][travis] [![Dependency Status](https://gemnasium.com/intridea/tweetstream.png?travis)][gemnasium]
1
+ # TweetStream [![Build Status](https://secure.travis-ci.org/intridea/tweetstream.png?branch=master)][travis] [![Dependency Status](https://gemnasium.com/intridea/tweetstream.png?travis)][gemnasium] [![Code Climate](https://codeclimate.com/badge.png)][codeclimate]
2
2
  TweetStream provides simple Ruby access to [Twitter's Streaming API](https://dev.twitter.com/docs/streaming-api).
3
3
 
4
4
  [travis]: http://travis-ci.org/intridea/tweetstream
5
5
  [gemnasium]: https://gemnasium.com/intridea/tweetstream
6
+ [codeclimate]: https://codeclimate.com/github/intridea/tweetstream
6
7
 
7
8
  ## Installation
8
9
 
@@ -57,7 +58,7 @@ additions in 2.0 include:
57
58
 
58
59
  ### OAuth
59
60
 
60
- OAuth is now the default authentication method. Both userstreams and Site
61
+ OAuth is now the default authentication method. Both userstreams and Site
61
62
  Streams exclusively work with OAuth. TweetStream still supports Basic Auth,
62
63
  however it is no longer the default. If you are still using Basic Auth, you
63
64
  should plan to move to OAuth as soon as possible.
@@ -68,7 +69,7 @@ Site Streams are now fully supported, including the connection management functi
68
69
 
69
70
  ### Compatablity with the Twitter gem
70
71
 
71
- TweetStream now emits objects from the [Twitter gem](https://github.com/jnunemaker/twitter) instead of custom hashes. These objects are already defined in the `twitter` gem and are superior to the custom objects in the following ways:
72
+ TweetStream now emits objects from the [Twitter gem](https://github.com/sferik/twitter) instead of custom hashes. These objects are already defined in the `twitter` gem and are superior to the custom objects in the following ways:
72
73
 
73
74
  1. Object equivalence (`#==` returns true if `#id`s are the same).
74
75
  2. The `#created_at` method returns a `Date` instead of a `String`.
@@ -85,14 +86,14 @@ It offers functionality parity with twitter-stream while also supporting several
85
86
 
86
87
  ### Removal of on_interval callback
87
88
 
88
- We have removed the `on_interval` callback. If you require interval-based timers, it is possible to run
89
+ We have removed the `on_interval` callback. If you require interval-based timers, it is possible to run
89
90
  TweetStream inside an already running EventMachine reactor in which you can define `EM::Timer` or `EM::PeriodicTimer`
90
91
  for time-based operations:
91
92
 
92
93
  ```ruby
93
94
  EM.run do
94
95
  client = TweetStream::Client.new
95
-
96
+
96
97
  EM::PeriodicTimer.new(10) do
97
98
  # do something on an interval
98
99
  end
@@ -141,12 +142,12 @@ client.control.friends_ids('115192457') do |friends|
141
142
  end
142
143
 
143
144
  # obtain the current state of the stream
144
- client.control.info do |info|
145
+ client.control.info do |info|
145
146
  # do something
146
147
  end
147
148
  ```
148
149
 
149
- Note that per Twitter's documentation, connection management features are not
150
+ Note that per Twitter's documentation, connection management features are not
150
151
  immediately available when connected
151
152
 
152
153
  You also can use method hooks for both regular timeline statuses and direct messages.
@@ -169,7 +170,7 @@ client.userstream
169
170
 
170
171
  ## Authentication
171
172
 
172
- TweetStream supports OAuth and Basic Auth. `TweetStream::Client` now accepts
173
+ TweetStream supports OAuth and Basic Auth. `TweetStream::Client` now accepts
173
174
  a hash:
174
175
 
175
176
  ```ruby
@@ -200,12 +201,12 @@ end
200
201
 
201
202
  TweetStream assumes OAuth by default. If you are using Basic Auth, it is recommended
202
203
  that you update your code to use OAuth as Twitter is likely to phase out Basic Auth
203
- support. Basic Auth is only available for public streams as User Stream and Site Stream
204
+ support. Basic Auth is only available for public streams as User Stream and Site Stream
204
205
  functionality [only support OAuth](https://dev.twitter.com/docs/streaming-apis/connecting#Authentication).
205
206
 
206
- ## Parsing JSON
207
+ ## Parsing JSON
207
208
 
208
- TweetStream supports swappable JSON backends via MultiJson. Simply require your preferred
209
+ TweetStream supports swappable JSON backends via MultiJson. Simply require your preferred
209
210
  JSON parser and it will be used to parse responses.
210
211
 
211
212
  ## Handling Deletes and Rate Limitations
@@ -1,18 +1,16 @@
1
- require 'cgi'
2
1
  require 'em-twitter'
3
2
  require 'eventmachine'
4
3
  require 'multi_json'
5
4
  require 'twitter'
6
- require 'uri'
7
5
 
8
6
  module TweetStream
9
- # Provides simple access to the Twitter Streaming API (http://apiwiki.twitter.com/Streaming-API-Documentation)
7
+ # Provides simple access to the Twitter Streaming API (https://dev.twitter.com/docs/streaming-api)
10
8
  # for Ruby scripts that need to create a long connection to
11
9
  # Twitter for tracking and other purposes.
12
10
  #
13
11
  # Basic usage of the library is to call one of the provided
14
12
  # methods and provide a block that will perform actions on
15
- # a yielded Twitter::Status. For example:
13
+ # a yielded Twitter::Tweet. For example:
16
14
  #
17
15
  # TweetStream::Client.new.track('fail') do |status|
18
16
  # puts "[#{status.user.screen_name}] #{status.text}"
@@ -22,6 +20,21 @@ module TweetStream
22
20
  # view the TweetStream::Daemon class.
23
21
  class Client
24
22
 
23
+ OPTION_CALLBACKS = [:delete,
24
+ :scrub_geo,
25
+ :limit,
26
+ :error,
27
+ :enhance_your_calm,
28
+ :unauthorized,
29
+ :reconnect,
30
+ :inited,
31
+ :direct_message,
32
+ :timeline_status,
33
+ :anything,
34
+ :no_data_received,
35
+ :status_withheld,
36
+ :user_withheld].freeze unless defined?(OPTION_CALLBACKS)
37
+
25
38
  # @private
26
39
  attr_accessor *Configuration::VALID_OPTIONS_KEYS
27
40
  attr_accessor :options
@@ -34,6 +47,7 @@ module TweetStream
34
47
  Configuration::VALID_OPTIONS_KEYS.each do |key|
35
48
  send("#{key}=", merged_options[key])
36
49
  end
50
+ @callbacks = {}
37
51
  end
38
52
 
39
53
  # Returns all public statuses. The Firehose is not a generally
@@ -41,7 +55,7 @@ module TweetStream
41
55
  # Creative use of a combination of other resources and various access
42
56
  # levels can satisfy nearly every application use case.
43
57
  def firehose(query_parameters = {}, &block)
44
- start('statuses/firehose', query_parameters, &block)
58
+ start('/1/statuses/firehose.json', query_parameters, &block)
45
59
  end
46
60
 
47
61
  # Returns all statuses containing http: and https:. The links stream is
@@ -49,7 +63,7 @@ module TweetStream
49
63
  # of access. Creative use of a combination of other resources and various
50
64
  # access levels can satisfy nearly every application use case.
51
65
  def links(query_parameters = {}, &block)
52
- start('statuses/links', query_parameters, &block)
66
+ start('/1/statuses/links.json', query_parameters, &block)
53
67
  end
54
68
 
55
69
  # Returns all retweets. The retweet stream is not a generally available
@@ -59,7 +73,7 @@ module TweetStream
59
73
  # the site-wide retweet feature has not yet launched,
60
74
  # so there are currently few, if any, retweets on this stream.
61
75
  def retweet(query_parameters = {}, &block)
62
- start('statuses/retweet', query_parameters, &block)
76
+ start('/1/statuses/retweet.json', query_parameters, &block)
63
77
  end
64
78
 
65
79
  # Returns a random sample of all public statuses. The default access level
@@ -68,7 +82,7 @@ module TweetStream
68
82
  # research applications that desire a larger proportion to be statistically
69
83
  # significant sample.
70
84
  def sample(query_parameters = {}, &block)
71
- start('statuses/sample', query_parameters, &block)
85
+ start('/1/statuses/sample.json', query_parameters, &block)
72
86
  end
73
87
 
74
88
  # Specify keywords to track. Queries are subject to Track Limitations,
@@ -79,8 +93,7 @@ module TweetStream
79
93
  # Keywords containing punctuation will only exact match tokens.
80
94
  # Query parameters may be passed as the last argument.
81
95
  def track(*keywords, &block)
82
- query_params = keywords.pop if keywords.last.is_a?(::Hash)
83
- query_params ||= {}
96
+ query_params = keywords.extract_options!
84
97
  filter(query_params.merge(:track => keywords), &block)
85
98
  end
86
99
 
@@ -89,8 +102,7 @@ module TweetStream
89
102
  # pressing the reply "swoosh") are not matched. Requires integer user
90
103
  # IDs, not screen names. Query parameters may be passed as the last argument.
91
104
  def follow(*user_ids, &block)
92
- query_params = user_ids.pop if user_ids.last.is_a?(::Hash)
93
- query_params ||= {}
105
+ query_params = user_ids.extract_options!
94
106
  filter(query_params.merge(:follow => user_ids), &block)
95
107
  end
96
108
 
@@ -103,8 +115,7 @@ module TweetStream
103
115
  # the first pair denoting the southwest corner of the box
104
116
  # longitude/latitude pairs, separated by commas. The first pair specifies the southwest corner of the box.
105
117
  def locations(*locations_map, &block)
106
- query_params = locations_map.pop if locations_map.last.is_a?(::Hash)
107
- query_params ||= {}
118
+ query_params = locations_map.extract_options!
108
119
  filter(query_params.merge(:locations => locations_map), &block)
109
120
  end
110
121
 
@@ -114,26 +125,26 @@ module TweetStream
114
125
  # method is provided separately for cases when it would conserve the
115
126
  # number of HTTP connections to combine track and follow.
116
127
  def filter(query_params = {}, &block)
117
- start('statuses/filter', query_params.merge(:method => :post), &block)
128
+ start('/1/statuses/filter.json', query_params.merge(:method => :post), &block)
118
129
  end
119
130
 
120
131
  # Make a call to the userstream api for currently authenticated user
121
132
  def userstream(query_params = {}, &block)
122
- stream_params = { :host => "userstream.twitter.com", :path => "/2/user.json" }
133
+ stream_params = { :host => "userstream.twitter.com" }
123
134
  query_params.merge!(:extra_stream_parameters => stream_params)
124
- start('', query_params, &block)
135
+ start('/2/user.json', query_params, &block)
125
136
  end
126
137
 
127
138
  # Make a call to the userstream api
128
139
  def sitestream(user_ids = [], query_params = {}, &block)
129
- stream_params = { :host => "sitestream.twitter.com", :path => '/2b/site.json' }
140
+ stream_params = { :host => "sitestream.twitter.com" }
130
141
  query_params.merge!({
131
142
  :method => :post,
132
143
  :follow => user_ids,
133
144
  :extra_stream_parameters => stream_params
134
145
  })
135
146
  query_params.merge!(:with => 'followings') if query_params.delete(:followings)
136
- start('', query_params, &block)
147
+ start('/2b/site.json', query_params, &block)
137
148
  end
138
149
 
139
150
  # Set a Proc to be run when a deletion notice is received
@@ -149,12 +160,7 @@ module TweetStream
149
160
  # deletion proc. When a block is given, the TweetStream::Client
150
161
  # object is returned to allow for chaining.
151
162
  def on_delete(&block)
152
- if block_given?
153
- @on_delete = block
154
- self
155
- else
156
- @on_delete
157
- end
163
+ on('delete', &block)
158
164
  end
159
165
 
160
166
  # Set a Proc to be run when a scrub_geo notice is received
@@ -170,12 +176,7 @@ module TweetStream
170
176
  # scrub_geo proc. When a block is given, the TweetStream::Client
171
177
  # object is returned to allow for chaining.
172
178
  def on_scrub_geo(&block)
173
- if block_given?
174
- @on_scrub_geo = block
175
- self
176
- else
177
- @on_scrub_geo
178
- end
179
+ on('scrub_geo', &block)
179
180
  end
180
181
 
181
182
  # Set a Proc to be run when a rate limit notice is received
@@ -191,12 +192,7 @@ module TweetStream
191
192
  # limit proc. When a block is given, the TweetStream::Client
192
193
  # object is returned to allow for chaining.
193
194
  def on_limit(&block)
194
- if block_given?
195
- @on_limit = block
196
- self
197
- else
198
- @on_limit
199
- end
195
+ on('limit', &block)
200
196
  end
201
197
 
202
198
  # Set a Proc to be run when an HTTP error is encountered in the
@@ -213,12 +209,7 @@ module TweetStream
213
209
  # error proc. When a block is given, the TweetStream::Client
214
210
  # object is returned to allow for chaining.
215
211
  def on_error(&block)
216
- if block_given?
217
- @on_error = block
218
- self
219
- else
220
- @on_error
221
- end
212
+ on('error', &block)
222
213
  end
223
214
 
224
215
  # Set a Proc to be run when an HTTP status 401 is encountered while
@@ -229,12 +220,7 @@ module TweetStream
229
220
  # unauthorized proc. When a block is given, the TweetStream::Client
230
221
  # object is returned to allow for chaining.
231
222
  def on_unauthorized(&block)
232
- if block_given?
233
- @on_unauthorized = block
234
- self
235
- else
236
- @on_unauthorized
237
- end
223
+ on('unauthorized', &block)
238
224
  end
239
225
 
240
226
  # Set a Proc to be run when a direct message is encountered in the
@@ -250,12 +236,7 @@ module TweetStream
250
236
  # direct message proc. When a block is given, the TweetStream::Client
251
237
  # object is returned to allow for chaining.
252
238
  def on_direct_message(&block)
253
- if block_given?
254
- @on_direct_message = block
255
- self
256
- else
257
- @on_direct_message
258
- end
239
+ on('direct_message', &block)
259
240
  end
260
241
 
261
242
  # Set a Proc to be run whenever anything is encountered in the
@@ -271,12 +252,7 @@ module TweetStream
271
252
  # timeline status proc. When a block is given, the TweetStream::Client
272
253
  # object is returned to allow for chaining.
273
254
  def on_anything(&block)
274
- if block_given?
275
- @on_anything = block
276
- self
277
- else
278
- @on_anything
279
- end
255
+ on('anything', &block)
280
256
  end
281
257
 
282
258
  # Set a Proc to be run when a regular timeline message is encountered in the
@@ -292,12 +268,7 @@ module TweetStream
292
268
  # timeline status proc. When a block is given, the TweetStream::Client
293
269
  # object is returned to allow for chaining.
294
270
  def on_timeline_status(&block)
295
- if block_given?
296
- @on_timeline_status = block
297
- self
298
- else
299
- @on_timeline_status
300
- end
271
+ on('timeline_status', &block)
301
272
  end
302
273
 
303
274
  # Set a Proc to be run on reconnect.
@@ -308,12 +279,7 @@ module TweetStream
308
279
  # end
309
280
  #
310
281
  def on_reconnect(&block)
311
- if block_given?
312
- @on_reconnect = block
313
- self
314
- else
315
- @on_reconnect
316
- end
282
+ on('reconnect', &block)
317
283
  end
318
284
 
319
285
  # Set a Proc to be run when connection established.
@@ -325,28 +291,18 @@ module TweetStream
325
291
  # end
326
292
  #
327
293
  def on_inited(&block)
328
- if block_given?
329
- @on_inited = block
330
- self
331
- else
332
- @on_inited
333
- end
294
+ on('inited', &block)
334
295
  end
335
296
 
336
297
  # Set a Proc to be run when no data is received from the server
337
298
  # and a stall occurs. Twitter defines this to be 90 seconds.
338
299
  #
339
300
  # @client = TweetStream::Client.new
340
- # @client.on_no_data do
301
+ # @client.on_no_data_received do
341
302
  # # Make note of no data, possi
342
303
  # end
343
304
  def on_no_data_received(&block)
344
- if block_given?
345
- @on_no_data = block
346
- self
347
- else
348
- @on_no_data
349
- end
305
+ on('no_data_received', &block)
350
306
  end
351
307
 
352
308
  # Set a Proc to be run when enhance_your_calm signal is received.
@@ -356,11 +312,45 @@ module TweetStream
356
312
  # # do something, your account has been blocked
357
313
  # end
358
314
  def on_enhance_your_calm(&block)
315
+ on('enhance_your_calm', &block)
316
+ end
317
+
318
+ # Set a Proc to be run when a status_withheld message is received.
319
+ #
320
+ # @client = TweetStream::Client.new
321
+ # @client.on_status_withheld do |status|
322
+ # # do something with the status
323
+ # end
324
+ def on_status_withheld(&block)
325
+ on('status_withheld', &block)
326
+ end
327
+
328
+ # Set a Proc to be run when a status_withheld message is received.
329
+ #
330
+ # @client = TweetStream::Client.new
331
+ # @client.on_user_withheld do |status|
332
+ # # do something with the status
333
+ # end
334
+ def on_user_withheld(&block)
335
+ on('user_withheld', &block)
336
+ end
337
+
338
+ # Set a Proc to be run on userstream events
339
+ #
340
+ # @client = TweetStream::Client.new
341
+ # @client.event(:favorite) do |event|
342
+ # # do something with the status
343
+ # end
344
+ def on_event(event, &block)
345
+ on(event, &block)
346
+ end
347
+
348
+ def on(event, &block)
359
349
  if block_given?
360
- @on_enhance_your_calm = block
350
+ @callbacks[event.to_s] = block
361
351
  self
362
352
  else
363
- @on_enhance_your_calm
353
+ @callbacks[event.to_s]
364
354
  end
365
355
  end
366
356
 
@@ -379,33 +369,24 @@ module TweetStream
379
369
  end
380
370
 
381
371
  # connect to twitter without starting a new EventMachine run loop
382
- def connect(path, query_parameters = {}, &block)
383
- method = query_parameters.delete(:method) || :get
384
- delete_proc = query_parameters.delete(:delete) || self.on_delete
385
- scrub_geo_proc = query_parameters.delete(:scrub_geo) || self.on_scrub_geo
386
- limit_proc = query_parameters.delete(:limit) || self.on_limit
387
- error_proc = query_parameters.delete(:error) || self.on_error
388
- enhance_your_calm_proc = query_parameters.delete(:enhance_your_calm) || self.on_error
389
- unauthorized_proc = query_parameters.delete(:unauthorized) || self.on_unauthorized
390
- reconnect_proc = query_parameters.delete(:reconnect) || self.on_reconnect
391
- inited_proc = query_parameters.delete(:inited) || self.on_inited
392
- direct_message_proc = query_parameters.delete(:direct_message) || self.on_direct_message
393
- timeline_status_proc = query_parameters.delete(:timeline_status) || self.on_timeline_status
394
- anything_proc = query_parameters.delete(:anything) || self.on_anything
395
- no_data_proc = query_parameters.delete(:no_data_received) || self.on_no_data_received
396
-
397
- params = normalize_filter_parameters(query_parameters)
398
-
399
- extra_stream_parameters = query_parameters.delete(:extra_stream_parameters) || {}
400
-
401
- uri = method == :get ? build_uri(path, params) : build_uri(path)
372
+ def connect(path, options = {}, &block)
373
+ request_method = options.delete(:method) || :get
374
+ warn_if_callbacks(options)
375
+
376
+ callbacks = @callbacks.dup
377
+ OPTION_CALLBACKS.each do |callback|
378
+ callbacks.merge(callback.to_s => options.delete(callback)) if options[callback]
379
+ end
380
+
381
+ inited_proc = options.delete(:inited) || @callbacks['inited']
382
+ extra_stream_parameters = options.delete(:extra_stream_parameters) || {}
402
383
 
403
384
  stream_params = {
404
- :path => uri,
405
- :method => method.to_s.upcase,
385
+ :path => path,
386
+ :method => request_method.to_s.upcase,
406
387
  :user_agent => user_agent,
407
- :on_inited => inited_proc,
408
- :params => params
388
+ :on_inited => inited_proc,
389
+ :params => normalize_filter_parameters(options)
409
390
  }.merge(extra_stream_parameters).merge(auth_params)
410
391
 
411
392
  @stream = EM::Twitter::Client.connect(stream_params)
@@ -413,76 +394,36 @@ module TweetStream
413
394
  begin
414
395
  hash = MultiJson.decode(item, :symbolize_keys => true)
415
396
  rescue MultiJson::DecodeError
416
- error_proc.call("MultiJson::DecodeError occured in stream: #{item}") if error_proc.is_a?(Proc)
397
+ invoke_callback(callbacks['error'], "MultiJson::DecodeError occured in stream: #{item}")
417
398
  next
418
399
  end
419
400
 
420
401
  unless hash.is_a?(::Hash)
421
- error_proc.call("Unexpected JSON object in stream: #{item}") if error_proc.is_a?(Proc)
402
+ invoke_callback(callbacks['error'], "Unexpected JSON object in stream: #{item}")
422
403
  next
423
404
  end
424
405
 
425
406
  Twitter.identity_map = false
426
407
 
427
- if hash[:control] && hash[:control][:control_uri]
428
- @control_uri = hash[:control][:control_uri]
429
- require 'tweetstream/site_stream_client'
430
- @control = TweetStream::SiteStreamClient.new(@control_uri, options)
431
- @control.on_error(&self.on_error)
432
- elsif hash[:delete] && hash[:delete][:status]
433
- delete_proc.call(hash[:delete][:status][:id], hash[:delete][:status][:user_id]) if delete_proc.is_a?(Proc)
434
- elsif hash[:scrub_geo] && hash[:scrub_geo][:up_to_status_id]
435
- scrub_geo_proc.call(hash[:scrub_geo][:up_to_status_id], hash[:scrub_geo][:user_id]) if scrub_geo_proc.is_a?(Proc)
436
- elsif hash[:limit] && hash[:limit][:track]
437
- limit_proc.call(hash[:limit][:track]) if limit_proc.is_a?(Proc)
438
- elsif hash[:direct_message]
439
- yield_message_to direct_message_proc, Twitter::DirectMessage.new(hash[:direct_message])
440
- elsif hash[:text] && hash[:user]
441
- @last_status = Twitter::Status.new(hash)
442
- yield_message_to timeline_status_proc, @last_status
443
-
444
- if block_given?
445
- # Give the block the option to receive either one
446
- # or two arguments, depending on its arity.
447
- case block.arity
448
- when 1
449
- yield @last_status
450
- when 2
451
- yield @last_status, self
452
- end
453
- end
454
- elsif hash[:for_user]
455
- @message = hash
456
-
457
- if block_given?
458
- # Give the block the option to receive either one
459
- # or two arguments, depending on its arity.
460
- case block.arity
461
- when 1
462
- yield @message
463
- when 2
464
- yield @message, self
465
- end
466
- end
467
- end
408
+ respond_to(hash, callbacks, &block)
468
409
 
469
- yield_message_to anything_proc, hash
410
+ yield_message_to(callbacks['anything'], hash)
470
411
  end
471
412
 
472
413
  @stream.on_error do |message|
473
- error_proc.call(message) if error_proc.is_a?(Proc)
414
+ invoke_callback(callbacks['error'], message)
474
415
  end
475
416
 
476
417
  @stream.on_unauthorized do
477
- unauthorized_proc.call if unauthorized_proc.is_a?(Proc)
418
+ invoke_callback(callbacks['unauthorized'])
478
419
  end
479
420
 
480
421
  @stream.on_enhance_your_calm do
481
- enhance_your_calm_proc.call if enhance_your_calm_proc.is_a?(Proc)
422
+ invoke_callback(callbacks['enhance_your_calm'])
482
423
  end
483
424
 
484
425
  @stream.on_reconnect do |timeout, retries|
485
- reconnect_proc.call(timeout, retries) if reconnect_proc.is_a?(Proc)
426
+ invoke_callback(callbacks['reconnect'], timeout, retries)
486
427
  end
487
428
 
488
429
  @stream.on_max_reconnects do |timeout, retries|
@@ -490,12 +431,42 @@ module TweetStream
490
431
  end
491
432
 
492
433
  @stream.on_no_data_received do
493
- no_data_proc.call if no_data_proc.is_a?(Proc)
434
+ invoke_callback(callbacks['no_data_received'])
494
435
  end
495
436
 
496
437
  @stream
497
438
  end
498
439
 
440
+ def respond_to(hash, callbacks, &block)
441
+ if hash[:control] && hash[:control][:control_uri]
442
+ @control_uri = hash[:control][:control_uri]
443
+ require 'tweetstream/site_stream_client'
444
+ @control = TweetStream::SiteStreamClient.new(@control_uri, options)
445
+ @control.on_error(&callbacks['error'])
446
+ elsif hash[:delete] && hash[:delete][:status]
447
+ invoke_callback(callbacks['delete'], hash[:delete][:status][:id], hash[:delete][:status][:user_id])
448
+ elsif hash[:scrub_geo] && hash[:scrub_geo][:up_to_status_id]
449
+ invoke_callback(callbacks['scrub_geo'], hash[:scrub_geo][:up_to_status_id], hash[:scrub_geo][:user_id])
450
+ elsif hash[:limit] && hash[:limit][:track]
451
+ invoke_callback(callbacks['limit'], hash[:limit][:track])
452
+ elsif hash[:direct_message]
453
+ yield_message_to(callbacks['direct_message'], Twitter::DirectMessage.new(hash[:direct_message]))
454
+ elsif hash[:status_withheld]
455
+ invoke_callback(callbacks['status_withheld'], hash[:status_withheld])
456
+ elsif hash[:user_withheld]
457
+ invoke_callback(callbacks['user_withheld'], hash[:user_withheld])
458
+ elsif hash[:event]
459
+ invoke_callback(callbacks[hash[:event].to_s], hash)
460
+ elsif hash[:text] && hash[:user]
461
+ @last_status = Twitter::Tweet.new(hash)
462
+ yield_message_to(callbacks['timeline_status'], @last_status)
463
+
464
+ yield_message_to(block, @last_status) if block_given?
465
+ elsif hash[:for_user]
466
+ yield_message_to(block, hash) if block_given?
467
+ end
468
+ end
469
+
499
470
  # Terminate the currently running TweetStream and close EventMachine loop
500
471
  def stop
501
472
  EventMachine.stop_event_loop
@@ -513,23 +484,6 @@ module TweetStream
513
484
 
514
485
  protected
515
486
 
516
- def build_uri(path, query_parameters = {}) #:nodoc:
517
- URI.parse("/1/#{path}.json#{build_query_parameters(query_parameters)}")
518
- end
519
-
520
- def build_query_parameters(query)
521
- query.size > 0 ? "?#{build_post_body(query)}" : ''
522
- end
523
-
524
- def build_post_body(query) #:nodoc:
525
- return '' unless query && query.is_a?(::Hash) && query.size > 0
526
-
527
- query.map do |k, v|
528
- v = v.flatten.collect { |q| q.to_s }.join(',') if v.is_a?(Array)
529
- "#{k.to_s}=#{CGI.escape(v.to_s)}"
530
- end.join('&')
531
- end
532
-
533
487
  def normalize_filter_parameters(query_parameters = {})
534
488
  [:follow, :track, :locations].each do |param|
535
489
  if query_parameters[param].kind_of?(Array)
@@ -542,38 +496,43 @@ module TweetStream
542
496
  end
543
497
 
544
498
  def auth_params
545
- if auth_method == :basic
546
- { :basic => basic_auth_params }
499
+ if auth_method.to_s == 'basic'
500
+ { :basic => {
501
+ :username => username,
502
+ :password => password
503
+ }
504
+ }
547
505
  else
548
- { :oauth => oauth_params }
506
+ { :oauth => {
507
+ :consumer_key => consumer_key,
508
+ :consumer_secret => consumer_secret,
509
+ :token => oauth_token,
510
+ :token_secret => oauth_token_secret
511
+ }
512
+ }
549
513
  end
550
514
  end
551
515
 
552
- def basic_auth_params
553
- {
554
- :username => username,
555
- :password => password
556
- }
557
- end
558
-
559
- def oauth_params
560
- {
561
- :consumer_key => consumer_key,
562
- :consumer_secret => consumer_secret,
563
- :token => oauth_token,
564
- :token_secret => oauth_token_secret
565
- }
516
+ # A utility method used to invoke callback methods against the Client
517
+ def invoke_callback(callback, *args)
518
+ callback.call(*args) if callback
566
519
  end
567
520
 
568
521
  def yield_message_to(procedure, message)
522
+ # Give the block the option to receive either one
523
+ # or two arguments, depending on its arity.
569
524
  if procedure.is_a?(Proc)
570
525
  case procedure.arity
571
- when 1
572
- procedure.call(message)
573
- when 2
574
- procedure.call(message, self)
526
+ when 1 then invoke_callback(procedure, message)
527
+ when 2 then invoke_callback(procedure, message, self)
575
528
  end
576
529
  end
577
530
  end
531
+
532
+ def warn_if_callbacks(options={})
533
+ if OPTION_CALLBACKS.select { |callback| options[callback] }.size > 0
534
+ Kernel.warn("Passing callbacks via the options hash is deprecated and will be removed in TweetStream 3.0")
535
+ end
536
+ end
578
537
  end
579
538
  end