twitter 6.2.0 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -7
  3. data/LICENSE.md +1 -1
  4. data/README.md +9 -12
  5. data/lib/twitter.rb +5 -0
  6. data/lib/twitter/client.rb +5 -5
  7. data/lib/twitter/creatable.rb +5 -1
  8. data/lib/twitter/cursor.rb +12 -2
  9. data/lib/twitter/direct_message.rb +2 -0
  10. data/lib/twitter/direct_message_event.rb +44 -0
  11. data/lib/twitter/direct_messages/welcome_message.rb +17 -0
  12. data/lib/twitter/direct_messages/welcome_message_rule.rb +12 -0
  13. data/lib/twitter/direct_messages/welcome_message_rule_wrapper.rb +36 -0
  14. data/lib/twitter/direct_messages/welcome_message_wrapper.rb +42 -0
  15. data/lib/twitter/enumerable.rb +14 -3
  16. data/lib/twitter/error.rb +48 -6
  17. data/lib/twitter/null_object.rb +15 -1
  18. data/lib/twitter/premium_search_results.rb +67 -0
  19. data/lib/twitter/profile.rb +2 -2
  20. data/lib/twitter/rate_limit.rb +2 -2
  21. data/lib/twitter/rest/account_activity.rb +99 -0
  22. data/lib/twitter/rest/api.rb +6 -0
  23. data/lib/twitter/rest/direct_messages.rb +131 -42
  24. data/lib/twitter/rest/direct_messages/welcome_messages.rb +90 -0
  25. data/lib/twitter/rest/favorites.rb +2 -2
  26. data/lib/twitter/rest/lists.rb +1 -0
  27. data/lib/twitter/rest/premium_search.rb +34 -0
  28. data/lib/twitter/rest/request.rb +39 -13
  29. data/lib/twitter/rest/search.rb +4 -3
  30. data/lib/twitter/rest/timelines.rb +1 -0
  31. data/lib/twitter/rest/tweets.rb +2 -31
  32. data/lib/twitter/rest/upload_utils.rb +68 -0
  33. data/lib/twitter/rest/utils.rb +24 -7
  34. data/lib/twitter/search_results.rb +4 -3
  35. data/lib/twitter/streaming/client.rb +5 -1
  36. data/lib/twitter/streaming/connection.rb +16 -3
  37. data/lib/twitter/streaming/message_parser.rb +1 -1
  38. data/lib/twitter/streaming/response.rb +1 -0
  39. data/lib/twitter/tweet.rb +10 -1
  40. data/lib/twitter/utils.rb +4 -2
  41. data/lib/twitter/version.rb +2 -2
  42. data/twitter.gemspec +3 -4
  43. metadata +16 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c1797367fcb91dca015c7a77acd6273beb4c49e929c98d2d3a913ea37009496
4
- data.tar.gz: 3c4a9f1fca5d3e99b9be0cb8993c4f274cb309b8fc19b2f3cf45838622484bce
3
+ metadata.gz: 578178613b24f694731c9b87c940488762c35a0f4027b57bbd518bd9f914469c
4
+ data.tar.gz: 4ad56cc9e3c49d60cdc9f60777f37070cd6d933cd53bb2b2a9e82fe6f6f5f193
5
5
  SHA512:
6
- metadata.gz: 887f6a6acfb58cd602fe1507c66e12fcb53c5b7479054a91e0ca68ee0c2a227c620b8bab614d256e4dfb31015cdc5c85fe8bdf9f05e9f48b8c38c8d945fbbf1e
7
- data.tar.gz: 631417a20ae3bca7970e05f6a63c6049af3c613b0f078a6d178d81f13750ff4a885514aa882be050a94f3909dc24df8df084fbc816bec280a9e7963fb7ab3750
6
+ metadata.gz: e9e85b61e8f806fda08720a1b3290370bf1824bd5afba0f2afce2e3d29956dafaa60ae500299349863e320074d4c8944046dd98b065d7f9900c7eb4e896fa05f
7
+ data.tar.gz: a10adbd38f44ba009ca21230a3a439f3b246bc84779aa9f80161643efb36e6abebeeb0d648257d1a29ccb1a65b06de445eac523aff36137e045cb40beae0246c
@@ -1,25 +1,37 @@
1
- 6.2.0
1
+ 7.0.0
2
2
  ------
