twitter 5.8.0 → 5.9.0

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/README.md +10 -36
  4. data/lib/twitter/base.rb +20 -3
  5. data/lib/twitter/basic_user.rb +6 -4
  6. data/lib/twitter/client.rb +2 -1
  7. data/lib/twitter/configuration.rb +1 -1
  8. data/lib/twitter/cursor.rb +1 -1
  9. data/lib/twitter/entities.rb +10 -6
  10. data/lib/twitter/enumerable.rb +2 -2
  11. data/lib/twitter/error.rb +7 -0
  12. data/lib/twitter/geo_results.rb +1 -1
  13. data/lib/twitter/list.rb +3 -2
  14. data/lib/twitter/media/photo.rb +1 -1
  15. data/lib/twitter/place.rb +13 -15
  16. data/lib/twitter/profile.rb +1 -1
  17. data/lib/twitter/profile_banner.rb +1 -1
  18. data/lib/twitter/rest/client.rb +17 -2
  19. data/lib/twitter/rest/friends_and_followers.rb +1 -1
  20. data/lib/twitter/rest/lists.rb +4 -2
  21. data/lib/twitter/rest/spam_reporting.rb +1 -1
  22. data/lib/twitter/rest/tweets.rb +17 -17
  23. data/lib/twitter/rest/users.rb +77 -13
  24. data/lib/twitter/rest/utils.rb +10 -6
  25. data/lib/twitter/search_results.rb +1 -1
  26. data/lib/twitter/settings.rb +4 -3
  27. data/lib/twitter/source_user.rb +3 -2
  28. data/lib/twitter/streaming/client.rb +7 -2
  29. data/lib/twitter/streaming/connection.rb +9 -2
  30. data/lib/twitter/streaming/response.rb +3 -3
  31. data/lib/twitter/suggestion.rb +1 -1
  32. data/lib/twitter/target_user.rb +1 -1
  33. data/lib/twitter/trend.rb +2 -1
  34. data/lib/twitter/trend_results.rb +1 -1
  35. data/lib/twitter/tweet.rb +4 -4
  36. data/lib/twitter/user.rb +60 -19
  37. data/lib/twitter/utils.rb +12 -5
  38. data/lib/twitter/version.rb +1 -1
  39. data/spec/fixtures/following.json +1 -1
  40. data/spec/fixtures/sferik.json +1 -1
  41. data/spec/helper.rb +14 -5
  42. data/spec/twitter/base_spec.rb +16 -4
  43. data/spec/twitter/direct_message_spec.rb +12 -13
  44. data/spec/twitter/entity/uri_spec.rb +2 -2
  45. data/spec/twitter/error_spec.rb +2 -2
  46. data/spec/twitter/media/photo_spec.rb +4 -4
  47. data/spec/twitter/oembed_spec.rb +3 -3
  48. data/spec/twitter/place_spec.rb +1 -1
  49. data/spec/twitter/rest/client_spec.rb +54 -14
  50. data/spec/twitter/rest/friends_and_followers_spec.rb +76 -76
  51. data/spec/twitter/rest/lists_spec.rb +85 -64
  52. data/spec/twitter/rest/timelines_spec.rb +2 -2
  53. data/spec/twitter/rest/tweets_spec.rb +20 -16
  54. data/spec/twitter/rest/undocumented_spec.rb +17 -17
  55. data/spec/twitter/rest/users_spec.rb +101 -17
  56. data/spec/twitter/streaming/client_spec.rb +1 -1
  57. data/spec/twitter/streaming/connection_spec.rb +32 -0
  58. data/spec/twitter/streaming/response_spec.rb +21 -0
  59. data/spec/twitter/trend_spec.rb +1 -1
  60. data/spec/twitter/tweet_spec.rb +14 -23
  61. data/spec/twitter/user_spec.rb +120 -13
  62. data/twitter.gemspec +3 -3
  63. metadata +8 -4
@@ -151,7 +151,7 @@ module Twitter
151
151
  # @param users [Enumerable<Integer, String, Twitter::User>] A collection of Twitter user IDs, screen names, or objects.
152
152
  # @param options [Hash] A customizable set of options.
