twitter 6.1.0 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +22 -15
  3. data/README.md +69 -394
  4. data/lib/twitter/base.rb +2 -16
  5. data/lib/twitter/basic_user.rb +0 -3
  6. data/lib/twitter/client.rb +5 -19
  7. data/lib/twitter/configuration.rb +3 -2
  8. data/lib/twitter/creatable.rb +1 -1
  9. data/lib/twitter/cursor.rb +0 -1
  10. data/lib/twitter/entity/uri.rb +0 -4
  11. data/lib/twitter/error.rb +81 -96
  12. data/lib/twitter/geo_results.rb +0 -1
  13. data/lib/twitter/headers.rb +11 -10
  14. data/lib/twitter/media/photo.rb +4 -0
  15. data/lib/twitter/media/video.rb +4 -1
  16. data/lib/twitter/media/video_info.rb +1 -1
  17. data/lib/twitter/null_object.rb +2 -2
  18. data/lib/twitter/profile.rb +3 -2
  19. data/lib/twitter/rate_limit.rb +1 -1
  20. data/lib/twitter/rest/api.rb +0 -2
  21. data/lib/twitter/rest/client.rb +0 -78
  22. data/lib/twitter/rest/direct_messages.rb +3 -3
  23. data/lib/twitter/rest/favorites.rb +25 -4
  24. data/lib/twitter/rest/friends_and_followers.rb +1 -3
  25. data/lib/twitter/rest/lists.rb +18 -29
  26. data/lib/twitter/rest/oauth.rb +15 -15
  27. data/lib/twitter/rest/request.rb +105 -16
  28. data/lib/twitter/rest/saved_searches.rb +0 -2
  29. data/lib/twitter/rest/search.rb +2 -0
  30. data/lib/twitter/rest/trends.rb +1 -0
  31. data/lib/twitter/rest/tweets.rb +80 -15
  32. data/lib/twitter/rest/undocumented.rb +3 -4
  33. data/lib/twitter/rest/users.rb +20 -34
  34. data/lib/twitter/rest/utils.rb +13 -20
  35. data/lib/twitter/search_results.rb +1 -2
  36. data/lib/twitter/streaming/client.rb +17 -23
  37. data/lib/twitter/streaming/connection.rb +23 -10
  38. data/lib/twitter/streaming/deleted_tweet.rb +0 -1
  39. data/lib/twitter/streaming/event.rb +6 -6
  40. data/lib/twitter/streaming/message_parser.rb +1 -1
  41. data/lib/twitter/streaming/response.rb +2 -2
  42. data/lib/twitter/trend_results.rb +1 -2
  43. data/lib/twitter/tweet.rb +1 -5
  44. data/lib/twitter/user.rb +0 -2
  45. data/lib/twitter/utils.rb +1 -16
  46. data/lib/twitter/version.rb +1 -1
  47. data/twitter.gemspec +13 -13
  48. metadata +35 -27
  49. data/lib/twitter/rest/media.rb +0 -30
  50. data/lib/twitter/rest/request/multipart_with_file.rb +0 -47
  51. data/lib/twitter/rest/response/parse_error_json.rb +0 -13
  52. data/lib/twitter/rest/response/parse_json.rb +0 -31
  53. data/lib/twitter/rest/response/raise_error.rb +0 -32
  54. data/lib/twitter/token.rb +0 -20
@@ -1,16 +1,20 @@
1
1
  require 'addressable/uri'
2
- require 'faraday'
2
+ require 'http'
3
+ require 'http/form_data'
3
4
  require 'json'
4
- require 'timeout'
5
+ require 'openssl'
5
6
  require 'twitter/error'
6
7
  require 'twitter/headers'
7
8
  require 'twitter/rate_limit'
9
+ require 'twitter/utils'
8
10
 
9
11
  module Twitter
10
12
  module REST
11
13
  class Request