3
+ * [Add `Twitter::DirectMessageEvent`](https://github.com/sferik/twitter/commit/38f6aaa482dcd5f4982abd811dbe6e21e36c2ae8) ([@FabienChaynes](https://twitter.com/FabienChaynes))
4
+ * [Create `Twitter::DirectMessageEvent` with media](https://github.com/sferik/twitter/commit/21478530ec6f8a798717a5ab8b197b895db3bc28) ([@FabienChaynes](https://twitter.com/FabienChaynes))
5
+ * [Support for DM welcome messages](https://github.com/sferik/twitter/pull/950) ([@FabienChaynes](https://twitter.com/FabienChaynes))
6
+ * [Support for closing `Twitter::Streaming::Connection`](https://github.com/sferik/twitter/commit/89e3543aa06e00eeab7eaf5bdd3a33a6112356b1) ([@okkez](https://twitter.com/okkez))
7
+ * [Add `Twitter::REST::Client#create_direct_message_event`](https://github.com/sferik/twitter/commit/b45d545c7ebfd28e4d908037dd3fde04e3c307cf) ([@cyu](https://twitter.com/cyu))
8
+ * [Add `Twitter::REST::Client#premium_search`](https://github.com/sferik/twitter/pull/953)
9
+ * [Add `Twitter::REST::AccountActivity`](https://github.com/sferik/twitter/pull/939)
10
+ * [Update all direct message methods to return `Twitter::DirectMessageEvent`](https://github.com/sferik/twitter/commit/0833471366a33657cd2920850e3928db010eecab) ([@flikglick](https://twitter.com/flikglick))
11
+ * [Correctly handle different `Twitter::Error::AlreadyRetweeted` error messages](https://github.com/sferik/twitter/commit/c9bf100eedc89aee43689c17f160025e0f40cfb4) ([@knu](https://twitter.com/knu))
12
+ * [Fix proxy setting sample](https://github.com/sferik/twitter/commit/91c037cfb26ac0c9d3099cdeec42d65fe8716b78) ([@nicklegr](https://twitter.com/nicklegr))
13
+ * [Add Active Support `presence` methods on `Twitter::NullObject`](https://github.com/sferik/twitter/commit/07a5d7b60f335aefd583dae85ba959235bc9f55f) ([@davebrace](https://twitter.com/davebrace))
14
+ * [Upload GIFs over 5MB in chunks](https://github.com/sferik/twitter/commit/ba6a3062782b37cf83b9813c5128c87d4971ab9c) ([@wild_dmitry](https://twitter.com/wild_dmitry))
15
+ * [Track rate limit when searching tweets](https://github.com/sferik/twitter/commit/067e751d58b7bb0bfbe8a5531a4288f4c966b301) ([@dsalahutdinov1](https://twitter.com/dsalahutdinov1))
16
+ * [Add `quote_count` and `reply_count` attributes to `Twitter::Tweet`](https://github.com/sferik/twitter/commit/844818cad07ce490ccb9d8542ebb6b4fc7a61cb4)
17
+ * [Drop support for Ruby 2.0, 2.1, and 2.2](https://github.com/sferik/twitter/commit/95861ec83e582c2a88499b97d9d5388a96d0abf0)
3
18
 
19
+ 6.2.0
20
+ ------
4
21
  Not yet documented, sorry. For now, please use git to compare tags:
5
22
  https://github.com/sferik/twitter/compare/v6.1.0...v6.2.0
6
23
 
7
24
  6.1.0
8
25
  ------
9
-
10
26
  Not yet documented, sorry. For now, please use git to compare tags:
11
27
  https://github.com/sferik/twitter/compare/v6.0.0...v6.1.0
12
28
 
13
-
14
29
  6.0.0
15
30
  ------
16
-
17
- Not yet documented, sorry. For now, please use git to compare tags:
18
- https://github.com/sferik/twitter/compare/v5.16.0...v6.0.0
31
+ * [Drop support for Ruby 1.8.7 and Ruby 1.9.3](https://github.com/sferik/twitter/commit/27980f45fb357e34b86e46cb9134d86ed29b3ce3)
19
32
 
20
33
  5.16.0
21
34
  ------
22
-
23
35
  * [Add Twitter::Trend#tweet_volume](https://github.com/sferik/twitter/commit/e797b62e5e6a768e8aeafde6186e1f5310e6bfc6)
24
36
  * [Add new settings to Twitter::Settings](https://github.com/sferik/twitter/commit/d047ce00034d26a99927076c28679ce08fd69308)
25
37
  * [Fix `Version.to_a`](https://github.com/sferik/twitter/commit/0cd119abf64e6c2b7fd861b0df65b7cb41d892b4)
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2006-2016 Erik Michaels-Ober, John Nunemaker, Wynn Netherland, Steve Richert, Steve Agalloco
1
+ Copyright (c) 2006-2020 Erik Berlin, John Nunemaker, Wynn Netherland, Steve Richert, Steve Agalloco
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,16 +1,14 @@
1
1
  # The Twitter Ruby Gem
2
2
 
3
- [![Gem Version](http://img.shields.io/gem/v/twitter.svg)][gem]
4
- [![Build Status](http://img.shields.io/travis/sferik/twitter.svg)][travis]
5
- [![Dependency Status](http://img.shields.io/gemnasium/sferik/twitter.svg)][gemnasium]
6
- [![Code Climate](http://img.shields.io/codeclimate/github/sferik/twitter.svg)][codeclimate]
7
- [![Coverage Status](http://img.shields.io/coveralls/sferik/twitter.svg)][coveralls]
3
+ [![Gem Version](https://badge.fury.io/rb/twitter.svg)][gem]
4
+ [![Build Status](https://travis-ci.org/sferik/twitter.svg?branch=master)][travis]
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/09362621ad91e8f599b3/maintainability)][maintainability]
6
+ [![Coverage Status](https://coveralls.io/repos/github/sferik/twitter/badge.svg?branch=master)][coveralls]
8
7
  [![Inline docs](http://inch-ci.org/github/sferik/twitter.svg?style=shields)][inchpages]
9
8
 
10
9
  [gem]: https://rubygems.org/gems/twitter
11
10
  [travis]: https://travis-ci.org/sferik/twitter
12
- [gemnasium]: https://gemnasium.com/sferik/twitter
13
- [codeclimate]: https://codeclimate.com/github/sferik/twitter
11
+ [maintainability]: https://codeclimate.com/github/sferik/twitter/maintainability
14
12
  [coveralls]: https://coveralls.io/r/sferik/twitter
15
13
  [inchpages]: http://inch-ci.org/github/sferik/twitter
16
14
 
@@ -231,11 +229,10 @@ command:
231
229
  This library aims to support and is [tested against][travis] the following Ruby
232
230
  versions:
233
231
 
234
- * Ruby 2.0.0
235
- * Ruby 2.1
236
- * Ruby 2.2
237
- * Ruby 2.3
238
- * JRuby 9.1.6.0
232
+ * Ruby 2.4
233
+ * Ruby 2.5
234
+ * Ruby 2.6
235
+ * Ruby 2.7
239
236
 
240
237
  If something doesn't work on one of these versions, it's a bug.
241
238
 
@@ -20,6 +20,7 @@ require 'twitter/relationship'
20
20
  require 'twitter/rest/client'
21
21
  require 'twitter/saved_search'
22
22
  require 'twitter/search_results'
23
+ require 'twitter/premium_search_results'
23
24
  require 'twitter/settings'
24
25
  require 'twitter/size'
25
26
  require 'twitter/source_user'
@@ -29,3 +30,7 @@ require 'twitter/target_user'
29
30
  require 'twitter/trend'
30
31
  require 'twitter/tweet'
31
32
  require 'twitter/user'
33
+ require 'twitter/direct_messages/welcome_message'
34
+ require 'twitter/direct_messages/welcome_message_rule'
35
+ require 'twitter/direct_messages/welcome_message_rule_wrapper'
36
+ require 'twitter/direct_messages/welcome_message_wrapper'
@@ -5,7 +5,7 @@ require 'twitter/version'
5
5
  module Twitter
6
6
  class Client
7
7
  include Twitter::Utils
8
- attr_accessor :access_token, :access_token_secret, :consumer_key, :consumer_secret, :proxy, :timeouts
8
+ attr_accessor :access_token, :access_token_secret, :consumer_key, :consumer_secret, :proxy, :timeouts, :dev_environment
9
9
  attr_writer :user_agent
10
10
 
11
11
  # Initializes a new Client object
@@ -21,7 +21,7 @@ module Twitter
21
21
 
22
22
  # @return [Boolean]
23
23
  def user_token?
24
- !(blank?(access_token) || blank?(access_token_secret))
24
+ !(blank_string?(access_token) || blank_string?(access_token_secret))
25
25
  end
26
26
 
27
27
  # @return [String]
@@ -41,13 +41,13 @@ module Twitter
41
41
 
42
42
  # @return [Boolean]
43
43
  def credentials?
44
- credentials.values.none? { |v| blank?(v) }
44
+ credentials.values.none? { |v| blank_string?(v) }
45
45
  end
46
46
 
47
47
  private
48
48
 
49
- def blank?(s)
50
- s.respond_to?(:empty?) ? s.empty? : !s
49
+ def blank_string?(string)
50
+ string.respond_to?(:empty?) ? string.empty? : !string
51
51
  end
52
52
  end
53
53
  end
@@ -9,7 +9,11 @@ module Twitter
9
9
  #
10
10
  # @return [Time]
11
11
  def created_at
12
- Time.parse(@attrs[:created_at]).utc unless @attrs[:created_at].nil?
12
+ time = @attrs[:created_at]
13
+ return if time.nil?
14
+
15
+ time = Time.parse(time) unless time.is_a?(Time)
16
+ time.utc
13
17
  end
14
18
  memoize :created_at
15
19
 
@@ -16,8 +16,9 @@ module Twitter
16
16
  # @param key [String, Symbol] The key to fetch the data from the response
17
17
  # @param klass [Class] The class to instantiate objects in the response
18
18
  # @param request [Twitter::REST::Request]
19
+ # @param limit [Integer] After reaching the limit, we stop fetching next page
19
20
  # @return [Twitter::Cursor]
20
- def initialize(key, klass, request)
21
+ def initialize(key, klass, request, limit = nil)
21
22
  @key = key.to_sym
22
23
  @klass = klass
23
24
  @client = request.client
@@ -25,6 +26,7 @@ module Twitter
25
26
  @path = request.path
26
27
  @options = request.options
27
28
  @collection = []
29
+ @limit = limit
28
30
  self.attrs = request.perform
29
31
  end
30
32
 
@@ -32,15 +34,23 @@ module Twitter
32
34
 
33
35
  # @return [Integer]
34
36
  def next_cursor
35
- @attrs[:next_cursor] || -1
37
+ @attrs[:next_cursor]
36
38
  end
37
39
  alias next next_cursor
38
40
 
39
41
  # @return [Boolean]
40
42
  def last?
43
+ return false if next_cursor.is_a?(String)
44
+ return true if next_cursor.nil?
45
+
41
46
  next_cursor.zero?
42
47
  end
43
48
 
49
+ # @return [Boolean]
50
+ def reached_limit?
51
+ @limit && @limit <= attrs[@key].count
52
+ end
53
+
44
54
  # @return [Hash]
45
55
  def fetch_next_page
46
56
  response = Twitter::REST::Request.new(@client, @request_method, @path, @options.merge(cursor: next_cursor)).perform
@@ -8,6 +8,8 @@ module Twitter
8
8
  include Twitter::Entities
9
9
  # @return [String]
10
10
  attr_reader :text
11
+ attr_reader :sender_id
12
+ attr_reader :recipient_id
11
13
  alias full_text text
12
14
  object_attr_reader :User, :recipient
13
15
  object_attr_reader :User, :sender
@@ -0,0 +1,44 @@
1
+ require 'twitter/creatable'
2
+ require 'twitter/entities'
3
+ require 'twitter/identity'
4
+
5
+ module Twitter
6
+ class DirectMessageEvent < Twitter::Identity
7
+ include Twitter::Creatable
8
+ include Twitter::Entities
9
+
10
+ attr_reader :created_timestamp
11
+
12
+ object_attr_reader :DirectMessage, :direct_message
13
+
14
+ def initialize(attrs)
15
+ attrs = read_from_response(attrs)
16
+ text = attrs.dig(:message_create, :message_data, :text)
17
+ urls = attrs.dig(:message_create, :message_data, :entities, :urls)
18
+
19
+ text.gsub!(urls[0][:url], urls[0][:expanded_url]) if urls.any?
20
+
21
+ attrs[:direct_message] = build_direct_message(attrs, text)
22
+ super
23
+ end
24
+
25
+ private
26
+
27
+ # @return [Hash] Normalized hash of attrs
28
+ def read_from_response(attrs)
29
+ attrs[:event].nil? ? attrs : attrs[:event]
30
+ end
31
+
32
+ def build_direct_message(attrs, text)
33
+ recipient_id = attrs[:message_create][:target][:recipient_id].to_i
34
+ sender_id = attrs[:message_create][:sender_id].to_i
35
+ {id: attrs[:id].to_i,
36
+ created_at: Time.at(attrs[:created_timestamp].to_i / 1000.0),
37
+ sender: {id: sender_id},
38
+ sender_id: sender_id,
39
+ recipient: {id: recipient_id},
40
+ recipient_id: recipient_id,
41
+ text: text}
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,17 @@
1
+ require 'twitter/creatable'
2
+ require 'twitter/entities'
3
+ require 'twitter/identity'
4
+
5
+ module Twitter
6
+ module DirectMessages
7
+ class WelcomeMessage < Twitter::Identity
8
+ include Twitter::Creatable
9
+ include Twitter::Entities
10
+ # @return [String]
11
+ attr_reader :text
12
+ # @return [String]
13
+ attr_reader :name
14
+ alias full_text text
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ require 'twitter/creatable'
2
+ require 'twitter/identity'
3
+
4
+ module Twitter
5
+ module DirectMessages
6
+ class WelcomeMessageRule < Twitter::Identity
7
+ include Twitter::Creatable
8
+ # @return [Integer]
9
+ attr_reader :welcome_message_id
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,36 @@
1
+ require 'twitter/creatable'
2
+ require 'twitter/identity'
3
+
4
+ module Twitter
5
+ module DirectMessages
6
+ class WelcomeMessageRuleWrapper < Twitter::Identity
7
+ attr_reader :created_timestamp
8
+
9
+ object_attr_reader 'DirectMessages::WelcomeMessageRule', :welcome_message_rule
10
+
11
+ def initialize(attrs)
12
+ attrs = read_from_response(attrs)
13
+
14
+ attrs[:welcome_message_rule] = build_welcome_message_rule(attrs)
15
+ super
16
+ end
17
+
18
+ private
19
+
20
+ # @return [Hash] Normalized hash of attrs
21
+ def read_from_response(attrs)
22
+ return attrs[:welcome_message_rule] unless attrs[:welcome_message_rule].nil?
23
+
24
+ attrs
25
+ end
26
+
27
+ def build_welcome_message_rule(attrs)
28
+ {
29
+ id: attrs[:id].to_i,
30
+ created_at: Time.at(attrs[:created_timestamp].to_i / 1000.0),
31
+ welcome_message_id: attrs[:welcome_message_id].to_i,
32
+ }
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,42 @@
1
+ require 'twitter/creatable'
2
+ require 'twitter/identity'
3
+
4
+ module Twitter
5
+ module DirectMessages
6
+ class WelcomeMessageWrapper < Twitter::Identity
7
+ attr_reader :created_timestamp
8
+
9
+ object_attr_reader 'DirectMessages::WelcomeMessage', :welcome_message
10
+
11
+ def initialize(attrs)
12
+ attrs = read_from_response(attrs)
13
+ text = attrs.dig(:message_data, :text)
14
+ urls = attrs.dig(:message_data, :entities, :urls)
15
+
16
+ text.gsub!(urls[0][:url], urls[0][:expanded_url]) if urls.any?
17
+
18
+ attrs[:welcome_message] = build_welcome_message(attrs, text)
19
+ super
20
+ end
21
+
22
+ private
23
+
24
+ # @return [Hash] Normalized hash of attrs
25
+ def read_from_response(attrs)
26
+ return attrs[:welcome_message] unless attrs[:welcome_message].nil?
27
+
28
+ attrs
29
+ end
30
+
31
+ def build_welcome_message(attrs, text)
32
+ {
33
+ id: attrs[:id].to_i,
34
+ created_at: Time.at(attrs[:created_timestamp].to_i / 1000.0),
35
+ text: text,
36
+ name: attrs[:name],
37
+ entities: attrs.dig(:message_data, :entities),
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -3,15 +3,16 @@ module Twitter
3
3
  include ::Enumerable
4
4
 
5
5
  # @return [Enumerator]
6
- def each(start = 0)
6
+ def each(start = 0, &block)
7
7
  return to_enum(:each, start) unless block_given?
8
+
8
9
  Array(@collection[start..-1]).each do |element|
9
10
  yield(element)
10
11
  end
11
- unless last?
12
+ unless finished?
12
13
  start = [@collection.size, start].max
13
14
  fetch_next_page
14
- each(start, &Proc.new)
15
+ each(start, &block)
15
16
  end
16
17
  self
17
18
  end
@@ -22,5 +23,15 @@ module Twitter
22
23
  def last?
23
24
  true
24
25
  end
26
+
27
+ # @return [Boolean]
28
+ def reached_limit?
29
+ false
30
+ end
31
+
32
+ # @return [Boolean]
33
+ def finished?
34
+ last? || reached_limit?
35
+ end
25
36
  end
26
37
  end
@@ -59,6 +59,21 @@ module Twitter
59
59
  # Raised when Twitter returns the HTTP status code 504
60
60
  GatewayTimeout = Class.new(ServerError)
61
61
 
62
+ # Raised when Twitter returns a media related error
63
+ MediaError = Class.new(self)
64
+
65
+ # Raised when Twitter returns an InvalidMedia error
66
+ InvalidMedia = Class.new(MediaError)
67
+
68
+ # Raised when Twitter returns a media InternalError error
69
+ MediaInternalError = Class.new(MediaError)
70
+
71
+ # Raised when Twitter returns an UnsupportedMedia error
72
+ UnsupportedMedia = Class.new(MediaError)
73
+
74
+ # Raised when an operation subject to timeout takes too long
75
+ TimeoutError = Class.new(self)
76
+
62
77
  ERRORS = {
63
78
  400 => Twitter::Error::BadRequest,
64
79
  401 => Twitter::Error::Unauthorized,
@@ -74,14 +89,29 @@ module Twitter
74
89
  504 => Twitter::Error::GatewayTimeout,
75
90
  }.freeze
76
91
 
77
- FORBIDDEN_MESSAGES = {
78
- 'Status is a duplicate.' => Twitter::Error::DuplicateStatus,
79
- 'You have already favorited this status.' => Twitter::Error::AlreadyFavorited,
80
- 'You have already retweeted this tweet.' => Twitter::Error::AlreadyRetweeted,
81
- 'sharing is not permissible for this status (Share validations failed)' => Twitter::Error::AlreadyRetweeted,
92
+ FORBIDDEN_MESSAGES = proc do |message|
93
+ case message
94
+ when /(?=.*status).*duplicate/i
95
+ # - "Status is a duplicate."
96
+ Twitter::Error::DuplicateStatus
97
+ when /already favorited/i
98
+ # - "You have already favorited this status."
99
+ Twitter::Error::AlreadyFavorited
100
+ when /already retweeted|Share validations failed/i
101
+ # - "You have already retweeted this Tweet." (Nov 2017-)
102
+ # - "You have already retweeted this tweet." (?-Nov 2017)
103
+ # - "sharing is not permissible for this status (Share validations failed)" (-? 2017)
104
+ Twitter::Error::AlreadyRetweeted
105
+ end
106
+ end
107
+
108
+ MEDIA_ERRORS = {
109
+ 'InternalError' => Twitter::Error::MediaInternalError,
110
+ 'InvalidMedia' => Twitter::Error::InvalidMedia,
111
+ 'UnsupportedMedia' => Twitter::Error::UnsupportedMedia,
82
112
  }.freeze
83
113
 
84
- # If error code is missing see https://dev.twitter.com/overview/api/response-codes
114
+ # If error code is missing see https://developer.twitter.com/en/docs/basics/response-codes
85
115
  module Code
86
116
  AUTHENTICATION_PROBLEM = 32
87
117
  RESOURCE_NOT_FOUND = 34
@@ -122,6 +152,18 @@ module Twitter
122
152
  new(message, headers, code)
123
153
  end
124
154
 
155
+ # Create a new error from a media error hash
156
+ #
157
+ # @param error [Hash]
158
+ # @param headers [Hash]
159
+ # @return [Twitter::MediaError]
160
+ def from_processing_response(error, headers)
161
+ klass = MEDIA_ERRORS[error[:name]] || self
162
+ message = error[:message]
163
+ code = error[:code]
164
+ klass.new(message, headers, code)
165
+ end
166
+
125
167
  private
126
168
 
127
169
  def parse_error(body)