x 0.9.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -27
  3. data/README.md +6 -2
  4. data/lib/x/authenticator.rb +8 -0
  5. data/lib/x/bearer_token_authenticator.rb +5 -3
  6. data/lib/x/cgi.rb +15 -0
  7. data/lib/x/client.rb +40 -37
  8. data/lib/x/connection.rb +42 -65
  9. data/lib/x/errors/bad_gateway.rb +5 -0
  10. data/lib/x/errors/{not_found_error.rb → bad_request.rb} +1 -1
  11. data/lib/x/errors/connection_exception.rb +5 -0
  12. data/lib/x/errors/error.rb +1 -9
  13. data/lib/x/errors/{forbidden_error.rb → forbidden.rb} +1 -1
  14. data/lib/x/errors/gateway_timeout.rb +5 -0
  15. data/lib/x/errors/{bad_request_error.rb → gone.rb} +1 -1
  16. data/lib/x/errors/internal_server_error.rb +5 -0
  17. data/lib/x/errors/network_error.rb +1 -1
  18. data/lib/x/errors/not_acceptable.rb +5 -0
  19. data/lib/x/errors/not_found.rb +5 -0
  20. data/lib/x/errors/payload_too_large.rb +5 -0
  21. data/lib/x/errors/service_unavailable.rb +5 -0
  22. data/lib/x/errors/too_many_redirects.rb +5 -0
  23. data/lib/x/errors/too_many_requests.rb +29 -0
  24. data/lib/x/errors/unauthorized.rb +5 -0
  25. data/lib/x/errors/unprocessable_entity.rb +5 -0
  26. data/lib/x/media_uploader.rb +122 -0
  27. data/lib/x/oauth_authenticator.rb +10 -15
  28. data/lib/x/redirect_handler.rb +26 -24
  29. data/lib/x/request_builder.rb +22 -28
  30. data/lib/x/response_parser.rb +92 -0
  31. data/lib/x/version.rb +1 -1
  32. data/sig/x.rbs +160 -71
  33. metadata +22 -11
  34. data/lib/x/errors/authentication_error.rb +0 -5
  35. data/lib/x/errors/service_unavailable_error.rb +0 -5
  36. data/lib/x/errors/too_many_redirects_error.rb +0 -5
  37. data/lib/x/errors/too_many_requests_error.rb +0 -29
  38. 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 bearer_token) -> void
7
- def header: (Net::HTTPRequest _request) -> String
10
+ def initialize: (bearer_token: String) -> void
11
+ def header: (Net::HTTPRequest? request) -> Hash[String, String]
8
12
  end
9
13
 
10
- class OauthAuthenticator
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: (String api_key, String api_key_secret, String access_token, String access_token_secret) -> void
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
- JSON_CONTENT_TYPE_REGEXP: Regexp
53
+ def initialize: (String msg, ?Net::HTTPResponse? response) -> void
54
+ end
38
55
 
39
- attr_reader object: Hash[String, untyped]
40
- def initialize: (String msg, response: Net::HTTPResponse) -> void
56
+ class Forbidden < ClientError
57
+ end
41
58
 
42
- private
43
- def json_response?: (Net::HTTPResponse response) -> bool
59
+ class GatewayTimeout < ClientError
44
60
  end
45
61
 
46
- class ClientError < Error
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 BadRequestError < ClientError
74
+ class NotFound < ClientError
50
75
  end
51
76
 
52
- class AuthenticationError < ClientError
77
+ class PayloadTooLarge < ClientError
53
78
  end
54
79
 
55
- class ForbiddenError < ClientError
80
+ class ServerError < Error
56
81
  end
57
82
 
58
- class NotFoundError < ClientError
83
+ class ServiceUnavailable < ServerError
59
84
  end
60
85
 
61
- class TooManyRedirectsError < ClientError
86
+ class TooManyRedirects < ClientError
62
87
  end
63
88
 
64
- class TooManyRequestsError < ClientError
89
+ class TooManyRequests < ClientError
65
90
  @response: Net::HTTPResponse
66
91
 
67
- def initialize: (String msg, response: Net::HTTPResponse) -> void
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 ServerError < Error
75
- end
76
-
77
- class ServiceUnavailableError < ServerError
99
+ class Unauthorized < ClientError
78
100
  end
79
101
 