12
- attr_accessor :client, :headers, :options, :rate_limit, :request_method,
13
- :path, :uri
14
+ include Twitter::Utils
15
+ BASE_URL = 'https://api.twitter.com'.freeze
16
+ attr_accessor :client, :headers, :options, :path, :rate_limit,
17
+ :request_method, :uri
14
18
  alias verb request_method
15
19
 
16
20
  # @param client [Twitter::Client]
@@ -20,24 +24,109 @@ module Twitter
20
24
  # @return [Twitter::REST::Request]
21
25
  def initialize(client, request_method, path, options = {})
22
26
  @client = client
23
- @request_method = request_method.to_sym
24
- @path = path
25
- @uri = Addressable::URI.parse(client.connection.url_prefix + path)
27
+ @uri = Addressable::URI.parse(path.start_with?('http') ? path : BASE_URL + path)
28
+ set_multipart_options!(request_method, options)
29
+ @path = uri.path
26
30
  @options = options
27
31
  end
28
32
 
29
33
  # @return [Array, Hash]
30
34
  def perform
31
- @headers = Twitter::Headers.new(@client, @request_method, @uri.to_s, @options).request_headers
32
- begin
33
- response = @client.connection.send(@request_method, @path, @options) { |request| request.headers.update(@headers) }.env
34
- rescue Faraday::Error::TimeoutError, Timeout::Error => error
35
- raise(Twitter::Error::RequestTimeout.new(error))
36
- rescue Faraday::Error::ClientError, JSON::ParserError => error
37
- raise(Twitter::Error.new(error))
35
+ options_key = @request_method == :get ? :params : :form
36
+ response = http_client.headers(@headers).public_send(@request_method, @uri.to_s, options_key => @options)
37
+ response_body = response.body.empty? ? '' : symbolize_keys!(response.parse)
38
+ response_headers = response.headers
39
+ fail_or_return_response_body(response.code, response_body, response_headers)
40
+ end
41
+
42
+ private
43
+
44
+ def merge_multipart_file!(options)
45
+ key = options.delete(:key)
46
+ file = options.delete(:file)
47
+
48
+ options[key] = if file.is_a?(StringIO)
49
+ HTTP::FormData::File.new(file, mime_type: 'video/mp4')
50
+ else
51
+ HTTP::FormData::File.new(file, filename: File.basename(file), mime_type: mime_type(File.basename(file)))
52
+ end
53
+ end
54
+
55
+ def set_multipart_options!(request_method, options)
56
+ if request_method == :multipart_post
57
+ merge_multipart_file!(options)
58
+ @request_method = :post
59
+ @headers = Twitter::Headers.new(@client, @request_method, @uri).request_headers
60
+ else
61
+ @request_method = request_method
62
+ @headers = Twitter::Headers.new(@client, @request_method, @uri, options).request_headers
63
+ end
64
+ end
65
+
66
+ def mime_type(basename)
67
+ case basename
68
+ when /\.gif$/i
69
+ 'image/gif'
70
+ when /\.jpe?g/i
71
+ 'image/jpeg'
72
+ when /\.png$/i
73
+ 'image/png'
74
+ else
75
+ 'application/octet-stream'
76
+ end
77
+ end
78
+
79
+ def fail_or_return_response_body(code, body, headers)
80
+ error = error(code, body, headers)
81
+ raise(error) if error
82
+ @rate_limit = Twitter::RateLimit.new(headers)
83
+ body
84
+ end
85
+
86
+ def error(code, body, headers)
87
+ klass = Twitter::Error::ERRORS[code]
88
+ if klass == Twitter::Error::Forbidden
89
+ forbidden_error(body, headers)
90
+ elsif !klass.nil?
91
+ klass.from_response(body, headers)
92
+ end
93
+ end
94
+
95
+ def forbidden_error(body, headers)
96
+ error = Twitter::Error::Forbidden.from_response(body, headers)
97
+ klass = Twitter::Error::FORBIDDEN_MESSAGES[error.message]
98
+ if klass
99
+ klass.from_response(body, headers)
100
+ else
101
+ error
102
+ end
103
+ end
104
+
105
+ def symbolize_keys!(object)
106
+ if object.is_a?(Array)
107
+ object.each_with_index do |val, index|
108
+ object[index] = symbolize_keys!(val)
109
+ end
110
+ elsif object.is_a?(Hash)
111
+ object.dup.each_key do |key|
112
+ object[key.to_sym] = symbolize_keys!(object.delete(key))
113
+ end
38
114
  end