153
153
  def unfollow(*args)
154
- parallel_user_objects_from_response(:post, '/1.1/friendships/destroy.json', args)
154
+ parallel_users_from_response(:post, '/1.1/friendships/destroy.json', args)
155
155
  end
156
156
  alias_method :destroy_friendship, :unfollow
157
157
  deprecate_alias :friendship_destroy, :unfollow
@@ -477,10 +477,12 @@ module Twitter
477
477
  # @param user[Integer, String, Twitter::User] A Twitter user ID, screen_name, or object.
478
478
  # @return [Hash]
479
479
  def merge_owner!(hash, user)
480
- unless hash[:owner_id] || hash[:owner_screen_name]
481
- user ||= screen_name
480
+ return hash if hash[:owner_id] || hash[:owner_screen_name]
481
+ if user
482
482
  merge_user!(hash, user, 'owner')
483
483
  hash[:owner_id] = hash.delete(:owner_user_id) unless hash[:owner_user_id].nil?
484
+ else
485
+ hash[:owner_id] = user_id
484
486
  end
485
487
  hash
486
488
  end
@@ -20,7 +20,7 @@ module Twitter
20
20
  # @param users [Enumerable<Integer, String, Twitter::User>] A collection of Twitter user IDs, screen names, or objects.
21
21
  # @param options [Hash] A customizable set of options.
22
22
  def report_spam(*args)
23
- parallel_user_objects_from_response(:post, '/1.1/users/report_spam.json', args)
23
+ parallel_users_from_response(:post, '/1.1/users/report_spam.json', args)
24
24
  end
25
25
  end
26
26
  end
@@ -11,6 +11,7 @@ module Twitter
11
11
  module Tweets
12
12
  include Twitter::REST::Utils
13
13
  include Twitter::Utils
14
+ MAX_TWEETS_PER_REQUEST = 100
14
15
 
15
16
  # Returns up to 100 of the first retweets of a given tweet
16
17
  #
@@ -38,7 +39,7 @@ module Twitter
38
39
  # @param options [Hash] A customizable set of options.
39
40
  # @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 100.
40
41
  # @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
41
- # @option options [Boolean] :ids_only ('false') Only return user ids instead of full user objects.
42
+ # @option options [Boolean] :ids_only ('false') Only return user IDs instead of full user objects.
42
43
  def retweeters_of(tweet, options = {})
43
44
  ids_only = !!options.delete(:ids_only)
44
45
  retweeters = retweets(tweet, options).collect(&:user)
@@ -62,19 +63,24 @@ module Twitter
62
63
 
63
64
  # Returns Tweets
64
65
  #
65
- # @see https://dev.twitter.com/docs/api/1.1/get/statuses/show/:id
66
+ # @see https://dev.twitter.com/docs/api/1.1/get/statuses/lookup
66
67
  # @rate_limited Yes
67
- # @authentication Requires user context
68
- # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
68
+ # @authentication Required
69
69
  # @return [Array<Twitter::Tweet>] The requested Tweets.
70
70
  # @overload statuses(*tweets)
71
71
  # @param tweets [Enumerable<Integer, String, URI, Twitter::Tweet>] A collection of Tweet IDs, URIs, or objects.
72
72
  # @overload statuses(*tweets, options)
73
73
  # @param tweets [Enumerable<Integer, String, URI, Twitter::Tweet>] A collection of Tweet IDs, URIs, or objects.
74
74
  # @param options [Hash] A customizable set of options.
75
+ # @option options [Symbol, String] :method Requests users via a GET request instead of the standard POST request if set to ':get'.
76
+ # @option options [Boolean] :include_entities The tweet entities node will be disincluded when set to false.
75
77
  # @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
76
78
  def statuses(*args)
77
- parallel_tweets_from_response(:get, '/1.1/statuses/show', args)
79
+ arguments = Twitter::Arguments.new(args)
80
+ request_method = arguments.options.delete(:method) || :post
81
+ flat_pmap(arguments.each_slice(MAX_TWEETS_PER_REQUEST)) do |tweets|
82
+ perform_with_objects(request_method, '/1.1/statuses/lookup.json', arguments.options.merge(:id => tweets.collect { |u| extract_id(u) }.join(',')), Twitter::Tweet)
83
+ end
78
84
  end
