x 0.9.1 → 0.11.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +43 -27
- data/README.md +6 -2
- data/lib/x/authenticator.rb +8 -0
- data/lib/x/bearer_token_authenticator.rb +5 -3
- data/lib/x/cgi.rb +15 -0
- data/lib/x/client.rb +40 -37
- data/lib/x/connection.rb +42 -65
- data/lib/x/errors/bad_gateway.rb +5 -0
- data/lib/x/errors/{not_found_error.rb → bad_request.rb} +1 -1
- data/lib/x/errors/connection_exception.rb +5 -0
- data/lib/x/errors/error.rb +1 -9
- data/lib/x/errors/{forbidden_error.rb → forbidden.rb} +1 -1
- data/lib/x/errors/gateway_timeout.rb +5 -0
- data/lib/x/errors/{bad_request_error.rb → gone.rb} +1 -1
- data/lib/x/errors/internal_server_error.rb +5 -0
- data/lib/x/errors/network_error.rb +1 -1
- data/lib/x/errors/not_acceptable.rb +5 -0
- data/lib/x/errors/not_found.rb +5 -0
- data/lib/x/errors/payload_too_large.rb +5 -0
- data/lib/x/errors/service_unavailable.rb +5 -0
- data/lib/x/errors/too_many_redirects.rb +5 -0
- data/lib/x/errors/too_many_requests.rb +29 -0
- data/lib/x/errors/unauthorized.rb +5 -0
- data/lib/x/errors/unprocessable_entity.rb +5 -0
- data/lib/x/media_uploader.rb +122 -0
- data/lib/x/oauth_authenticator.rb +10 -15
- data/lib/x/redirect_handler.rb +26 -24
- data/lib/x/request_builder.rb +22 -28
- data/lib/x/response_parser.rb +92 -0
- data/lib/x/version.rb +1 -1
- data/sig/x.rbs +160 -71
- metadata +22 -11
- data/lib/x/errors/authentication_error.rb +0 -5
- data/lib/x/errors/service_unavailable_error.rb +0 -5
- data/lib/x/errors/too_many_redirects_error.rb +0 -5
- data/lib/x/errors/too_many_requests_error.rb +0 -29
- data/lib/x/response_handler.rb +0 -54
data/sig/x.rbs
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
module X
|
2
2
|
VERSION: Gem::Version
|
3
3
|
|
4
|
+
class Authenticator
|
5
|
+
def header: (Net::HTTPRequest? request) -> Hash[String, String]
|
6
|
+
end
|
7
|
+
|
4
8
|
class BearerTokenAuthenticator
|
5
9
|
attr_accessor bearer_token: String
|
6
|
-
def initialize: (String
|
7
|
-
def header: (Net::HTTPRequest
|
10
|
+
def initialize: (bearer_token: String) -> void
|
11
|
+
def header: (Net::HTTPRequest? request) -> Hash[String, String]
|
8
12
|
end
|
9
13
|
|
10
|
-
class
|
14
|
+
class OAuthAuthenticator
|
11
15
|
OAUTH_VERSION: String
|
12
16
|
OAUTH_SIGNATURE_METHOD: String
|
13
17
|
OAUTH_SIGNATURE_ALGORITHM: String
|
@@ -16,8 +20,8 @@ module X
|
|
16
20
|
attr_accessor api_key_secret: String
|
17
21
|
attr_accessor access_token: String
|
18
22
|
attr_accessor access_token_secret: String
|
19
|
-
def initialize: (
|
20
|
-
def header: (Net::HTTPRequest request) -> String
|
23
|
+
def initialize: (api_key: String, api_key_secret: String, access_token: String, access_token_secret: String) -> void
|
24
|
+
def header: (Net::HTTPRequest request) -> Hash[String, String]
|
21
25
|
|
22
26
|
private
|
23
27
|
def parse_request: (Net::HTTPRequest request) -> [String, String, Hash[String, String]]
|
@@ -33,152 +37,237 @@ module X
|
|
33
37
|
def escape: (String value) -> String
|
34
38
|
end
|
35
39
|
|
40
|
+
class ClientError < Error
|
41
|
+
end
|
42
|
+
|
43
|
+
class BadGateway < ClientError
|
44
|
+
end
|
45
|
+
|
46
|
+
class BadRequest < ClientError
|
47
|
+
end
|
48
|
+
|
49
|
+
class ConnectionException < ClientError
|
50
|
+
end
|
51
|
+
|
36
52
|
class Error < StandardError
|
37
|
-
|
53
|
+
def initialize: (String msg, ?Net::HTTPResponse? response) -> void
|
54
|
+
end
|
38
55
|
|
39
|
-
|
40
|
-
|
56
|
+
class Forbidden < ClientError
|
57
|
+
end
|
41
58
|
|
42
|
-
|
43
|
-
def json_response?: (Net::HTTPResponse response) -> bool
|
59
|
+
class GatewayTimeout < ClientError
|
44
60
|
end
|
45
61
|
|
46
|
-
class
|
62
|
+
class Gone < ClientError
|
63
|
+
end
|
64
|
+
|
65
|
+
class InternalServerError < ServerError
|
66
|
+
end
|
67
|
+
|
68
|
+
class NetworkError < Error
|
69
|
+
end
|
70
|
+
|
71
|
+
class NotAcceptable < ClientError
|
47
72
|
end
|
48
73
|
|
49
|
-
class
|
74
|
+
class NotFound < ClientError
|
50
75
|
end
|
51
76
|
|
52
|
-
class
|
77
|
+
class PayloadTooLarge < ClientError
|
53
78
|
end
|
54
79
|
|
55
|
-
class
|
80
|
+
class ServerError < Error
|
56
81
|
end
|
57
82
|
|
58
|
-
class
|
83
|
+
class ServiceUnavailable < ServerError
|
59
84
|
end
|
60
85
|
|
61
|
-
class
|
86
|
+
class TooManyRedirects < ClientError
|
62
87
|
end
|
63
88
|
|
64
|
-
class
|
89
|
+
class TooManyRequests < ClientError
|
65
90
|
@response: Net::HTTPResponse
|
66
91
|
|
67
|
-
def initialize: (String msg,
|
92
|
+
def initialize: (String msg, Net::HTTPResponse response) -> void
|
68
93
|
def limit: -> Integer
|
69
94
|
def remaining: -> Integer
|
70
95
|
def reset_at: -> Time
|
71
96
|
def reset_in: -> Integer?
|
72
97
|
end
|
73
98
|
|
74
|
-
class
|
75
|
-
end
|
76
|
-
|
77
|
-
class ServiceUnavailableError < ServerError
|
99
|
+
class Unauthorized < ClientError
|
78
100
|
end
|
79
101
|
|
80
|
-
class
|
102
|
+
class UnprocessableEntity < ClientError
|
81
103
|
end
|
82
104
|
|
83
105
|
class Connection
|
84
|
-
DEFAULT_BASE_URL: String
|
85
106
|
DEFAULT_HOST: String
|
86
107
|
DEFAULT_PORT: Integer
|
87
108
|
DEFAULT_OPEN_TIMEOUT: Integer
|
88
109
|
DEFAULT_READ_TIMEOUT: Integer
|
89
110
|
DEFAULT_WRITE_TIMEOUT: Integer
|
90
|
-
|
111
|
+
DEFAULT_DEBUG_OUTPUT: IO
|
112
|
+
NETWORK_ERRORS: Array[(singleton(Errno::ECONNREFUSED) | singleton(Errno::ECONNRESET) | singleton(Net::OpenTimeout) | singleton(Net::ReadTimeout) | singleton(OpenSSL::SSL::SSLError))]
|
113
|
+
|
91
114
|
extend Forwardable
|
92
|
-
@http_client: Net::HTTP
|
93
115
|
|
94
|
-
|
116
|
+
attr_accessor open_timeout : Float | Integer
|
117
|
+
attr_accessor read_timeout : Float | Integer
|
118
|
+
attr_accessor write_timeout : Float | Integer
|
119
|
+
attr_accessor debug_output : IO
|
120
|
+
|
95
121
|
attr_reader proxy_uri: URI::Generic?
|
96
|
-
attr_reader
|
97
|
-
attr_reader
|
98
|
-
attr_reader
|
99
|
-
|
100
|
-
|
101
|
-
def
|
102
|
-
def
|
122
|
+
attr_reader proxy_host : String?
|
123
|
+
attr_reader proxy_port : Integer?
|
124
|
+
attr_reader proxy_user : String?
|
125
|
+
attr_reader proxy_pass : String?
|
126
|
+
|
127
|
+
def initialize: (?open_timeout: Float | Integer, ?read_timeout: Float | Integer, ?write_timeout: Float | Integer, ?proxy_url: URI::Generic? | String?, ?debug_output: IO) -> void
|
128
|
+
def proxy_url=: (URI::Generic | String proxy_url) -> void
|
129
|
+
def perform: (request: Net::HTTPRequest) -> Net::HTTPResponse
|
103
130
|
|
104
131
|
private
|
105
|
-
def
|
106
|
-
def
|
107
|
-
def update_http_client_settings: -> untyped
|
108
|
-
def build_http_client: (host: String, port: Integer) -> (Net::HTTP)
|
109
|
-
def conditionally_apply_http_client_settings: { -> untyped } -> untyped
|
132
|
+
def build_http_client: (?String host, ?Integer port) -> Net::HTTP
|
133
|
+
def configure_http_client: (Net::HTTP http_client) -> Net::HTTP
|
110
134
|
end
|
111
135
|
|
112
136
|
class RequestBuilder
|
113
|
-
HTTP_METHODS: Hash[
|
114
|
-
|
115
|
-
|
116
|
-
AUTHORIZATION_HEADER: String
|
117
|
-
CONTENT_TYPE_HEADER: String
|
118
|
-
USER_AGENT_HEADER: String
|
119
|
-
|
120
|
-
attr_accessor content_type: String
|
121
|
-
attr_accessor user_agent: String
|
137
|
+
HTTP_METHODS: Hash[Symbol, (singleton(Net::HTTP::Get) | singleton(Net::HTTP::Post) | singleton(Net::HTTP::Put) | singleton(Net::HTTP::Delete))]
|
138
|
+
DEFAULT_HEADERS: Hash[String, String]
|
139
|
+
|
122
140
|
def initialize: (?content_type: String, ?user_agent: String) -> void
|
123
|
-
def build: (
|
141
|
+
def build: (authenticator: Authenticator, http_method: Symbol, uri: URI::Generic, ?body: String?, ?headers: Hash[String, String]) -> (Net::HTTPRequest)
|
124
142
|
|
125
143
|
private
|
126
|
-
def create_request: (Symbol
|
127
|
-
def
|
128
|
-
def
|
129
|
-
def add_user_agent: (Net::HTTPRequest request) -> void
|
144
|
+
def create_request: (http_method: Symbol, uri: URI::Generic, body: String?) -> (Net::HTTPRequest)
|
145
|
+
def add_authentication: (request: Net::HTTPRequest, authenticator: Authenticator) -> void
|
146
|
+
def add_headers: (request: Net::HTTPRequest, headers: Hash[String, String]) -> void
|
130
147
|
def escape_query_params: (URI::Generic uri) -> URI::Generic
|
131
148
|
end
|
132
149
|
|
133
150
|
class RedirectHandler
|
134
151
|
DEFAULT_MAX_REDIRECTS: Integer
|
135
152
|
|
136
|
-
attr_reader authenticator:
|
153
|
+
attr_reader authenticator: Authenticator
|
137
154
|
attr_reader connection: Connection
|
138
155
|
attr_reader request_builder: RequestBuilder
|
139
156
|
attr_reader max_redirects: Integer
|
140
|
-
def initialize: (
|
141
|
-
def
|
157
|
+
def initialize: (authenticator: Authenticator, connection: Connection, request_builder: RequestBuilder, ?max_redirects: Integer) -> void
|
158
|
+
def handle: (response: Net::HTTPResponse, request: Net::HTTPRequest, base_url: String, ?redirect_count: Integer) -> Net::HTTPResponse
|
142
159
|
|
143
160
|
private
|
144
|
-
def build_new_uri: (Net::HTTPResponse response,
|
145
|
-
def build_request: (Net::HTTPRequest
|
161
|
+
def build_new_uri: (Net::HTTPResponse response, String base_url) -> URI::Generic
|
162
|
+
def build_request: (Net::HTTPRequest request, URI::Generic new_uri, Integer response_code) -> Net::HTTPRequest
|
146
163
|
def send_new_request: (URI::Generic new_uri, Net::HTTPRequest new_request) -> Net::HTTPResponse
|
147
164
|
end
|
148
165
|
|
149
|
-
class
|
166
|
+
class ResponseParser
|
150
167
|
DEFAULT_ARRAY_CLASS: Class
|
151
168
|
DEFAULT_OBJECT_CLASS: Class
|
152
|
-
ERROR_CLASSES: Hash[Integer, singleton(
|
169
|
+
ERROR_CLASSES: Hash[Integer, singleton(Unauthorized) | singleton(BadRequest) | singleton(Forbidden) | singleton(InternalServerError) | singleton(NotFound) | singleton(PayloadTooLarge) | singleton(ServiceUnavailable) | singleton(TooManyRequests)]
|
153
170
|
JSON_CONTENT_TYPE_REGEXP: Regexp
|
154
171
|
|
155
172
|
attr_accessor array_class: Class
|
156
173
|
attr_accessor object_class: Class
|
157
174
|
def initialize: (?array_class: Class, ?object_class: Class) -> void
|
158
|
-
def
|
175
|
+
def parse: (response: Net::HTTPResponse) -> untyped
|
159
176
|
|
160
177
|
private
|
161
178
|
def success?: (Net::HTTPResponse response) -> bool
|
179
|
+
def error: (Net::HTTPResponse response) -> (Unauthorized | BadRequest | Forbidden | InternalServerError | NotFound | PayloadTooLarge | ServiceUnavailable | TooManyRequests)
|
180
|
+
def error_class: (Net::HTTPResponse response) -> (singleton(Unauthorized) | singleton(BadRequest) | singleton(Forbidden) | singleton(InternalServerError) | singleton(NotFound) | singleton(PayloadTooLarge) | singleton(ServiceUnavailable) | singleton(TooManyRequests))
|
181
|
+
def error_message: (Net::HTTPResponse response) -> String
|
182
|
+
def message_from_json_response: (Net::HTTPResponse response) -> String
|
162
183
|
def json?: (Net::HTTPResponse response) -> bool
|
163
184
|
end
|
164
185
|
|
165
186
|
class Client
|
187
|
+
DEFAULT_BASE_URL: String
|
188
|
+
|
166
189
|
extend Forwardable
|
167
|
-
@authenticator:
|
190
|
+
@authenticator: Authenticator
|
168
191
|
@connection: Connection
|
169
192
|
@request_builder: RequestBuilder
|
170
193
|
@redirect_handler: RedirectHandler
|
171
|
-
@
|
194
|
+
@response_parser: ResponseParser
|
172
195
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
196
|
+
attr_accessor access_token: String
|
197
|
+
attr_accessor access_token_secret: String
|
198
|
+
attr_accessor api_key: String
|
199
|
+
attr_accessor api_key_secret: String
|
200
|
+
attr_accessor bearer_token: String
|
201
|
+
attr_accessor base_url: String
|
202
|
+
attr_accessor open_timeout: Float | Integer
|
203
|
+
attr_accessor read_timeout: Float | Integer
|
204
|
+
attr_accessor write_timeout: Float | Integer
|
205
|
+
attr_accessor proxy_url: String
|
206
|
+
attr_accessor debug_output: IO
|
207
|
+
attr_accessor array_class: Class
|
208
|
+
attr_accessor object_class: Class
|
209
|
+
attr_accessor max_redirects: Integer
|
210
|
+
attr_accessor authenticator: Authenticator
|
211
|
+
attr_accessor connection: Connection
|
212
|
+
attr_accessor request_builder: RequestBuilder
|
213
|
+
attr_accessor redirect_handler: RedirectHandler
|
214
|
+
attr_accessor response_parser: ResponseParser
|
215
|
+
|
216
|
+
def initialize: (?bearer_token: String?, ?api_key: String?, ?api_key_secret: String?, ?access_token: String?, ?access_token_secret: String?, ?base_url: String, ?open_timeout: Float | Integer, ?read_timeout: Float | Integer, ?write_timeout: Float | Integer, ?proxy_url: URI::Generic? | String?, ?debug_output: IO, ?array_class: Class, ?object_class: Class, ?max_redirects: Integer) -> void
|
217
|
+
def get: (String endpoint, ?headers: Hash[String, String]) -> untyped
|
218
|
+
def post: (String endpoint, ?String? body, ?headers: Hash[String, String]) -> untyped
|
219
|
+
def put: (String endpoint, ?String? body, ?headers: Hash[String, String]) -> untyped
|
220
|
+
def delete: (String endpoint, ?headers: Hash[String, String]) -> untyped
|
221
|
+
|
222
|
+
private
|
223
|
+
def initialize_authenticator: (String? bearer_token, String? api_key, String? api_key_secret, String? access_token, String? access_token_secret) -> (BearerTokenAuthenticator | OAuthAuthenticator | Authenticator)
|
224
|
+
def execute_request: (Symbol http_method, String endpoint, headers: Hash[String, String], ?body: String?) -> untyped
|
225
|
+
end
|
226
|
+
|
227
|
+
module MediaUploader
|
228
|
+
MAX_RETRIES: Integer
|
229
|
+
BYTES_PER_MB: Integer
|
230
|
+
MEDIA_CATEGORIES: Array[String]
|
231
|
+
DM_GIF: String
|
232
|
+
DM_IMAGE: String
|
233
|
+
DM_VIDEO: String
|
234
|
+
SUBTITLES: String
|
235
|
+
TWEET_GIF: String
|
236
|
+
TWEET_IMAGE: String
|
237
|
+
TWEET_VIDEO: String
|
238
|
+
DEFAULT_MIME_TYPE: String
|
239
|
+
MIME_TYPES: Array[String]
|
240
|
+
GIF_MIME_TYPE: String
|
241
|
+
JPEG_MIME_TYPE: String
|
242
|
+
MP4_MIME_TYPE: String
|
243
|
+
PNG_MIME_TYPE: String
|
244
|
+
SUBRIP_MIME_TYPE: String
|
245
|
+
WEBP_MIME_TYPE: String
|
246
|
+
MIME_TYPE_MAP: Hash[String, String]
|
247
|
+
extend MediaUploader
|
248
|
+
|
249
|
+
def upload: (client: Client, file_path: String, media_category: String, ?media_type: String, ?boundary: String) -> untyped
|
250
|
+
def chunked_upload: (client: Client, file_path: String, media_category: String, ?media_type: String, ?boundary: String, ?chunk_size_mb: Integer) -> untyped
|
251
|
+
def await_processing: (client: Client, media: untyped) -> untyped
|
179
252
|
|
180
253
|
private
|
181
|
-
def
|
182
|
-
def
|
254
|
+
def validate!: (file_path: String, media_category: String) -> nil
|
255
|
+
def infer_media_type: (String file_path, String media_category) -> String
|
256
|
+
def init: (Client upload_client, String file_path, String media_type, String media_category) -> untyped
|
257
|
+
def split: (String file_path, Integer chunk_size) -> Array[String]
|
258
|
+
def append: (Client upload_client, Array[String] chunk_paths, untyped media, String media_type, ?String boundary) -> Array[String]
|
259
|
+
def upload_chunk: (Client upload_client, String query, String chunk_path, String media_type, ?Hash[String, String] headers) -> Integer?
|
260
|
+
def cleanup_chunk: (String chunk_path) -> Integer?
|
261
|
+
def finalize: (Client upload_client, untyped media) -> untyped
|
262
|
+
def construct_upload_body: (String file_path, String media_type, ?String boundary) -> String
|
263
|
+
end
|
264
|
+
|
265
|
+
class CGI
|
266
|
+
def self.escape: (String value) -> String
|
267
|
+
def self.escape_params: (Hash[String, String] | Array[[String, String]] params) -> String
|
183
268
|
end
|
184
269
|
end
|
270
|
+
|
271
|
+
class Dir
|
272
|
+
def self.mktmpdir: (?String? prefix_suffix) -> String
|
273
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: x
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Erik Berlin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -23,24 +23,35 @@ files:
|
|
23
23
|
- bin/console
|
24
24
|
- bin/setup
|
25
25
|
- lib/x.rb
|
26
|
+
- lib/x/authenticator.rb
|
26
27
|
- lib/x/bearer_token_authenticator.rb
|
28
|
+
- lib/x/cgi.rb
|
27
29
|
- lib/x/client.rb
|
28
30
|
- lib/x/connection.rb
|
29
|
-
- lib/x/errors/
|
30
|
-
- lib/x/errors/
|
31
|
+
- lib/x/errors/bad_gateway.rb
|
32
|
+
- lib/x/errors/bad_request.rb
|
31
33
|
- lib/x/errors/client_error.rb
|
34
|
+
- lib/x/errors/connection_exception.rb
|
32
35
|
- lib/x/errors/error.rb
|
33
|
-
- lib/x/errors/
|
36
|
+
- lib/x/errors/forbidden.rb
|
37
|
+
- lib/x/errors/gateway_timeout.rb
|
38
|
+
- lib/x/errors/gone.rb
|
39
|
+
- lib/x/errors/internal_server_error.rb
|
34
40
|
- lib/x/errors/network_error.rb
|
35
|
-
- lib/x/errors/
|
41
|
+
- lib/x/errors/not_acceptable.rb
|
42
|
+
- lib/x/errors/not_found.rb
|
43
|
+
- lib/x/errors/payload_too_large.rb
|
36
44
|
- lib/x/errors/server_error.rb
|
37
|
-
- lib/x/errors/
|
38
|
-
- lib/x/errors/
|
39
|
-
- lib/x/errors/
|
45
|
+
- lib/x/errors/service_unavailable.rb
|
46
|
+
- lib/x/errors/too_many_redirects.rb
|
47
|
+
- lib/x/errors/too_many_requests.rb
|
48
|
+
- lib/x/errors/unauthorized.rb
|
49
|
+
- lib/x/errors/unprocessable_entity.rb
|
50
|
+
- lib/x/media_uploader.rb
|
40
51
|
- lib/x/oauth_authenticator.rb
|
41
52
|
- lib/x/redirect_handler.rb
|
42
53
|
- lib/x/request_builder.rb
|
43
|
-
- lib/x/
|
54
|
+
- lib/x/response_parser.rb
|
44
55
|
- lib/x/version.rb
|
45
56
|
- sig/x.rbs
|
46
57
|
homepage: https://sferik.github.io/x-ruby
|
@@ -69,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
80
|
- !ruby/object:Gem::Version
|
70
81
|
version: '0'
|
71
82
|
requirements: []
|
72
|
-
rubygems_version: 3.4.
|
83
|
+
rubygems_version: 3.4.21
|
73
84
|
signing_key:
|
74
85
|
specification_version: 4
|
75
86
|
summary: A Ruby interface to the X API.
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require_relative "client_error"
|
2
|
-
|
3
|
-
module X
|
4
|
-
# Rate limit error
|
5
|
-
class TooManyRequestsError < ClientError
|
6
|
-
def initialize(msg, response:)
|
7
|
-
@response = response
|
8
|
-
super
|
9
|
-
end
|
10
|
-
|
11
|
-
def limit
|
12
|
-
@response.fetch("x-rate-limit-limit", 0).to_i
|
13
|
-
end
|
14
|
-
|
15
|
-
def remaining
|
16
|
-
@response.fetch("x-rate-limit-remaining", 0).to_i
|
17
|
-
end
|
18
|
-
|
19
|
-
def reset_at
|
20
|
-
Time.at(@response.fetch("x-rate-limit-reset", 0).to_i).utc
|
21
|
-
end
|
22
|
-
|
23
|
-
def reset_in
|
24
|
-
[(reset_at - Time.now).ceil, 0].max if reset_at
|
25
|
-
end
|
26
|
-
|
27
|
-
alias_method :retry_after, :reset_in
|
28
|
-
end
|
29
|
-
end
|
data/lib/x/response_handler.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require "json"
|
2
|
-
require "net/http"
|
3
|
-
require_relative "errors/bad_request_error"
|
4
|
-
require_relative "errors/authentication_error"
|
5
|
-
require_relative "errors/forbidden_error"
|
6
|
-
require_relative "errors/not_found_error"
|
7
|
-
require_relative "errors/too_many_requests_error"
|
8
|
-
require_relative "errors/server_error"
|
9
|
-
require_relative "errors/service_unavailable_error"
|
10
|
-
|
11
|
-
module X
|
12
|
-
# Process HTTP responses
|
13
|
-
class ResponseHandler
|
14
|
-
DEFAULT_ARRAY_CLASS = Array
|
15
|
-
DEFAULT_OBJECT_CLASS = Hash
|
16
|
-
ERROR_CLASSES = {
|
17
|
-
400 => BadRequestError,
|
18
|
-
401 => AuthenticationError,
|
19
|
-
403 => ForbiddenError,
|
20
|
-
404 => NotFoundError,
|
21
|
-
429 => TooManyRequestsError,
|
22
|
-
500 => ServerError,
|
23
|
-
503 => ServiceUnavailableError
|
24
|
-
}.freeze
|
25
|
-
JSON_CONTENT_TYPE_REGEXP = %r{application/(problem\+|)json}
|
26
|
-
|
27
|
-
attr_accessor :array_class, :object_class
|
28
|
-
|
29
|
-
def initialize(array_class: DEFAULT_ARRAY_CLASS, object_class: DEFAULT_OBJECT_CLASS)
|
30
|
-
@array_class = array_class
|
31
|
-
@object_class = object_class
|
32
|
-
end
|
33
|
-
|
34
|
-
def handle(response)
|
35
|
-
if success?(response)
|
36
|
-
JSON.parse(response.body, array_class: array_class, object_class: object_class) if json?(response)
|
37
|
-
else
|
38
|
-
error_class = ERROR_CLASSES[response.code.to_i] || Error
|
39
|
-
error_message = "#{response.code} #{response.message}"
|
40
|
-
raise error_class.new(error_message, response: response)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
def success?(response)
|
47
|
-
response.is_a?(Net::HTTPSuccess)
|
48
|
-
end
|
49
|
-
|
50
|
-
def json?(response)
|
51
|
-
response.body && JSON_CONTENT_TYPE_REGEXP.match?(response["content-type"])
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|