80
- class NetworkError < Error
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
- NETWORK_ERRORS: Array[(singleton(::Errno::ECONNREFUSED) | singleton(::Net::OpenTimeout) | singleton(::Net::ReadTimeout))]
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
- attr_reader base_uri: URI::Generic
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 open_timeout : Float | Integer
97
- attr_reader read_timeout : Float | Integer
98
- attr_reader write_timeout : Float | Integer
99
- def initialize: (?base_url: URI::Generic | String, ?open_timeout: Float | Integer, ?read_timeout: Float | Integer, ?write_timeout: Float | Integer, ?proxy_url: URI::Generic? | String?, ?debug_output: IO?) -> void
100
- def send_request: (Net::HTTPRequest request) -> Net::HTTPResponse
101
- def base_uri=: (URI::Generic | String base_url) -> void
102
- def debug_output: -> IO?
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 apply_http_client_settings: (open_timeout: Float | Integer, read_timeout: Float | Integer, write_timeout: Float | Integer, debug_output: IO?) -> untyped
106
- def current_http_client_settings: -> {open_timeout: Float | Integer, read_timeout: Float | Integer, write_timeout: Float | Integer, debug_output: IO?}
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[::Symbol, (singleton(::Net::HTTP::Get) | singleton(::Net::HTTP::Post) | singleton(::Net::HTTP::Put) | singleton(::Net::HTTP::Delete))]
114
- DEFAULT_CONTENT_TYPE: String
115
- DEFAULT_USER_AGENT: String
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: (BearerTokenAuthenticator | OauthAuthenticator authenticator, Symbol http_method, URI::Generic uri, ?body: String?) -> (Net::HTTPRequest)
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 http_method, URI::Generic uri, String? body) -> (Net::HTTPRequest)
127
- def add_authorization: (Net::HTTPRequest request, BearerTokenAuthenticator | OauthAuthenticator authenticator) -> void
128
- def add_content_type: (Net::HTTPRequest request) -> void
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: BearerTokenAuthenticator | OauthAuthenticator
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: (BearerTokenAuthenticator | OauthAuthenticator authenticator, Connection connection, RequestBuilder request_builder, ?max_redirects: Integer) -> void
141
- def handle_redirects: (Net::HTTPResponse response, Net::HTTPRequest original_request, URI::Generic | String original_base_url, ?Integer redirect_count) -> Net::HTTPResponse
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, URI::Generic | String original_base_url) -> URI::Generic
145
- def build_request: (Net::HTTPRequest original_request, URI::Generic new_uri) -> 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 ResponseHandler
166
+ class ResponseParser
150
167
  DEFAULT_ARRAY_CLASS: Class
151
168
  DEFAULT_OBJECT_CLASS: Class
152
- ERROR_CLASSES: Hash[Integer, singleton(AuthenticationError) | singleton(BadRequestError) | singleton(ForbiddenError) | singleton(NotFoundError) | singleton(ServerError) | singleton(ServiceUnavailableError) | singleton(TooManyRequestsError)]
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 handle: (Net::HTTPResponse response) -> Hash[String, untyped]?
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: BearerTokenAuthenticator | OauthAuthenticator
190
+ @authenticator: Authenticator
168
191
  @connection: Connection
169
192
  @request_builder: RequestBuilder
170
193
  @redirect_handler: RedirectHandler
171
- @response_handler: ResponseHandler
194
+ @response_parser: ResponseParser
172
195
 
173
- attr_reader base_uri: URI::Generic
174
- def initialize: (?bearer_token: String?, ?api_key: String?, ?api_key_secret: String?, ?access_token: String?, ?access_token_secret: String?, ?base_url: URI::Generic | String, ?content_type: String, ?user_agent: 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
175
- def get: (String endpoint) -> Hash[String, untyped]?
176
- def post: (String endpoint, ?nil body) -> Hash[String, untyped]?
177
- def put: (String endpoint, ?nil body) -> Hash[String, untyped]?
178
- def delete: (String endpoint) -> Hash[String, untyped]?
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 initialize_authenticator: (String? bearer_token, String? api_key, String? api_key_secret, String? access_token, String? access_token_secret) -> (BearerTokenAuthenticator | OauthAuthenticator)
182
- def send_request: (Symbol http_method, String endpoint, ?nil body) -> Hash[String, untyped]?
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.9.1
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-06 00:00:00.000000000 Z
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/authentication_error.rb
30
- - lib/x/errors/bad_request_error.rb
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/forbidden_error.rb
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/not_found_error.rb
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/service_unavailable_error.rb
38
- - lib/x/errors/too_many_redirects_error.rb
39
- - lib/x/errors/too_many_requests_error.rb
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/response_handler.rb
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.20
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,5 +0,0 @@
1
- require_relative "client_error"
2
-
3
- module X
4
- class AuthenticationError < ClientError; end
5
- end
@@ -1,5 +0,0 @@
1
- require_relative "server_error"
2
-
3
- module X
4
- class ServiceUnavailableError < ServerError; end
5
- end
@@ -1,5 +0,0 @@
1
- require_relative "client_error"
2
-
3
- module X
4
- class TooManyRedirectsError < ClientError; end
5
- end
@@ -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
@@ -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