39
- @rate_limit = Twitter::RateLimit.new(response.response_headers)
40
- response.body
115
+ object
116
+ end
117
+
118
+ # @return [HTTP::Client, HTTP]
119
+ def http_client
120
+ client = @client.proxy ? HTTP.via(*proxy) : HTTP
121
+ client = client.timeout(:per_operation, connect: @client.timeouts[:connect], read: @client.timeouts[:read], write: @client.timeouts[:write]) if @client.timeouts
122
+ client
123
+ end
124
+
125
+ # Return proxy values as a compacted array
126
+ #
127
+ # @return [Array]
128
+ def proxy
129
+ @client.proxy.values_at(:host, :port, :username, :password).compact
41
130
  end
42
131
  end
43
132
  end
@@ -65,7 +65,6 @@ module Twitter
65
65
  def create_saved_search(query, options = {})
66
66
  perform_post_with_object('/1.1/saved_searches/create.json', options.merge(query: query), Twitter::SavedSearch)
67
67
  end
68
- deprecate_alias :saved_search_create, :create_saved_search
69
68
 
70
69
  # Destroys saved searches for the authenticated user
71
70
  #
@@ -86,7 +85,6 @@ module Twitter
86
85
  perform_post_with_object("/1.1/saved_searches/destroy/#{id}.json", arguments.options, Twitter::SavedSearch)
87
86
  end
88
87
  end
89
- deprecate_alias :saved_search_destroy, :destroy_saved_search
90
88
  end
91
89
  end
92
90
  end
@@ -24,8 +24,10 @@ module Twitter
24
24
  # @option options [String] :until Optional. Returns tweets generated before the given date. Date should be formatted as YYYY-MM-DD.
25
25
  # @option options [Integer] :since_id Returns results with an ID greater than (that is, more recent than) the specified ID. There are limits to the number of Tweets which can be accessed through the API. If the limit of Tweets has occured since the since_id, the since_id will be forced to the oldest ID available.
26
26
  # @option options [Integer] :max_id Returns results with an ID less than (that is, older than) or equal to the specified ID.
27
+ # @option options [Boolean] :include_entities The entities node will be disincluded when set to false.
27
28
  # @return [Twitter::SearchResults] Return tweets that match a specified query with search metadata
28
29
  def search(q, options = {})
30
+ options = options.dup
29
31
  options[:count] ||= MAX_TWEETS_PER_REQUEST
30
32
  request = Twitter::REST::Request.new(self, :get, '/1.1/search/tweets.json', options.merge(q: q))
31
33
  Twitter::SearchResults.new(request)
@@ -19,6 +19,7 @@ module Twitter
19
19
  # @option options [String] :exclude Setting this equal to 'hashtags' will remove all hashtags from the trends list.
20
20
  # @return [Array<Twitter::Trend>]
21
21
  def trends(id = 1, options = {})
22
+ options = options.dup
22
23
  options[:id] = id
23
24
  response = perform_get('/1.1/trends/place.json', options).first
24
25
  Twitter::TrendResults.new(response)
@@ -41,6 +41,7 @@ module Twitter
41
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.
42
42
  # @option options [Boolean] :ids_only ('false') Only return user IDs instead of full user objects.
43
43
  def retweeters_of(tweet, options = {})
44
+ options = options.dup
44
45
  ids_only = !!options.delete(:ids_only)
45
46
  retweeters = retweets(tweet, options).collect(&:user)
46
47
  ids_only ? retweeters.collect(&:id) : retweeters
@@ -52,7 +53,7 @@ module Twitter
52
53
  # @rate_limited Yes
53
54
  # @authentication Requires user context
54
55
  # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