79
85
 
80
86
  # Destroys the specified Tweets
@@ -92,7 +98,10 @@ module Twitter
92
98
  # @param options [Hash] A customizable set of options.
93
99
  # @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
94
100
  def destroy_status(*args)
95
- parallel_tweets_from_response(:post, '/1.1/statuses/destroy', args)
101
+ arguments = Twitter::Arguments.new(args)
102
+ pmap(arguments) do |tweet|
103
+ perform_with_object(:post, "/1.1/statuses/destroy/#{extract_id(tweet)}.json", arguments.options, Twitter::Tweet)
104
+ end
96
105
  end
97
106
  alias_method :destroy_tweet, :destroy_status
98
107
  deprecate_alias :status_destroy, :destroy_status
@@ -200,6 +209,7 @@ module Twitter
200
209
  # @rate_limited No
201
210
  # @authentication Requires user context
202
211
  # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
212
+ # @raise [Twitter::Error::UnacceptableIO] Error when the IO object for the media argument does not have a to_io method.
203
213
  # @return [Twitter::Tweet] The created Tweet.
204
214
  # @param status [String] The text of your status update, up to 140 characters.
205
215
  # @param media [File, Hash] A File object with your picture (PNG, JPEG or GIF)
@@ -214,6 +224,7 @@ module Twitter
214
224
  # @option options [String] :display_coordinates Whether or not to put a pin on the exact coordinates a tweet has been sent from.
215
225
  # @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
216
226
  def update_with_media(status, media, options = {})
227
+ fail(Twitter::Error::UnacceptableIO.new) unless media.respond_to?(:to_io)
217
228
  hash = options.dup
218
229
  hash[:in_reply_to_status_id] = hash.delete(:in_reply_to_status).id unless hash[:in_reply_to_status].nil?
219
230
  hash[:place_id] = hash.delete(:place).woeid unless hash[:place].nil?
@@ -287,17 +298,6 @@ module Twitter
287
298
 
288
299
  private
289
300
 
290
- # @param request_method [Symbol]
291
- # @param path [String]
292
- # @param args [Array]
293
- # @return [Array<Twitter::Tweet>]
294
- def parallel_tweets_from_response(request_method, path, args)
295
- arguments = Twitter::Arguments.new(args)
296
- pmap(arguments) do |tweet|
297
- perform_with_object(request_method, path + "/#{extract_id(tweet)}.json", arguments.options, Twitter::Tweet)
298
- end
299
- end
300
-
301
301
  def post_retweet(tweet, options)
302
302
  response = post("/1.1/statuses/retweet/#{extract_id(tweet)}.json", options).body
303
303
  Twitter::Tweet.new(response)
@@ -34,7 +34,7 @@ module Twitter
34
34
  request_method = options.size.zero? ? :get : :post
35
35
  response = send(request_method.to_sym, '/1.1/account/settings.json', options).body
36
36
  # https://dev.twitter.com/issues/59
37
- response.update(:trend_location => Array(response[:trend_location]).first)
37
+ response.update(:trend_location => response.fetch(:trend_location, []).first)
38
38
  Twitter::Settings.new(response)
39
39
  end
40
40
 
@@ -136,19 +136,21 @@ module Twitter
136
136
  # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
137
137
  # @return [Array<Twitter::User>] User objects that the authenticating user is blocking.
138
138
  # @param options [Hash] A customizable set of options.
139
- # @option options [Integer] :page Specifies the page of results to retrieve.
140
- def blocking(options = {})
139
+ # @option options [Boolean] :include_entities The tweet entities node will be disincluded when set to false.
140
+ # @option options [Boolean, String, Integer] :skip_status Do not include user's Tweets when set to true, 't' or 1.
141
+ def blocked(options = {})
141
142
  perform_with_cursor(:get, '/1.1/blocks/list.json', options, :users, Twitter::User)
142
143
  end
144
+ deprecate_alias :blocking, :blocked
143
145
 
