twitter 5.17.0 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +37 -10
- data/LICENSE.md +1 -1
- data/README.md +78 -407
- data/lib/twitter/base.rb +5 -19
- data/lib/twitter/basic_user.rb +0 -3
- data/lib/twitter/client.rb +9 -23
- data/lib/twitter/configuration.rb +4 -4
- data/lib/twitter/creatable.rb +5 -1
- data/lib/twitter/cursor.rb +13 -4
- data/lib/twitter/direct_message.rb +2 -0
- data/lib/twitter/direct_message_event.rb +44 -0
- data/lib/twitter/direct_messages/welcome_message.rb +17 -0
- data/lib/twitter/direct_messages/welcome_message_rule.rb +12 -0
- data/lib/twitter/direct_messages/welcome_message_rule_wrapper.rb +36 -0
- data/lib/twitter/direct_messages/welcome_message_wrapper.rb +42 -0
- data/lib/twitter/entity/uri.rb +0 -4
- data/lib/twitter/enumerable.rb +14 -3
- data/lib/twitter/error.rb +122 -95
- data/lib/twitter/geo_results.rb +0 -1
- data/lib/twitter/headers.rb +11 -15
- data/lib/twitter/media/photo.rb +5 -2
- data/lib/twitter/media/video.rb +5 -2
- data/lib/twitter/media/video_info.rb +1 -1
- data/lib/twitter/null_object.rb +20 -7
- data/lib/twitter/premium_search_results.rb +67 -0
- data/lib/twitter/profile.rb +5 -4
- data/lib/twitter/profile_banner.rb +1 -2
- data/lib/twitter/rate_limit.rb +3 -3
- data/lib/twitter/rest/account_activity.rb +99 -0
- data/lib/twitter/rest/api.rb +6 -2
- data/lib/twitter/rest/client.rb +0 -78
- data/lib/twitter/rest/direct_messages/welcome_messages.rb +90 -0
- data/lib/twitter/rest/direct_messages.rb +133 -44
- data/lib/twitter/rest/favorites.rb +29 -8
- data/lib/twitter/rest/friends_and_followers.rb +1 -3
- data/lib/twitter/rest/lists.rb +20 -30
- data/lib/twitter/rest/oauth.rb +15 -15
- data/lib/twitter/rest/premium_search.rb +34 -0
- data/lib/twitter/rest/request.rb +133 -18
- data/lib/twitter/rest/saved_searches.rb +1 -3
- data/lib/twitter/rest/search.rb +6 -3
- data/lib/twitter/rest/timelines.rb +1 -0
- data/lib/twitter/rest/trends.rb +1 -0
- data/lib/twitter/rest/tweets.rb +54 -18
- data/lib/twitter/rest/undocumented.rb +3 -4
- data/lib/twitter/rest/upload_utils.rb +68 -0
- data/lib/twitter/rest/users.rb +23 -37
- data/lib/twitter/rest/utils.rb +38 -28
- data/lib/twitter/search_results.rb +4 -4
- data/lib/twitter/streaming/client.rb +23 -25
- data/lib/twitter/streaming/connection.rb +37 -11
- data/lib/twitter/streaming/deleted_tweet.rb +0 -1
- data/lib/twitter/streaming/event.rb +6 -6
- data/lib/twitter/streaming/message_parser.rb +1 -1
- data/lib/twitter/streaming/response.rb +7 -3
- data/lib/twitter/trend_results.rb +1 -2
- data/lib/twitter/tweet.rb +11 -6
- data/lib/twitter/user.rb +2 -4
- data/lib/twitter/utils.rb +5 -18
- data/lib/twitter/version.rb +6 -6
- data/lib/twitter.rb +5 -0
- data/twitter.gemspec +10 -11
- metadata +31 -42
- data/lib/twitter/rest/media.rb +0 -30
- data/lib/twitter/rest/request/multipart_with_file.rb +0 -47
- data/lib/twitter/rest/response/parse_error_json.rb +0 -13
- data/lib/twitter/rest/response/parse_json.rb +0 -31
- data/lib/twitter/rest/response/raise_error.rb +0 -32
- data/lib/twitter/token.rb +0 -20
data/lib/twitter/error.rb
CHANGED
@@ -8,7 +8,110 @@ module Twitter
|
|
8
8
|
# @return [Twitter::RateLimit]
|
9
9
|
attr_reader :rate_limit
|
10
10
|
|
11
|
-
#
|
11
|
+
# Raised when Twitter returns a 4xx HTTP status code
|
12
|
+
ClientError = Class.new(self)
|
13
|
+
|
14
|
+
# Raised when Twitter returns the HTTP status code 400
|
15
|
+
BadRequest = Class.new(ClientError)
|
16
|
+
|
17
|
+
# Raised when Twitter returns the HTTP status code 401
|
18
|
+
Unauthorized = Class.new(ClientError)
|
19
|
+
|
20
|
+
# Raised when Twitter returns the HTTP status code 403
|
21
|
+
Forbidden = Class.new(ClientError)
|
22
|
+
|
23
|
+
# Raised when Twitter returns the HTTP status code 413
|
24
|
+
RequestEntityTooLarge = Class.new(ClientError)
|
25
|
+
|
26
|
+
# Raised when a Tweet has already been favorited
|
27
|
+
AlreadyFavorited = Class.new(Forbidden)
|
28
|
+
|
29
|
+
# Raised when a Tweet has already been retweeted
|
30
|
+
AlreadyRetweeted = Class.new(Forbidden)
|
31
|
+
|
32
|
+
# Raised when a Tweet has already been posted
|
33
|
+
DuplicateStatus = Class.new(Forbidden)
|
34
|
+
|
35
|
+
# Raised when Twitter returns the HTTP status code 404
|
36
|
+
NotFound = Class.new(ClientError)
|
37
|
+
|
38
|
+
# Raised when Twitter returns the HTTP status code 406
|
39
|
+
NotAcceptable = Class.new(ClientError)
|
40
|
+
|
41
|
+
# Raised when Twitter returns the HTTP status code 422
|
42
|
+
UnprocessableEntity = Class.new(ClientError)
|
43
|
+
|
44
|
+
# Raised when Twitter returns the HTTP status code 429
|
45
|
+
TooManyRequests = Class.new(ClientError)
|
46
|
+
|
47
|
+
# Raised when Twitter returns a 5xx HTTP status code
|
48
|
+
ServerError = Class.new(self)
|
49
|
+
|
50
|
+
# Raised when Twitter returns the HTTP status code 500
|
51
|
+
InternalServerError = Class.new(ServerError)
|
52
|
+
|
53
|
+
# Raised when Twitter returns the HTTP status code 502
|
54
|
+
BadGateway = Class.new(ServerError)
|
55
|
+
|
56
|
+
# Raised when Twitter returns the HTTP status code 503
|
57
|
+
ServiceUnavailable = Class.new(ServerError)
|
58
|
+
|
59
|
+
# Raised when Twitter returns the HTTP status code 504
|
60
|
+
GatewayTimeout = Class.new(ServerError)
|
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
|
+
|
77
|
+
ERRORS = {
|
78
|
+
400 => Twitter::Error::BadRequest,
|
79
|
+
401 => Twitter::Error::Unauthorized,
|
80
|
+
403 => Twitter::Error::Forbidden,
|
81
|
+
404 => Twitter::Error::NotFound,
|
82
|
+
406 => Twitter::Error::NotAcceptable,
|
83
|
+
413 => Twitter::Error::RequestEntityTooLarge,
|
84
|
+
422 => Twitter::Error::UnprocessableEntity,
|
85
|
+
429 => Twitter::Error::TooManyRequests,
|
86
|
+
500 => Twitter::Error::InternalServerError,
|
87
|
+
502 => Twitter::Error::BadGateway,
|
88
|
+
503 => Twitter::Error::ServiceUnavailable,
|
89
|
+
504 => Twitter::Error::GatewayTimeout,
|
90
|
+
}.freeze
|
91
|
+
|
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,
|
112
|
+
}.freeze
|
113
|
+
|
114
|
+
# If error code is missing see https://developer.twitter.com/en/docs/basics/response-codes
|
12
115
|
module Code
|
13
116
|
AUTHENTICATION_PROBLEM = 32
|
14
117
|
RESOURCE_NOT_FOUND = 34
|
@@ -35,49 +138,36 @@ module Twitter
|
|
35
138
|
CANNOT_MUTE = 271
|
36
139
|
CANNOT_UNMUTE = 272
|
37
140
|
end
|
38
|
-
Codes = Code
|
39
141
|
|
40
142
|
class << self
|
143
|
+
include Twitter::Utils
|
144
|
+
|
41
145
|
# Create a new error from an HTTP response
|
42
146
|
#
|
43
|
-
# @param
|
147
|
+
# @param body [String]
|
148
|
+
# @param headers [Hash]
|
44
149
|
# @return [Twitter::Error]
|
45
|
-
def from_response(
|
46
|
-
message, code = parse_error(
|
47
|
-
new(message,
|
48
|
-
end
|
49
|
-
|
50
|
-
# @return [Hash]
|
51
|
-
def errors
|
52
|
-
@errors ||= {
|
53
|
-
400 => Twitter::Error::BadRequest,
|
54
|
-
401 => Twitter::Error::Unauthorized,
|
55
|
-
403 => Twitter::Error::Forbidden,
|
56
|
-
404 => Twitter::Error::NotFound,
|
57
|
-
406 => Twitter::Error::NotAcceptable,
|
58
|
-
408 => Twitter::Error::RequestTimeout,
|
59
|
-
420 => Twitter::Error::EnhanceYourCalm,
|
60
|
-
422 => Twitter::Error::UnprocessableEntity,
|
61
|
-
429 => Twitter::Error::TooManyRequests,
|
62
|
-
500 => Twitter::Error::InternalServerError,
|
63
|
-
502 => Twitter::Error::BadGateway,
|
64
|
-
503 => Twitter::Error::ServiceUnavailable,
|
65
|
-
504 => Twitter::Error::GatewayTimeout,
|
66
|
-
}
|
150
|
+
def from_response(body, headers)
|
151
|
+
message, code = parse_error(body)
|
152
|
+
new(message, headers, code)
|
67
153
|
end
|
68
154
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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)
|
75
165
|
end
|
76
166
|
|
77
167
|
private
|
78
168
|
|
79
169
|
def parse_error(body)
|
80
|
-
if body.nil?
|
170
|
+
if body.nil? || body.empty?
|
81
171
|
['', nil]
|
82
172
|
elsif body[:error]
|
83
173
|
[body[:error], nil]
|
@@ -107,68 +197,5 @@ module Twitter
|
|
107
197
|
@rate_limit = Twitter::RateLimit.new(rate_limit)
|
108
198
|
@code = code
|
109
199
|
end
|
110
|
-
|
111
|
-
ConfigurationError = Class.new(::ArgumentError)
|
112
|
-
|
113
|
-
# Raised when a Tweet includes media that doesn't have a to_io method
|
114
|
-
class UnacceptableIO < StandardError
|
115
|
-
def initialize
|
116
|
-
super('The IO object for media must respond to to_io')
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# Raised when Twitter returns a 4xx HTTP status code
|
121
|
-
ClientError = Class.new(self)
|
122
|
-
|
123
|
-
# Raised when Twitter returns the HTTP status code 400
|
124
|
-
BadRequest = Class.new(ClientError)
|
125
|
-
|
126
|
-
# Raised when Twitter returns the HTTP status code 401
|
127
|
-
Unauthorized = Class.new(ClientError)
|
128
|
-
|
129
|
-
# Raised when Twitter returns the HTTP status code 403
|
130
|
-
Forbidden = Class.new(ClientError)
|
131
|
-
|
132
|
-
# Raised when a Tweet has already been favorited
|
133
|
-
AlreadyFavorited = Class.new(Forbidden)
|
134
|
-
|
135
|
-
# Raised when a Tweet has already been retweeted
|
136
|
-
AlreadyRetweeted = Class.new(Forbidden)
|
137
|
-
|
138
|
-
# Raised when a Tweet has already been posted
|
139
|
-
DuplicateStatus = Class.new(Forbidden)
|
140
|
-
AlreadyPosted = DuplicateStatus
|
141
|
-
|
142
|
-
# Raised when Twitter returns the HTTP status code 404
|
143
|
-
NotFound = Class.new(ClientError)
|
144
|
-
|
145
|
-
# Raised when Twitter returns the HTTP status code 406
|
146
|
-
NotAcceptable = Class.new(ClientError)
|
147
|
-
|
148
|
-
# Raised when Twitter returns the HTTP status code 408
|
149
|
-
RequestTimeout = Class.new(ClientError)
|
150
|
-
|
151
|
-
# Raised when Twitter returns the HTTP status code 422
|
152
|
-
UnprocessableEntity = Class.new(ClientError)
|
153
|
-
|
154
|
-
# Raised when Twitter returns the HTTP status code 429
|
155
|
-
TooManyRequests = Class.new(ClientError)
|
156
|
-
EnhanceYourCalm = TooManyRequests
|
157
|
-
RateLimited = TooManyRequests
|
158
|
-
|
159
|
-
# Raised when Twitter returns a 5xx HTTP status code
|
160
|
-
ServerError = Class.new(self)
|
161
|
-
|
162
|
-
# Raised when Twitter returns the HTTP status code 500
|
163
|
-
InternalServerError = Class.new(ServerError)
|
164
|
-
|
165
|
-
# Raised when Twitter returns the HTTP status code 502
|
166
|
-
BadGateway = Class.new(ServerError)
|
167
|
-
|
168
|
-
# Raised when Twitter returns the HTTP status code 503
|
169
|
-
ServiceUnavailable = Class.new(ServerError)
|
170
|
-
|
171
|
-
# Raised when Twitter returns the HTTP status code 504
|
172
|
-
GatewayTimeout = Class.new(ServerError)
|
173
200
|
end
|
174
201
|
end
|
data/lib/twitter/geo_results.rb
CHANGED
data/lib/twitter/headers.rb
CHANGED
@@ -8,21 +8,24 @@ module Twitter
|
|
8
8
|
@client = client
|
9
9
|
@request_method = request_method.to_sym
|
10
10
|
@uri = Addressable::URI.parse(url)
|
11
|
+
@bearer_token_request = options.delete(:bearer_token_request)
|
11
12
|
@options = options
|
12
|
-
|
13
|
+
end
|
14
|
+
|
15
|
+
def bearer_token_request?
|
16
|
+
!!@bearer_token_request
|
13
17
|
end
|
14
18
|
|
15
19
|
def oauth_auth_header
|
16
|
-
SimpleOAuth::Header.new(@request_method, @uri, @
|
20
|
+
SimpleOAuth::Header.new(@request_method, @uri, @options, @client.credentials.merge(ignore_extra_keys: true))
|
17
21
|
end
|
18
22
|
|
19
23
|
def request_headers
|
20
|
-
bearer_token_request = @options.delete(:bearer_token_request)
|
21
24
|
headers = {}
|
22
|
-
|
25
|
+
headers[:user_agent] = @client.user_agent
|
26
|
+
if bearer_token_request?
|
23
27
|
headers[:accept] = '*/*'
|
24
28
|
headers[:authorization] = bearer_token_credentials_auth_header
|
25
|
-
headers[:content_type] = 'application/x-www-form-urlencoded; charset=UTF-8'
|
26
29
|
else
|
27
30
|
headers[:authorization] = auth_header
|
28
31
|
end
|
@@ -40,23 +43,16 @@ module Twitter
|
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
46
|
+
# @return [String]
|
43
47
|
def bearer_auth_header
|
44
|
-
|
45
|
-
token = bearer_token.is_a?(Twitter::Token) && bearer_token.bearer? ? bearer_token.access_token : bearer_token
|
46
|
-
"Bearer #{token}"
|
48
|
+
"Bearer #{@client.bearer_token}"
|
47
49
|
end
|
48
50
|
|
49
51
|
# Generates authentication header for a bearer token request
|
50
52
|
#
|
51
53
|
# @return [String]
|
52
54
|
def bearer_token_credentials_auth_header
|
53
|
-
|
54
|
-
"Basic #{basic_auth_token}"
|
55
|
-
end
|
56
|
-
|
57
|
-
# Base64.strict_encode64 is not available on Ruby 1.8.7
|
58
|
-
def strict_encode64(str)
|
59
|
-
Base64.encode64(str).delete("\n")
|
55
|
+
"Basic #{Base64.strict_encode64("#{@client.consumer_key}:#{@client.consumer_secret}")}"
|
60
56
|
end
|
61
57
|
end
|
62
58
|
end
|
data/lib/twitter/media/photo.rb
CHANGED
@@ -8,6 +8,10 @@ module Twitter
|
|
8
8
|
|
9
9
|
# @return [Array<Integer>]
|
10
10
|
attr_reader :indices
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
attr_reader :type
|
14
|
+
|
11
15
|
display_uri_attr_reader
|
12
16
|
uri_attr_reader :expanded_uri, :media_uri, :media_uri_https, :uri
|
13
17
|
|
@@ -15,9 +19,8 @@ module Twitter
|
|
15
19
|
#
|
16
20
|
# @return [Array<Twitter::Size>]
|
17
21
|
def sizes
|
18
|
-
@attrs.fetch(:sizes, []).
|
22
|
+
@attrs.fetch(:sizes, []).each_with_object({}) do |(key, value), object|
|
19
23
|
object[key] = Size.new(value)
|
20
|
-
object
|
21
24
|
end
|
22
25
|
end
|
23
26
|
memoize :sizes
|
data/lib/twitter/media/video.rb
CHANGED
@@ -9,6 +9,10 @@ module Twitter
|
|
9
9
|
|
10
10
|
# @return [Array<Integer>]
|
11
11
|
attr_reader :indices
|
12
|
+
|
13
|
+
# @return [String]
|
14
|
+
attr_reader :type
|
15
|
+
|
12
16
|
display_uri_attr_reader
|
13
17
|
uri_attr_reader :expanded_uri, :media_uri, :media_uri_https, :uri
|
14
18
|
|
@@ -16,9 +20,8 @@ module Twitter
|
|
16
20
|
#
|
17
21
|
# @return [Array<Twitter::Size>]
|
18
22
|
def sizes
|
19
|
-
@attrs.fetch(:sizes, []).
|
23
|
+
@attrs.fetch(:sizes, []).each_with_object({}) do |(key, value), object|
|
20
24
|
object[key] = Size.new(value)
|
21
|
-
object
|
22
25
|
end
|
23
26
|
end
|
24
27
|
memoize :sizes
|
data/lib/twitter/null_object.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'naught'
|
2
2
|
|
3
3
|
module Twitter
|
4
|
-
NullObject = Naught.build do |config|
|
4
|
+
NullObject = Naught.build do |config| # rubocop:disable Metrics/BlockLength
|
5
5
|
include Comparable
|
6
6
|
|
7
7
|
config.black_hole
|
@@ -9,22 +9,23 @@ module Twitter
|
|
9
9
|
config.define_implicit_conversions
|
10
10
|
config.predicates_return false
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# end
|
12
|
+
def !
|
13
|
+
true
|
14
|
+
end
|
16
15
|
|
17
16
|
def respond_to?(*)
|
18
17
|
true
|
19
18
|
end
|
20
19
|
|
21
20
|
def instance_of?(klass)
|
22
|
-
raise(TypeError
|
21
|
+
raise(TypeError, 'class or module required') unless klass.is_a?(Class)
|
22
|
+
|
23
23
|
self.class == klass
|
24
24
|
end
|
25
25
|
|
26
26
|
def kind_of?(mod)
|
27
|
-
raise(TypeError
|
27
|
+
raise(TypeError, 'class or module required') unless mod.is_a?(Module)
|
28
|
+
|
28
29
|
self.class.ancestors.include?(mod)
|
29
30
|
end
|
30
31
|
|
@@ -49,5 +50,17 @@ module Twitter
|
|
49
50
|
def to_json(*args)
|
50
51
|
nil.to_json(*args)
|
51
52
|
end
|
53
|
+
|
54
|
+
def presence
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def blank?
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def present?
|
63
|
+
false
|
64
|
+
end
|
52
65
|
end
|
53
66
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'twitter/enumerable'
|
3
|
+
require 'twitter/rest/request'
|
4
|
+
require 'twitter/utils'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
module Twitter
|
8
|
+
class PremiumSearchResults
|
9
|
+
include Twitter::Enumerable
|
10
|
+
include Twitter::Utils
|
11
|
+
# @return [Hash]
|
12
|
+
attr_reader :attrs
|
13
|
+
alias to_h attrs
|
14
|
+
alias to_hash to_h
|
15
|
+
|
16
|
+
# Initializes a new SearchResults object
|
17
|
+
#
|
18
|
+
# @param request [Twitter::REST::Request]
|
19
|
+
# @return [Twitter::PremiumSearchResults]
|
20
|
+
def initialize(request, request_config = {})
|
21
|
+
@client = request.client
|
22
|
+
@request_method = request.verb
|
23
|
+
@path = request.path
|
24
|
+
@options = request.options
|
25
|
+
@request_config = request_config
|
26
|
+
@collection = []
|
27
|
+
self.attrs = request.perform
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# @return [Boolean]
|
33
|
+
def last?
|
34
|
+
!next_page?
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Boolean]
|
38
|
+
def next_page?
|
39
|
+
!!@attrs[:next]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a Hash of query parameters for the next result in the search
|
43
|
+
#
|
44
|
+
# @note Returned Hash can be merged into the previous search options list to easily access the next page.
|
45
|
+
# @return [Hash] The parameters needed to fetch the next page.
|
46
|
+
def next_page
|
47
|
+
{next: @attrs[:next]} if next_page?
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Hash]
|
51
|
+
def fetch_next_page
|
52
|
+
request = @client.premium_search(@options[:query], (@options.reject { |k| k == :query } || {}).merge(next_page), @request_config)
|
53
|
+
|
54
|
+
self.attrs = request.attrs
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param attrs [Hash]
|
58
|
+
# @return [Hash]
|
59
|
+
def attrs=(attrs)
|
60
|
+
@attrs = attrs
|
61
|
+
@attrs.fetch(:results, []).collect do |tweet|
|
62
|
+
@collection << Tweet.new(tweet)
|
63
|
+
end
|
64
|
+
@attrs
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/twitter/profile.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
require 'addressable/uri'
|
2
|
+
require 'cgi'
|
2
3
|
require 'memoizable'
|
3
4
|
|
4
5
|
module Twitter
|
5
6
|
module Profile
|
6
|
-
PROFILE_IMAGE_SUFFIX_REGEX = /_normal(\.gif|\.jpe?g|\.png)$/i
|
7
|
-
PREDICATE_URI_METHOD_REGEX = /_uri
|
7
|
+
PROFILE_IMAGE_SUFFIX_REGEX = /_normal(\.gif|\.jpe?g|\.png)$/i.freeze
|
8
|
+
PREDICATE_URI_METHOD_REGEX = /_uri\?$/.freeze
|
8
9
|
include Memoizable
|
9
10
|
|
10
11
|
class << self
|
11
12
|
private
|
12
13
|
|
13
14
|
def alias_predicate_uri_methods(method)
|
14
|
-
%w
|
15
|
+
%w[_url? _uri_https? _url_https?].each do |replacement|
|
15
16
|
alias_method_sub(method, PREDICATE_URI_METHOD_REGEX, replacement)
|
16
17
|
end
|
17
18
|
end
|
@@ -88,7 +89,7 @@ module Twitter
|
|
88
89
|
end
|
89
90
|
|
90
91
|
def profile_image_suffix(size)
|
91
|
-
|
92
|
+
size.to_sym == :original ? '\\1' : "_#{size}\\1"
|
92
93
|
end
|
93
94
|
end
|
94
95
|
end
|
@@ -9,9 +9,8 @@ module Twitter
|
|
9
9
|
#
|
10
10
|
# @return [Array<Twitter::Size>]
|
11
11
|
def sizes
|
12
|
-
@attrs.fetch(:sizes, []).
|
12
|
+
@attrs.fetch(:sizes, []).each_with_object({}) do |(key, value), object|
|
13
13
|
object[key] = Size.new(value)
|
14
|
-
object
|
15
14
|
end
|
16
15
|
end
|
17
16
|
memoize :sizes
|
data/lib/twitter/rate_limit.rb
CHANGED
@@ -7,21 +7,21 @@ module Twitter
|
|
7
7
|
# @return [Integer]
|
8
8
|
def limit
|
9
9
|
limit = @attrs['x-rate-limit-limit']
|
10
|
-
limit
|
10
|
+
limit&.to_i
|
11
11
|
end
|
12
12
|
memoize :limit
|
13
13
|
|
14
14
|
# @return [Integer]
|
15
15
|
def remaining
|
16
16
|
remaining = @attrs['x-rate-limit-remaining']
|
17
|
-
remaining
|
17
|
+
remaining&.to_i
|
18
18
|
end
|
19
19
|
memoize :remaining
|
20
20
|
|
21
21
|
# @return [Time]
|
22
22
|
def reset_at
|
23
23
|
reset = @attrs['x-rate-limit-reset']
|
24
|
-
Time.at(reset.to_i) if reset
|
24
|
+
Time.at(reset.to_i).utc if reset
|
25
25
|
end
|
26
26
|
memoize :reset_at
|
27
27
|
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'twitter/rest/request'
|
2
|
+
require 'twitter/rest/utils'
|
3
|
+
require 'twitter/utils'
|
4
|
+
|
5
|
+
module Twitter
|
6
|
+
module REST
|
7
|
+
module AccountActivity
|
8
|
+
include Twitter::REST::Utils
|
9
|
+
include Twitter::Utils
|
10
|
+
|
11
|
+
# Registers a webhook URL for all event types. The URL will be validated via CRC request before saving. In case the validation failed, returns comprehensive error message to the requester.
|
12
|
+
# @see https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/api-reference
|
13
|
+
# @see https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/api-reference/aaa-premium#post-account-activity-all-env-name-webhooks
|
14
|
+
# @note Create a webhook
|
15
|
+
# @rate_limited Yes
|
16
|
+
# @authentication Requires user context - all consumer and access tokens
|
17
|
+
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
|
18
|
+
# @return [Hash]
|
19
|
+
# @param env_name [String] Environment Name.
|
20
|
+
# @param url [String] Encoded URL for the callback endpoint.
|
21
|
+
def create_webhook(env_name, url)
|
22
|
+
perform_request(:json_post, "/1.1/account_activity/all/#{env_name}/webhooks.json?url=#{url}")
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns all environments, webhook URLs and their statuses for the authenticating app. Currently, only one webhook URL can be registered to each environment.
|
26
|
+
# @see https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/api-reference/aaa-premium#get-account-activity-all-webhooks
|
27
|
+
# @note List webhooks
|
28
|
+
# @rate_limited Yes
|
29
|
+
# @authentication Requires user context - all consumer and access tokens
|
30
|
+
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
|
31
|
+
# @return [Hash]
|
32
|
+
# @param env_name [String] Environment Name.
|
33
|
+
def list_webhooks(env_name)
|
34
|
+
perform_request(:get, "/1.1/account_activity/all/#{env_name}/webhooks.json")
|
35
|
+
end
|
36
|
+
|
37
|
+
# Removes the webhook from the provided application's all activities configuration. The webhook ID can be accessed by making a call to GET /1.1/account_activity/all/webhooks.
|
38
|
+
# @see https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/api-reference/aaa-premium#delete-account-activity-all-env-name-webhooks-webhook-id
|
39
|
+
# @note Delete a webhook
|
40
|
+
# @authentication Requires user context - all consumer and access tokens
|
41
|
+
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
|
42
|
+
# @return [nil]
|
43
|
+
# @param env_name [String] Environment Name.
|
44
|
+
# @param webhook_id [String] Webhook ID.
|
45
|
+
def delete_webhook(env_name, webhook_id)
|
46
|
+
perform_request(:delete, "/1.1/account_activity/all/#{env_name}/webhooks/#{webhook_id}.json")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Triggers the challenge response check (CRC) for the given enviroments webhook for all activites. If the check is successful, returns 204 and reenables the webhook by setting its status to valid.
|
50
|
+
# @see https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/api-reference/aaa-premium#put-account-activity-all-env-name-webhooks-webhook-id
|
51
|
+
# @note Trigger CRC check to a webhook
|
52
|
+
# @rate_limited Yes
|
53
|
+
# @authentication Requires user context - all consumer and access tokens
|
54
|
+
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
|
55
|
+
# @return [nil]
|
56
|
+
# @param env_name [String] Environment Name.
|
57
|
+
# @param webhook_id [String] Webhook ID.
|
58
|
+
def trigger_crc_check(env_name, webhook_id)
|
59
|
+
perform_request(:json_put, "/1.1/account_activity/all/#{env_name}/webhooks/#{webhook_id}.json")
|
60
|
+
end
|
61
|
+
|
62
|
+
# Subscribes the provided application to all events for the provided environment for all message types. After activation, all events for the requesting user will be sent to the application's webhook via POST request.
|
63
|
+
# @see https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/api-reference/aaa-premium#post-account-activity-all-env-name-subscriptions
|
64
|
+
# @note Subscribe the user(whose credentials are provided) to the app so that the webhook can receive all types of events from user
|
65
|
+
# @rate_limited Yes
|
66
|
+
# @authentication Requires user context - all consumer and access tokens
|
67
|
+
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
|
68
|
+
# @return [nil]
|
69
|
+
# @param env_name [String] Environment Name
|
70
|
+
def create_subscription(env_name)
|
71
|
+
perform_request(:json_post, "/1.1/account_activity/all/#{env_name}/subscriptions.json")
|
72
|
+
end
|
73
|
+
|
74
|
+
# Provides a way to determine if a webhook configuration is subscribed to the provided user's events. If the provided user context has an active subscription with provided application, returns 204 OK.
|
75
|
+
# @see https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/api-reference/aaa-premium#get-account-activity-all-env-name-subscriptions
|
76
|
+
# @note Check if the user is subscribed to the given app
|
77
|
+
# @rate_limited Yes
|
78
|
+
# @authentication Requires user context - all consumer and access tokens
|
79
|
+
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
|
80
|
+
# @return [nil]
|
81
|
+
# @param env_name [String] Environment Name
|
82
|
+
def check_subscription(env_name)
|
83
|
+
perform_request(:get, "/1.1/account_activity/all/#{env_name}/subscriptions.json")
|
84
|
+
end
|
85
|
+
|
86
|
+
# Deactivates subscription(s) for the provided user context and application for all activities. After deactivation, all events for the requesting user will no longer be sent to the webhook URL.
|
87
|
+
# @see https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/api-reference/aaa-premium#delete-account-activity-all-env-name-subscriptions
|
88
|
+
# @note Deactivate a subscription, Users events will not be sent to the app
|
89
|
+
# @rate_limited Yes
|
90
|
+
# @authentication Requires user context - all consumer and access tokens
|
91
|
+
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
|
92
|
+
# @return [nil]
|
93
|
+
# @param env_name [String] Environment Name
|
94
|
+
def deactivate_subscription(env_name)
|
95
|
+
perform_request(:delete, "/1.1/account_activity/all/#{env_name}/subscriptions.json")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|