55
- # @raise [Twitter::Error::Forbidden] Error raised when supplied status is over 140 characters.
56
+ # @raise [Twitter::Error::Forbidden] Error raised when supplied status is over 280 characters.
56
57
  # @return [Twitter::Tweet] The requested Tweet.
57
58
  # @param tweet [Integer, String, URI, Twitter::Tweet] A Tweet ID, URI, or object.
58
59
  # @param options [Hash] A customizable set of options.
@@ -101,8 +102,6 @@ module Twitter
101
102
  end
102
103
  end
103
104
  alias destroy_tweet destroy_status
104
- deprecate_alias :status_destroy, :destroy_status
105
- deprecate_alias :tweet_destroy, :destroy_status
106
105
 
107
106
  # Updates the authenticating user's status
108
107
  #
@@ -112,7 +111,7 @@ module Twitter
112
111
  # @authentication Requires user context
113
112
  # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
114
113
  # @return [Twitter::Tweet] The created Tweet. When the tweet is deemed a duplicate by Twitter, returns the last Tweet from the user's timeline.
115
- # @param status [String] The text of your status update, up to 140 characters.
114
+ # @param status [String] The text of your status update, up to 280 characters.
116
115
  # @param options [Hash] A customizable set of options.
117
116
  # @option options [Boolean, String, Integer] :possibly_sensitive Set to true for content which may not be suitable for every audience.
118
117
  # @option options [Twitter::Tweet] :in_reply_to_status An existing status that the update is in reply to. If the status being replied to was not originally posted by the authenticated user, the text of the status must begin with an @-mention, or twitter will reject the update.
@@ -121,7 +120,6 @@ module Twitter
121
120
  # @option options [Float] :long The longitude of the location this tweet refers to. The valid ranges for longitude is -180.0 to +180.0 (East is positive) inclusive. This option will be ignored if outside that range, if it is not a number, if geo_enabled is disabled, or if there not a corresponding :lat option.
122
121
  # @option options [Twitter::Place] :place A place in the world. These can be retrieved from {Twitter::REST::PlacesAndGeo#reverse_geocode}.
123
122
  # @option options [String] :place_id A place in the world. These IDs can be retrieved from {Twitter::REST::PlacesAndGeo#reverse_geocode}.
124
- # @option options [String] :media_ids A comma separated list of uploaded media IDs to attach to the Tweet.
125
123
  # @option options [String] :display_coordinates Whether or not to put a pin on the exact coordinates a tweet has been sent from.
126
124
  # @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.
127
125
  def update(status, options = {})
@@ -139,7 +137,7 @@ module Twitter
139
137
  # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
140
138
  # @raise [Twitter::Error::DuplicateStatus] Error raised when a duplicate status is posted.
141
139
  # @return [Twitter::Tweet] The created Tweet.
142
- # @param status [String] The text of your status update, up to 140 characters.
140
+ # @param status [String] The text of your status update, up to 280 characters.
143
141
  # @param options [Hash] A customizable set of options.
144
142
  # @option options [Boolean, String, Integer] :possibly_sensitive Set to true for content which may not be suitable for every audience.
145
143
  # @option options [Twitter::Tweet] :in_reply_to_status An existing status that the update is in reply to. If the status being replied to was not originally posted by the authenticated user, the text of the status must begin with an @-mention, or twitter will reject the update.
@@ -148,7 +146,6 @@ module Twitter
148
146
  # @option options [Float] :long The longitude of the location this tweet refers to. The valid ranges for longitude is -180.0 to +180.0 (East is positive) inclusive. This option will be ignored if outside that range, if it is not a number, if geo_enabled is disabled, or if there not a corresponding :lat option.
149
147
  # @option options [Twitter::Place] :place A place in the world. These can be retrieved from {Twitter::REST::PlacesAndGeo#reverse_geocode}.
150
148
  # @option options [String] :place_id A place in the world. These IDs can be retrieved from {Twitter::REST::PlacesAndGeo#reverse_geocode}.