144
- # Returns an array of numeric user ids the authenticating user is blocking
146
+ # Returns an array of numeric user IDs the authenticating user is blocking
145
147
  #
146
148
  # @see https://dev.twitter.com/docs/api/1.1/get/blocks/ids
147
149
  # @rate_limited Yes
148
150
  # @authentication Requires user context
149
151
  # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
150
152
  # @return [Twitter::Cursor] Numeric user IDs the authenticating user is blocking.
151
- # @overload block(options = {})
153
+ # @overload blocked_ids(options = {})
152
154
  # @param options [Hash] A customizable set of options.
153
155
  def blocked_ids(*args)
154
156
  arguments = Twitter::Arguments.new(args)
@@ -191,7 +193,7 @@ module Twitter
191
193
  # @param users [Enumerable<Integer, String, Twitter::User>] A collection of Twitter user IDs, screen names, or objects.
192
194
  # @param options [Hash] A customizable set of options.
193
195
  def block(*args)
194
- parallel_user_objects_from_response(:post, '/1.1/blocks/create.json', args)
196
+ parallel_users_from_response(:post, '/1.1/blocks/create.json', args)
195
197
  end
196
198
 
197
199
  # Un-blocks the users specified by the authenticating user
@@ -207,14 +209,14 @@ module Twitter
207
209
  # @param users [Enumerable<Integer, String, Twitter::User>] A collection of Twitter user IDs, screen names, or objects.
208
210
  # @param options [Hash] A customizable set of options.
209
211
  def unblock(*args)
210
- parallel_user_objects_from_response(:post, '/1.1/blocks/destroy.json', args)
212
+ parallel_users_from_response(:post, '/1.1/blocks/destroy.json', args)
211
213
  end
212
214
 
213
215
  # Returns extended information for up to 100 users
214
216
  #
215
217
  # @see https://dev.twitter.com/docs/api/1.1/get/users/lookup
216
218
  # @rate_limited Yes
217
- # @authentication Requires user context
219
+ # @authentication Required
218
220
  # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
219
221
  # @return [Array<Twitter::User>] The requested users.
220
222
  # @overload users(*users)
@@ -252,8 +254,8 @@ module Twitter
252
254
  # @option options [Boolean, String, Integer] :skip_status Do not include user's Tweets when set to true, 't' or 1.
253
255
  def user(*args)
254
256
  arguments = Twitter::Arguments.new(args)
255
- if arguments.last
256
- merge_user!(arguments.options, arguments.pop)
257
+ if arguments.last || user_id?
258
+ merge_user!(arguments.options, arguments.pop || user_id)
257
259
  perform_with_object(:get, '/1.1/users/show.json', arguments.options, Twitter::User)
258
260
  else
259
261
  verify_credentials(arguments.options)
@@ -305,7 +307,7 @@ module Twitter
305
307
  # @param options [Hash] A customizable set of options.
306
308
  # @option options [Boolean, String, Integer] :skip_status Do not include contributee's Tweets when set to true, 't' or 1.
307
309
  def contributees(*args)
308
- user_objects_from_response(:get, '/1.1/users/contributees.json', args)
310
+ users_from_response(:get, '/1.1/users/contributees.json', args)
309
311
  end
310
312
 
311
313
  # Returns an array of users who can contribute to the specified account
@@ -323,7 +325,7 @@ module Twitter
323
325
  # @param options [Hash] A customizable set of options.
324
326
  # @option options [Boolean, String, Integer] :skip_status Do not include contributee's Tweets when set to true, 't' or 1.
325
327
  def contributors(*args)
326
- user_objects_from_response(:get, '/1.1/users/contributors.json', args)
328
+ users_from_response(:get, '/1.1/users/contributors.json', args)
327
329
  end
328
330
 
329
331
  # Removes the authenticating user's profile banner image
@@ -375,9 +377,71 @@ module Twitter
375
377
  # @param user [Integer, String, Twitter::User] A Twitter user ID, screen name, URI, or object.
376
378
  def profile_banner(*args)
377
379
  arguments = Twitter::Arguments.new(args)
