x 0.1.0 → 0.2.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/.rubocop.yml +3 -3
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -0
- data/README.md +9 -6
- data/lib/x/client.rb +159 -60
- data/lib/x/errors.rb +11 -0
- data/lib/x/version.rb +1 -1
- data/lib/x.rb +1 -1
- metadata +2 -2
- data/lib/x/error.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c40d2b65cf1479d65e6f434d6d9c98cb32ad7aa62b739fd1207b491b7e276e4d
|
4
|
+
data.tar.gz: 6dee4de59342deb6bbc8a5897f7a96e18ae6b7a856083ae84e1ee26580ce7482
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d64f01c2f011e53621214597fd1a9ac80e777ce22db2eb5d48c6b2f760743efa2fa3aa6848e6549b3fc25290c80456873262ddf92dbffaff2d134040cb87555f
|
7
|
+
data.tar.gz: 8fc7d2aca33c67534ac775cc97f6afce95ef035716c5799e3571fb7b3a0218fd5b4646b41d8c66f61e3bba1d58f22b6c56c67ca273199b99dd7c55829827215a
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -15,17 +15,20 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
15
15
|
## Usage
|
16
16
|
|
17
17
|
```ruby
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
x_api_key = "YOUR_X_API_KEY"
|
19
|
+
x_api_key_secret = "YOUR_X_API_KEY_SECRET"
|
20
|
+
x_access_token = "YOUR_X_ACCESS_TOKEN"
|
21
|
+
x_access_token_secret = "YOUR_X_ACCESS_TOKEN_SECRET"
|
22
22
|
|
23
|
-
x_client = X::Client.new(api_key:
|
23
|
+
x_client = X::Client.new(api_key: x_api_key,
|
24
|
+
api_key_secret: x_api_key_secret,
|
25
|
+
access_token: x_access_token,
|
26
|
+
access_token_secret: x_access_token_secret)
|
24
27
|
|
25
28
|
begin
|
26
29
|
response = x_client.get("users/me")
|
27
30
|
puts JSON.pretty_generate(response)
|
28
|
-
rescue
|
31
|
+
rescue X::Error => e
|
29
32
|
puts "Error: #{e.message}"
|
30
33
|
end
|
31
34
|
```
|
data/lib/x/client.rb
CHANGED
@@ -1,94 +1,193 @@
|
|
1
|
-
require "oauth"
|
2
1
|
require "json"
|
3
2
|
require "net/http"
|
3
|
+
require "oauth"
|
4
4
|
|
5
5
|
module X
|
6
|
-
#
|
6
|
+
# HTTP client that handles authentication and requests
|
7
7
|
class Client
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@bearer_token = bearer_token
|
21
|
-
else
|
22
|
-
unless api_key && api_key_secret && access_token && access_token_secret
|
23
|
-
raise ArgumentError, "Missing OAuth credentials."
|
24
|
-
end
|
25
|
-
|
26
|
-
@consumer = OAuth::Consumer.new(api_key, api_key_secret, site: BASE_URL)
|
27
|
-
@access_token = OAuth::Token.new(access_token, access_token_secret)
|
28
|
-
end
|
8
|
+
DEFAULT_BASE_URL = "https://api.twitter.com/2/".freeze
|
9
|
+
DEFAULT_USER_AGENT = "X-Client/#{VERSION} Ruby/#{RUBY_VERSION}".freeze
|
10
|
+
|
11
|
+
def initialize(bearer_token: nil, api_key: nil, api_key_secret: nil, access_token: nil, access_token_secret: nil,
|
12
|
+
base_url: DEFAULT_BASE_URL, user_agent: DEFAULT_USER_AGENT)
|
13
|
+
@http_request = HttpRequest.new(bearer_token: bearer_token,
|
14
|
+
api_key: api_key,
|
15
|
+
api_key_secret: api_key_secret,
|
16
|
+
access_token: access_token,
|
17
|
+
access_token_secret: access_token_secret,
|
18
|
+
base_url: base_url,
|
19
|
+
user_agent: user_agent)
|
29
20
|
end
|
30
21
|
|
31
22
|
def get(endpoint)
|
32
|
-
|
33
|
-
handle_response(response)
|
23
|
+
handle_response { @http_request.get(endpoint) }
|
34
24
|
end
|
35
25
|
|
36
26
|
def post(endpoint, body = nil)
|
37
|
-
|
38
|
-
handle_response(response)
|
27
|
+
handle_response { @http_request.post(endpoint, body) }
|
39
28
|
end
|
40
29
|
|
41
30
|
def put(endpoint, body = nil)
|
42
|
-
|
43
|
-
handle_response(response)
|
31
|
+
handle_response { @http_request.put(endpoint, body) }
|
44
32
|
end
|
45
33
|
|
46
34
|
def delete(endpoint)
|
47
|
-
|
48
|
-
handle_response(response)
|
35
|
+
handle_response { @http_request.delete(endpoint) }
|
49
36
|
end
|
50
37
|
|
51
38
|
private
|
52
39
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
|
40
|
+
def handle_response
|
41
|
+
response = yield
|
42
|
+
ErrorHandler.new(response).handle
|
43
|
+
end
|
57
44
|
|
58
|
-
|
59
|
-
|
45
|
+
# HTTP client requester
|
46
|
+
class HttpRequest
|
47
|
+
HTTP_METHODS = {
|
48
|
+
get: Net::HTTP::Get,
|
49
|
+
post: Net::HTTP::Post,
|
50
|
+
put: Net::HTTP::Put,
|
51
|
+
delete: Net::HTTP::Delete
|
52
|
+
}.freeze
|
53
|
+
|
54
|
+
def initialize(bearer_token: nil, api_key: nil, api_key_secret: nil, access_token: nil, access_token_secret: nil,
|
55
|
+
base_url: nil, user_agent: nil)
|
56
|
+
@base_url = base_url
|
57
|
+
@use_bearer_token = !bearer_token.nil?
|
58
|
+
@user_agent = user_agent || Client::DEFAULT_USER_AGENT
|
59
|
+
|
60
|
+
if @use_bearer_token
|
61
|
+
@bearer_token = bearer_token
|
62
|
+
else
|
63
|
+
initialize_oauth(api_key, api_key_secret, access_token, access_token_secret)
|
64
|
+
end
|
65
|
+
end
|
60
66
|
|
61
|
-
|
62
|
-
|
67
|
+
def get(endpoint)
|
68
|
+
send_request(:get, endpoint)
|
69
|
+
end
|
63
70
|
|
64
|
-
|
65
|
-
|
71
|
+
def post(endpoint, body = nil)
|
72
|
+
send_request(:post, endpoint, body)
|
73
|
+
end
|
66
74
|
|
67
|
-
|
75
|
+
def put(endpoint, body = nil)
|
76
|
+
send_request(:put, endpoint, body)
|
77
|
+
end
|
68
78
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
79
|
+
def delete(endpoint)
|
80
|
+
send_request(:delete, endpoint)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def initialize_oauth(api_key, api_key_secret, access_token, access_token_secret)
|
86
|
+
unless api_key && api_key_secret && access_token && access_token_secret
|
87
|
+
raise ArgumentError, "Missing OAuth credentials."
|
88
|
+
end
|
89
|
+
|
90
|
+
@consumer = OAuth::Consumer.new(api_key, api_key_secret, site: @base_url)
|
91
|
+
@access_token = OAuth::Token.new(access_token, access_token_secret)
|
92
|
+
end
|
93
|
+
|
94
|
+
def send_request(http_method, endpoint, body = nil)
|
95
|
+
url = URI.parse(@base_url + endpoint)
|
96
|
+
http = Net::HTTP.new(url.host, url.port)
|
97
|
+
http.use_ssl = true
|
98
|
+
|
99
|
+
request = create_request(http_method, url, body)
|
100
|
+
add_authorization(request)
|
101
|
+
add_user_agent(request)
|
102
|
+
|
103
|
+
http.request(request)
|
104
|
+
end
|
73
105
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
106
|
+
def create_request(http_method, url, body)
|
107
|
+
http_method_class = HTTP_METHODS[http_method]
|
108
|
+
|
109
|
+
raise ArgumentError, "Unsupported HTTP method: #{http_method}" unless http_method_class
|
110
|
+
|
111
|
+
request = http_method_class.new(url)
|
112
|
+
request.body = body if body && http_method != :get
|
113
|
+
request
|
114
|
+
end
|
115
|
+
|
116
|
+
def add_authorization(request)
|
117
|
+
if @use_bearer_token
|
118
|
+
request["Authorization"] = "Bearer #{@bearer_token}"
|
119
|
+
else
|
120
|
+
@consumer.sign!(request, @access_token)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_user_agent(request)
|
125
|
+
request["User-Agent"] = @user_agent if @user_agent
|
79
126
|
end
|
80
127
|
end
|
81
128
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
129
|
+
# HTTP client error handler
|
130
|
+
class ErrorHandler
|
131
|
+
HTTP_STATUS_HANDLERS = {
|
132
|
+
Net::HTTPOK => :handle_success_response,
|
133
|
+
Net::HTTPBadRequest => :handle_bad_request_response,
|
134
|
+
Net::HTTPForbidden => :handle_forbidden_response,
|
135
|
+
Net::HTTPUnauthorized => :handle_unauthorized_response,
|
136
|
+
Net::HTTPNotFound => :handle_not_found_response,
|
137
|
+
Net::HTTPTooManyRequests => :handle_too_many_requests_response,
|
138
|
+
Net::HTTPInternalServerError => :handle_server_error_response,
|
139
|
+
Net::HTTPServiceUnavailable => :handle_service_unavailable_response
|
140
|
+
}.freeze
|
141
|
+
|
142
|
+
def initialize(response)
|
143
|
+
@response = response
|
144
|
+
end
|
145
|
+
|
146
|
+
def handle
|
147
|
+
handler_method = HTTP_STATUS_HANDLERS[@response.class]
|
148
|
+
if handler_method
|
149
|
+
send(handler_method)
|
150
|
+
else
|
151
|
+
handle_unexpected_response
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def handle_success_response
|
158
|
+
JSON.parse(@response.body)
|
159
|
+
end
|
160
|
+
|
161
|
+
def handle_bad_request_response
|
162
|
+
raise X::BadRequestError, "Bad request: #{@response.code} #{@response.message}"
|
163
|
+
end
|
164
|
+
|
165
|
+
def handle_forbidden_response
|
166
|
+
raise X::ForbiddenError, "Forbidden: #{@response.code} #{@response.message}"
|
167
|
+
end
|
168
|
+
|
169
|
+
def handle_unauthorized_response
|
87
170
|
raise X::AuthenticationError, "Authentication failed. Please check your credentials."
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
raise X::
|
171
|
+
end
|
172
|
+
|
173
|
+
def handle_not_found_response
|
174
|
+
raise X::NotFoundError, "Not found: #{@response.code} #{@response.message}"
|
175
|
+
end
|
176
|
+
|
177
|
+
def handle_too_many_requests_response
|
178
|
+
raise X::TooManyRequestsError, "Too many requests: #{@response.code} #{@response.message}"
|
179
|
+
end
|
180
|
+
|
181
|
+
def handle_server_error_response
|
182
|
+
raise X::ServerError, "Internal server error: #{@response.code} #{@response.message}"
|
183
|
+
end
|
184
|
+
|
185
|
+
def handle_service_unavailable_response
|
186
|
+
raise X::ServiceUnavailableError, "Service unavailable: #{@response.code} #{@response.message}"
|
187
|
+
end
|
188
|
+
|
189
|
+
def handle_unexpected_response
|
190
|
+
raise X::Error, "Unexpected response: #{@response.code}"
|
92
191
|
end
|
93
192
|
end
|
94
193
|
end
|
data/lib/x/errors.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module X
|
2
|
+
class Error < ::StandardError; end
|
3
|
+
class ClientError < Error; end
|
4
|
+
class AuthenticationError < ClientError; end
|
5
|
+
class BadRequestError < ClientError; end
|
6
|
+
class ForbiddenError < ClientError; end
|
7
|
+
class NotFoundError < ClientError; end
|
8
|
+
class TooManyRequestsError < ClientError; end
|
9
|
+
class ServerError < Error; end
|
10
|
+
class ServiceUnavailableError < ServerError; end
|
11
|
+
end
|
data/lib/x/version.rb
CHANGED
data/lib/x.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: x
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Erik Berlin
|
@@ -39,7 +39,7 @@ files:
|
|
39
39
|
- Rakefile
|
40
40
|
- lib/x.rb
|
41
41
|
- lib/x/client.rb
|
42
|
-
- lib/x/
|
42
|
+
- lib/x/errors.rb
|
43
43
|
- lib/x/version.rb
|
44
44
|
- sig/x.rbs
|
45
45
|
homepage: https://github.com/sferik/x-ruby
|