151
- # @option options [String] :media_ids A comma separated list of uploaded media IDs to attach to the Tweet.
152
149
  # @option options [String] :display_coordinates Whether or not to put a pin on the exact coordinates a tweet has been sent from.
153
150
  # @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.
154
151
  def update!(status, options = {})
@@ -211,10 +208,9 @@ module Twitter
211
208
  # @rate_limited No
212
209
  # @authentication Requires user context
213
210
  # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
214
- # @raise [Twitter::Error::UnacceptableIO] Error when the IO object for the media argument does not have a to_io method.
215
211
  # @return [Twitter::Tweet] The created Tweet.
216
- # @param status [String] The text of your status update, up to 140 characters.
217
- # @param media [File, Hash] A File object with your picture (PNG, JPEG or GIF)
212
+ # @param status [String] The text of your status update, up to 280 characters.
213
+ # @param media [File, Array<File>] An image file or array of image files (PNG, JPEG or GIF).
218
214
  # @param options [Hash] A customizable set of options.
219
215
  # @option options [Boolean, String, Integer] :possibly_sensitive Set to true for content which may not be suitable for every audience.
220
216
  # @option options [Twitter::Tweet] :in_reply_to_status An existing status that the update is in reply to.
@@ -226,11 +222,11 @@ module Twitter
226
222
  # @option options [String] :display_coordinates Whether or not to put a pin on the exact coordinates a tweet has been sent from.
227
223
  # @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.
228
224
  def update_with_media(status, media, options = {})
229
- raise(Twitter::Error::UnacceptableIO.new) unless media.respond_to?(:to_io)
230
- hash = options.dup
231
- hash[:in_reply_to_status_id] = hash.delete(:in_reply_to_status).id unless hash[:in_reply_to_status].nil?
232
- hash[:place_id] = hash.delete(:place).woeid unless hash[:place].nil?
233
- perform_post_with_object('/1.1/statuses/update_with_media.json', hash.merge('media[]' => media, 'status' => status), Twitter::Tweet)
225
+ options = options.dup
226
+ media_ids = pmap(array_wrap(media)) do |medium|
227
+ upload(medium)[:media_id]
228
+ end
229
+ update!(status, options.merge(media_ids: media_ids.join(',')))
234
230
  end
235
231
 
236
232
  # Returns oEmbed for a Tweet
@@ -252,6 +248,7 @@ module Twitter
252
248
  # @option options [String] :widget_type Set to video to return a Twitter Video embed for the given Tweet.
253
249
  # @option options [Boolean, String] :hide_tweet Applies to video type only. Set to 1 or true to link directly to the Tweet URL instead of displaying a Tweet overlay when a viewer clicks on the Twitter bird logo.
254
250
  def oembed(tweet, options = {})
251
+ options = options.dup
255
252
  options[:id] = extract_id(tweet)
256
253
  perform_get_with_object('/1.1/statuses/oembed.json', options, Twitter::OEmbed)
257
254
  end
@@ -300,12 +297,80 @@ module Twitter
300
297
  perform_get_with_cursor('/1.1/statuses/retweeters/ids.json', arguments.options, :ids)
301
298
  end
302
299
 
300
+ # Untweets a retweeted status as the authenticating user
301
+ #
302
+ # @see https://dev.twitter.com/rest/reference/post/statuses/unretweet/:id
303
+ # @rate_limited Yes
304
+ # @authentication Requires user context
305
+ # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
306
+ # @return [Array<Twitter::Tweet>] The original tweets with retweet details embedded.
307
+ # @overload unretweet(*tweets)
308
+ # @param tweets [Enumerable<Integer, String, URI, Twitter::Tweet>] A collection of Tweet IDs, URIs, or objects.
309
+ # @overload unretweet(*tweets, options)
310
+ # @param tweets [Enumerable<Integer, String, URI, Twitter::Tweet>] A collection of Tweet IDs, URIs, or objects.
311
+ # @param options [Hash] A customizable set of options.
312
+ # @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.
313
+ def unretweet(*args)
314
+ arguments = Twitter::Arguments.new(args)
315
+ pmap(arguments) do |tweet|
316
+ begin
317
+ post_unretweet(extract_id(tweet), arguments.options)
318
+ rescue Twitter::Error::NotFound
319
+ next
320
+ end
321
+ end.compact
322
+ end
323
+
303
324
  private