378
- merge_user!(arguments.options, arguments.pop || screen_name) unless arguments.options[:user_id] || arguments.options[:screen_name]
380
+ merge_user!(arguments.options, arguments.pop || user_id) unless arguments.options[:user_id] || arguments.options[:screen_name]
379
381
  perform_with_object(:get, '/1.1/users/profile_banner.json', arguments.options, Twitter::ProfileBanner)
380
382
  end
383
+
384
+ # Mutes the users specified by the authenticating user
385
+ #
386
+ # @see https://dev.twitter.com/docs/api/1.1/post/mutes/users/create
387
+ # @rate_limited Yes
388
+ # @authentication Requires user context
389
+ # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
390
+ # @return [Array<Twitter::User>] The muted users.
391
+ # @overload mute(*users)
392
+ # @param users [Enumerable<Integer, String, Twitter::User>] A collection of Twitter user IDs, screen names, or objects.
393
+ # @overload mute(*users, options)
394
+ # @param users [Enumerable<Integer, String, Twitter::User>] A collection of Twitter user IDs, screen names, or objects.
395
+ # @param options [Hash] A customizable set of options.
396
+ def mute(*args)
397
+ parallel_users_from_response(:post, '/1.1/mutes/users/create.json', args)
398
+ end
399
+
400
+ # Un-mutes the user specified by the authenticating user.
401
+ #
402
+ # @see https://dev.twitter.com/docs/api/1.1/post/mutes/users/destroy
403
+ # @rate_limited Yes
404
+ # @authentication Requires user context
405
+ # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
406
+ # @return [Array<Twitter::User>] The un-muted users.
407
+ # @overload unmute(*users)
408
+ # @param users [Enumerable<Integer, String, Twitter::User>] A collection of Twitter user IDs, screen names, or objects.
409
+ # @overload unmute(*users, options)
410
+ # @param users [Enumerable<Integer, String, Twitter::User>] A collection of Twitter user IDs, screen names, or objects.
411
+ # @param options [Hash] A customizable set of options.
412
+ def unmute(*args)
413
+ parallel_users_from_response(:post, '/1.1/mutes/users/destroy.json', args)
414
+ end
415
+
416
+ # Returns an array of user objects that the authenticating user is muting
417
+ #
418
+ # @see https://dev.twitter.com/docs/api/1.1/get/mutes/users/list
419
+ # @rate_limited Yes
420
+ # @authentication Requires user context
421
+ # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
422
+ # @return [Array<Twitter::User>] User objects that the authenticating user is muting.
423
+ # @param options [Hash] A customizable set of options.
424
+ # @option options [Boolean] :include_entities The tweet entities node will be disincluded when set to false.
425
+ # @option options [Boolean, String, Integer] :skip_status Do not include user's Tweets when set to true, 't' or 1.
426
+ def muted(options = {})
427
+ perform_with_cursor(:get, '/1.1/mutes/users/list.json', options, :users, Twitter::User)
428
+ end
429
+ deprecate_alias :muting, :muted
430
+
431
+ # Returns an array of numeric user IDs the authenticating user is muting
432
+ #
433
+ # @see https://dev.twitter.com/docs/api/1.1/get/mutes/users/ids
434
+ # @rate_limited Yes
435
+ # @authentication Requires user context
436
+ # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
437
+ # @return [Twitter::Cursor] Numeric user IDs the authenticating user is muting
438
+ # @overload muted_ids(options = {})
439
+ # @param options [Hash] A customizable set of options.
440
+ def muted_ids(*args)
441
+ arguments = Twitter::Arguments.new(args)
442
+ merge_user!(arguments.options, arguments.pop)
443
+ perform_with_cursor(:get, '/1.1/mutes/users/ids.json', arguments.options, :ids)
444
+ end
381
445
  end
382
446
  end
383
447
  end
@@ -62,7 +62,7 @@ module Twitter
62
62
  # @param path [String]
63
63
  # @param args [Array]
64
64
  # @return [Array<Twitter::User>]
65
- def parallel_user_objects_from_response(request_method, path, args)
65
+ def parallel_users_from_response(request_method, path, args)
66
66
  arguments = Twitter::Arguments.new(args)