304
325
 
326
+ # Uploads images and videos. Videos require multiple requests and uploads in chunks of 5 Megabytes.
327
+ # The only supported video format is mp4.
328
+ #
329
+ # @see https://dev.twitter.com/rest/public/uploading-media
330
+ def upload(media) # rubocop:disable MethodLength, AbcSize
331
+ if File.basename(media) !~ /\.mp4$/
332
+ Twitter::REST::Request.new(self, :multipart_post, 'https://upload.twitter.com/1.1/media/upload.json', key: :media, file: media).perform
333
+ else
334
+ init = Twitter::REST::Request.new(self, :post, 'https://upload.twitter.com/1.1/media/upload.json',
335
+ command: 'INIT',
336
+ media_type: 'video/mp4',
337
+ total_bytes: media.size).perform
338
+
339
+ until media.eof?
340
+ chunk = media.read(5_000_000)
341
+ seg ||= -1
342
+ Twitter::REST::Request.new(self, :multipart_post, 'https://upload.twitter.com/1.1/media/upload.json',
343
+ command: 'APPEND',
344
+ media_id: init[:media_id],
345
+ segment_index: seg += 1,
346
+ key: :media,
347
+ file: StringIO.new(chunk)).perform
348
+ end
349
+
350
+ media.close
351
+
352
+ Twitter::REST::Request.new(self, :post, 'https://upload.twitter.com/1.1/media/upload.json',
353
+ command: 'FINALIZE', media_id: init[:media_id]).perform
354
+ end
355
+ end
356
+
357
+ def array_wrap(object)
358
+ if object.respond_to?(:to_ary)
359
+ object.to_ary || [object]
360
+ else
361
+ [object]
362
+ end
363
+ end
364
+
305
365
  def post_retweet(tweet, options)
306
366
  response = perform_post("/1.1/statuses/retweet/#{extract_id(tweet)}.json", options)
307
367
  Twitter::Tweet.new(response)
308
368
  end
369
+
370
+ def post_unretweet(tweet, options)
371
+ response = perform_post("/1.1/statuses/unretweet/#{extract_id(tweet)}.json", options)
372
+ Twitter::Tweet.new(response)
373
+ end
309
374
  end
310
375
  end
311
376
  end
@@ -33,11 +33,10 @@ module Twitter
33
33
  # @rate_limited No
34
34
  # @authentication Not required
35
35
  # @return [Integer]
36
- # @param uri [String, URI] A URI.
36
+ # @param url [String, URI] A URL.
37
37
  # @param options [Hash] A customizable set of options.
38
- def tweet_count(uri, options = {})
39
- connection = Faraday.new('https://cdn.api.twitter.com', connection_options)
40
- connection.get('/1/urls/count.json', options.merge(url: uri.to_s)).body[:count]
38
+ def tweet_count(url, options = {})
39
+ HTTP.get('https://cdn.api.twitter.com/1/urls/count.json', params: options.merge(url: url.to_s)).parse['count']
41
40
  end
42
41
  end
43
42
  end
@@ -30,11 +30,13 @@ module Twitter
30
30
  # @option options [Integer] :end_sleep_time The hour that sleep time should end if it is enabled. The value for this parameter should be provided in {http://en.wikipedia.org/wiki/ISO_8601 ISO8601} format (i.e. 00-23). The time is considered to be in the same timezone as the user's time_zone setting.
31
31
  # @option options [String] :time_zone The timezone dates and times should be displayed in for the user. The timezone must be one of the {http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html Rails TimeZone} names.
32
32
  # @option options [String] :lang The language which Twitter should render in for this user. The language must be specified by the appropriate two letter ISO 639-1 representation. Currently supported languages are provided by {https://dev.twitter.com/rest/reference/get/help/languages GET help/languages}.
33
+ # @option options [String] :allow_contributor_request Whether to allow others to include user as contributor. Possible values include 'all' (anyone can include user), 'following' (only followers can include user) or 'none'. Also note that changes to this field require the request also include a current_password value with the user's password to successfully modify this field.
34
+ # @option options [String] :current_password The user's password. This is only required when modifying the allow_contributor_request field.
33
35
  def settings(options = {})
34
36
  request_method = options.size.zero? ? :get : :post
35
37
  response = perform_request(request_method.to_sym, '/1.1/account/settings.json', options)
36
38
  # https://dev.twitter.com/issues/59
37
- response.update(trend_location: response.fetch(:trend_location, []).first)
39
+ response[:trend_location] = response.fetch(:trend_location, []).first
38
40
  Twitter::Settings.new(response)
39
41
  end
40
42
 
@@ -50,7 +52,6 @@ module Twitter
50
52
  def verify_credentials(options = {})
51
53
  perform_get_with_object('/1.1/account/verify_credentials.json', options, Twitter::User)
52
54
  end
53
- alias current_user verify_credentials
54
55
 
55
56
  # Sets which device Twitter delivers updates to for the authenticating user
56
57
  #
@@ -78,6 +79,7 @@ module Twitter
78
79
  # @option options [String] :url URL associated with the profile. Will be prepended with "http://" if not present. Maximum of 100 characters.
79
80
  # @option options [String] :location The city or country describing where the user of the account is located. The contents are not normalized or geocoded in any way. Maximum of 30 characters.
80
81
  # @option options [String] :description A description of the user owning the account. Maximum of 160 characters.
82
+ # @option options [String] :profile_link_color A hex value of the color scheme used for links on user's profile page. Must be a valid hexadecimal value, and may be either three or six characters
81
83
  def update_profile(options = {})
82
84
  perform_post_with_object('/1.1/account/update_profile.json', options, Twitter::User)
83
85
  end
@@ -93,24 +95,7 @@ module Twitter
93
95
  # @param options [Hash] A customizable set of options.
94
96
  # @option options [Boolean] :tile Whether or not to tile the background image. If set to true the background image will be displayed tiled. The image will not be tiled otherwise.
95
97
  def update_profile_background_image(image, options = {})
96
- perform_post_with_object('/1.1/account/update_profile_background_image.json', options.merge(image: image), Twitter::User)
97
- end
98
-
99
- # Sets one or more hex values that control the color scheme of the authenticating user's profile
100
- #
101
- # @see https://dev.twitter.com/rest/reference/post/account/update_profile_colors
102
- # @rate_limited No
103
- # @authentication Requires user context
104
- # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
105
- # @return [Twitter::User] The authenticated user.
106
- # @param options [Hash] A customizable set of options.
107
- # @option options [String] :profile_background_color Profile background color.
108
- # @option options [String] :profile_text_color Profile text color.
109
- # @option options [String] :profile_link_color Profile link color.
110
- # @option options [String] :profile_sidebar_fill_color Profile sidebar's background color.
111
- # @option options [String] :profile_sidebar_border_color Profile sidebar's border color.
112
- def update_profile_colors(options = {})
113
- perform_post_with_object('/1.1/account/update_profile_colors.json', options, Twitter::User)
98
+ post_profile_image('/1.1/account/update_profile_background_image.json', image, options)
114
99
  end
115
100
 
116
101
  # Updates the authenticating user's profile image
@@ -125,7 +110,7 @@ module Twitter
125
110
  # @param image [File] The avatar image for the profile, base64-encoded. Must be a valid GIF, JPG, or PNG image of less than 700 kilobytes in size. Images with width larger than 500 pixels will be scaled down. Animated GIFs will be converted to a static GIF of the first frame, removing the animation.
126
111
  # @param options [Hash] A customizable set of options.
127
112
  def update_profile_image(image, options = {})