67
67
  pmap(arguments) do |user|
68
68
  perform_with_object(request_method, path, merge_user(arguments.options, user), Twitter::User)
@@ -73,9 +73,9 @@ module Twitter
73
73
  # @param path [String]
74
74
  # @param args [Array]
75
75
  # @return [Array<Twitter::User>]
76
- def user_objects_from_response(request_method, path, args)
76
+ def users_from_response(request_method, path, args)
77
77
  arguments = Twitter::Arguments.new(args)
78
- merge_user!(arguments.options, arguments.pop || screen_name) unless arguments.options[:user_id] || arguments.options[:screen_name]
78
+ merge_user!(arguments.options, arguments.pop || user_id) unless arguments.options[:user_id] || arguments.options[:screen_name]
79
79
  perform_with_objects(request_method, path, arguments.options, Twitter::User)
80
80
  end
81
81
 
@@ -110,12 +110,16 @@ module Twitter
110
110
  # @return [Twitter::Cursor]
111
111
  def cursor_from_response_with_user(collection_name, klass, request_method, path, args) # rubocop:disable ParameterLists
112
112
  arguments = Twitter::Arguments.new(args)
113
- merge_user!(arguments.options, arguments.pop || screen_name) unless arguments.options[:user_id] || arguments.options[:screen_name]
113
+ merge_user!(arguments.options, arguments.pop || user_id) unless arguments.options[:user_id] || arguments.options[:screen_name]
114
114
  perform_with_cursor(request_method, path, arguments.options, collection_name, klass)
115
115
  end
116
116
 
117
- def screen_name
118
- @screen_name ||= verify_credentials.screen_name
117
+ def user_id
118
+ @user_id ||= verify_credentials(:include_entities => false, :skip_status => true).id
119
+ end
120
+
121
+ def user_id?
122
+ instance_variable_defined?(:@user_id)
119
123
  end
120
124
 
121
125
  def merge_default_cursor!(options)
@@ -58,7 +58,7 @@ module Twitter
58
58
  # @return [Hash]
59
59
  def attrs=(attrs)
60
60
  @attrs = attrs
61
- Array(@attrs[:statuses]).collect do |tweet|
61
+ @attrs.fetch(:statuses, []).collect do |tweet|
62
62
  @collection << Tweet.new(tweet)
63
63
  end
64
64
  @attrs
@@ -2,9 +2,10 @@ require 'twitter/base'
2
2
 
3
3
  module Twitter
4
4
  class Settings < Twitter::Base
5
- attr_reader :always_use_https, :discoverable_by_email, :geo_enabled,
6
- :language, :protected, :screen_name, :show_all_inline_media,
7
- :sleep_time, :time_zone
5
+ attr_reader :language, :screen_name, :sleep_time, :time_zone
8
6
  object_attr_reader :Place, :trend_location
7
+ predicate_attr_reader :always_use_https, :discoverable_by_email,
8
+ :geo_enabled, :protected, :show_all_inline_media,
9
+ :use_cookie_personalization
9
10
  end
10
11
  end
@@ -2,7 +2,8 @@ require 'twitter/basic_user'
2
2
 
3
3
  module Twitter
4
4
  class SourceUser < Twitter::BasicUser
5
- attr_reader :all_replies, :blocking, :can_dm, :followed_by, :marked_spam,
6
- :notifications_enabled, :want_retweets
5
+ predicate_attr_reader :all_replies, :blocking, :can_dm, :followed_by,
6
+ :marked_spam, :muting, :notifications_enabled,
7
+ :want_retweets
7
8
  end
8
9
  end
@@ -9,13 +9,17 @@ module Twitter
9
9
  module Streaming
10
10
  class Client < Twitter::Client
11
11
  attr_writer :connection
12
+ attr_accessor :tcp_socket_class, :ssl_socket_class
12
13
 
13
14
  # Initializes a new Client object
14
15
  #
16
+ # @param options [Hash] A customizable set of options.
17
+ # @option options [String] :tcp_socket_class A class that Connection will use to create a new TCP socket.
18
+ # @option options [String] :ssl_socket_class A class that Connection will use to create a new SSL socket.
15
19
  # @return [Twitter::Streaming::Client]