128
- perform_post_with_object('/1.1/account/update_profile_image.json', options.merge(image: image), Twitter::User)
113
+ post_profile_image('/1.1/account/update_profile_image.json', image, options)
129
114
  end
130
115
 
131
116
  # Returns an array of user objects that the authenticating user is blocking
@@ -140,7 +125,6 @@ module Twitter
140
125
  def blocked(options = {})
141
126
  perform_get_with_cursor('/1.1/blocks/list.json', options, :users, Twitter::User)
142
127
  end
143
- deprecate_alias :blocking, :blocked
144
128
 
145
129
  # Returns an array of numeric user IDs the authenticating user is blocking
146
130
  #
@@ -167,17 +151,12 @@ module Twitter
167
151
  # @param user [Integer, String, URI, Twitter::User] A Twitter user ID, screen name, URI, or object.
168
152
  # @param options [Hash] A customizable set of options.
169
153
  def block?(user, options = {})
170
- user_id = begin
154
+ user_id =
171
155
  case user
172
- when Integer
173
- user
174
- when String, URI, Addressable::URI
175
- user(user).id
176
- when Twitter::User
177
- user.id
156
+ when Integer then user
157
+ when String, URI, Addressable::URI then user(user).id
158
+ when Twitter::User then user.id
178
159
  end
179
- end
180
-
181
160
  blocked_ids(options).collect(&:to_i).include?(user_id)
182
161
  end
183
162
 
@@ -229,7 +208,7 @@ module Twitter
229
208
  def users(*args)
230
209
  arguments = Twitter::Arguments.new(args)
231
210
  flat_pmap(arguments.each_slice(MAX_USERS_PER_REQUEST)) do |users|
232
- perform_post_with_objects('/1.1/users/lookup.json', merge_users(arguments.options, users), Twitter::User)
211
+ perform_get_with_objects('/1.1/users/lookup.json', merge_users(arguments.options, users), Twitter::User)
233
212
  end
234
213
  end
235
214
 
@@ -267,6 +246,7 @@ module Twitter
267
246
  # @return [Boolean] true if the user exists, otherwise false.
268
247
  # @param user [Integer, String, Twitter::User] A Twitter user ID, screen name, URI, or object.
269
248
  def user?(user, options = {})
249
+ options = options.dup
270
250
  merge_user!(options, user)
271
251
  perform_get('/1.1/users/show.json', options)
272
252
  true
@@ -286,6 +266,7 @@ module Twitter
286
266
  # @option options [Integer] :count The number of people to retrieve. Maxiumum of 20 allowed per page.
287
267
  # @option options [Integer] :page Specifies the page of results to retrieve.
288
268
  def user_search(query, options = {})
269
+ options = options.dup
289
270
  perform_get_with_objects('/1.1/users/search.json', options.merge(q: query), Twitter::User)
290
271
  end
291
272
 
@@ -337,7 +318,6 @@ module Twitter
337
318
  perform_post('/1.1/account/remove_profile_banner.json', options)
338
319
  true
339
320
  end
340
- deprecate_alias :profile_banner_remove, :remove_profile_banner
341
321
 
342
322
  # Updates the authenticating user's profile banner image
343
323
  #
@@ -422,7 +402,6 @@ module Twitter
422
402
  def muted(options = {})
423
403
  perform_get_with_cursor('/1.1/mutes/users/list.json', options, :users, Twitter::User)
424
404
  end
425
- deprecate_alias :muting, :muted
426
405
 
427
406
  # Returns an array of numeric user IDs the authenticating user is muting
428
407
  #
@@ -438,6 +417,13 @@ module Twitter
438
417
  merge_user!(arguments.options, arguments.pop)
439
418
  perform_get_with_cursor('/1.1/mutes/users/ids.json', arguments.options, :ids)
440
419
  end
420
+
421
+ private
422
+
423
+ def post_profile_image(path, image, options)
424
+ response = Twitter::REST::Request.new(self, :multipart_post, path, options.merge(key: :image, file: image)).perform
425
+ Twitter::User.new(response)
426
+ end
441
427
  end
442
428
  end
443
429
  end