16
20
  def initialize(options = {})
17
21
  super
18
- @connection = Streaming::Connection.new
22
+ @connection = Streaming::Connection.new(options)
19
23
  end
20
24
 
21
25
  # Returns public statuses that match one or more filter predicates
@@ -77,7 +81,8 @@ module Twitter
77
81
  # @see https://dev.twitter.com/docs/streaming-apis/parameters
78
82
  # @param options [Hash] A customizable set of options.
79
83
  # @option options [String] :with Specifies whether to return information for just the users specified in the follow parameter, or include messages from accounts they follow.
80
- # @option options [String] :replies Specifies whether stall warnings should be delivered.
84
+ # @option options [String] :replies Specifies whether to return additional @replies.
85
+ # @option options [String] :stall_warnings Specifies whether stall warnings should be delivered.
81
86
  # @option options [String] :track Includes additional Tweets matching the specified keywords. Phrases of keywords are specified by a comma-separated list.
82
87
  # @option options [String] :locations Includes additional Tweets falling within the specified bounding boxes.
83
88
  # @yield [Twitter::Tweet, Twitter::Streaming::Event, Twitter::DirectMessage, Twitter::Streaming::FriendList, Twitter::Streaming::DeletedTweet, Twitter::Streaming::StallWarning] A stream of Twitter objects.
@@ -5,10 +5,17 @@ require 'resolv'
5
5
  module Twitter
6
6
  module Streaming
7
7
  class Connection
8
+ def initialize(opts = {})
9
+ @tcp_socket_class = opts.fetch(:tcp_socket_class) { TCPSocket }
10
+ @ssl_socket_class = opts.fetch(:ssl_socket_class) { OpenSSL::SSL::SSLSocket }
11
+ end
12
+ attr_reader :tcp_socket_class, :ssl_socket_class
13
+
8
14
  def stream(request, response)
9
15
  client_context = OpenSSL::SSL::SSLContext.new
10
- client = TCPSocket.new(Resolv.getaddress(request.uri.host), request.uri.port)
11
- ssl_client = OpenSSL::SSL::SSLSocket.new(client, client_context)
16
+ client = @tcp_socket_class.new(Resolv.getaddress(request.uri.host), request.uri.port)
17
+ ssl_client = @ssl_socket_class.new(client, client_context)
18
+
12
19
  ssl_client.connect
13
20
  request.stream(ssl_client)
14
21
  while body = ssl_client.readpartial(1024) # rubocop:disable AssignmentInCondition, WhileUntilModifier
@@ -16,9 +16,9 @@ module Twitter
16
16
  @parser << data
17
17
  end
18
18
 
19
- def on_headers_complete(headers)
20
- # TODO: handle response codes
21
- p(:status_code => @parser.status_code, :header => headers) unless @parser.status_code == 200
19
+ def on_headers_complete(_headers)
20
+ error = Twitter::Error.errors[@parser.status_code]
21
+ fail error.new if error
22
22
  end
23
23
 
24
24
  def on_body(data)
@@ -8,7 +8,7 @@ module Twitter
8
8
 
9
9
  # @return [Array<Twitter::User>]
10
10
  def users
11
- Array(@attrs[:users]).collect do |user|
11
+ @attrs.fetch(:users, []).collect do |user|
12
12
  User.new(user)
13
13
  end
14
14
  end
@@ -2,6 +2,6 @@ require 'twitter/basic_user'
2
2
 
3
3
  module Twitter
4
4
  class TargetUser < Twitter::BasicUser
5
- attr_reader :followed_by
5
+ predicate_attr_reader :followed_by
6
6
  end
7
7
  end
@@ -4,7 +4,8 @@ require 'twitter/base'
4
4
  module Twitter
5
5
  class Trend < Twitter::Base
6
6
  include Equalizer.new(:name)
7
- attr_reader :events, :name, :promoted_content, :query
7
+ attr_reader :events, :name, :query
8
+ predicate_attr_reader :promoted_content
8
9
  uri_attr_reader :uri
9
10
  end
10
11
  end