x 0.19.0 → 1.0.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +9 -0
  3. data/CHANGELOG.md +648 -15
  4. data/README.md +506 -73
  5. data/SECURITY.md +66 -0
  6. data/UPGRADING.md +670 -0
  7. data/lib/x/version.rb +16 -1
  8. data/lib/x.rb +13 -1
  9. data/sig/manifest.yaml +5 -0
  10. data/sig/x.rbs +5 -361
  11. metadata +57 -49
  12. data/bin/console +0 -10
  13. data/bin/setup +0 -6
  14. data/lib/x/account_uploader.rb +0 -168
  15. data/lib/x/authenticator.rb +0 -21
  16. data/lib/x/bearer_token_authenticator.rb +0 -36
  17. data/lib/x/client.rb +0 -191
  18. data/lib/x/client_credentials.rb +0 -208
  19. data/lib/x/connection.rb +0 -183
  20. data/lib/x/errors/bad_gateway.rb +0 -6
  21. data/lib/x/errors/bad_request.rb +0 -6
  22. data/lib/x/errors/client_error.rb +0 -6
  23. data/lib/x/errors/connection_exception.rb +0 -6
  24. data/lib/x/errors/error.rb +0 -4
  25. data/lib/x/errors/forbidden.rb +0 -6
  26. data/lib/x/errors/gateway_timeout.rb +0 -6
  27. data/lib/x/errors/gone.rb +0 -6
  28. data/lib/x/errors/http_error.rb +0 -84
  29. data/lib/x/errors/internal_server_error.rb +0 -6
  30. data/lib/x/errors/invalid_media_type.rb +0 -6
  31. data/lib/x/errors/network_error.rb +0 -6
  32. data/lib/x/errors/not_acceptable.rb +0 -6
  33. data/lib/x/errors/not_found.rb +0 -6
  34. data/lib/x/errors/payload_too_large.rb +0 -6
  35. data/lib/x/errors/server_error.rb +0 -6
  36. data/lib/x/errors/service_unavailable.rb +0 -6
  37. data/lib/x/errors/too_many_redirects.rb +0 -6
  38. data/lib/x/errors/too_many_requests.rb +0 -58
  39. data/lib/x/errors/unauthorized.rb +0 -6
  40. data/lib/x/errors/unprocessable_entity.rb +0 -6
  41. data/lib/x/media_upload_validator.rb +0 -36
  42. data/lib/x/media_uploader.rb +0 -234
  43. data/lib/x/oauth2_authenticator.rb +0 -169
  44. data/lib/x/oauth_authenticator.rb +0 -182
  45. data/lib/x/rate_limit.rb +0 -89
  46. data/lib/x/redirect_handler.rb +0 -109
  47. data/lib/x/request_builder.rb +0 -93
  48. data/lib/x/response_parser.rb +0 -81
  49. data/lib/x/stream_parser.rb +0 -75
@@ -1,168 +0,0 @@
1
- require "base64"
2
- require "securerandom"
3
- require_relative "errors/invalid_media_type"
4
-
5
- module X
6
- # Uploads profile images and banners to the X API v1.1
7
- # @api public
8
- module AccountUploader
9
- extend self
10
-
11
- # Base URL for X API v1.1 account endpoints
12
- V1_BASE_URL = "https://api.x.com/1.1/".freeze
13
- # Supported image extensions for profile uploads
14
- SUPPORTED_EXTENSIONS = %w[gif jpg jpeg png].freeze
15
- # Mapping of file extensions to MIME types
16
- MIME_TYPE_MAP = {"gif" => "image/gif", "jpg" => "image/jpeg", "jpeg" => "image/jpeg", "png" => "image/png"}.freeze
17
-
18
- # Update the authenticating user's profile image
19
- #
20
- # @api public
21
- # @param client [Client] the X API client
22
- # @param file_path [String] the path to the image file
23
- # @param boundary [String] the multipart boundary
24
- # @return [Hash, nil] the updated user object
25
- # @raise [RuntimeError] if the file does not exist
26
- # @raise [InvalidMediaType] if the file type is not supported
27
- # @example Update profile image from a file
28
- # AccountUploader.update_profile_image(client: client, file_path: "avatar.png")
29
- def update_profile_image(client:, file_path:, boundary: SecureRandom.hex)
30
- validate_file!(file_path)
31
- upload_profile_image_binary(client:, content: File.binread(file_path), boundary:)
32
- end
33
-
34
- # Update the authenticating user's profile image from binary content
35
- #
36
- # @api public
37
- # @param client [Client] the X API client
38
- # @param content [String] the binary image content
39
- # @param boundary [String] the multipart boundary
40
- # @return [Hash, nil] the updated user object
41
- # @example Update profile image from binary content
42
- # AccountUploader.upload_profile_image_binary(client: client, content: image_data)
43
- def upload_profile_image_binary(client:, content:, boundary: SecureRandom.hex)
44
- body = construct_multipart_body(field_name: "image", content:, boundary:)
45
- headers = {"Content-Type" => "multipart/form-data; boundary=#{boundary}"}
46
- v1_client(client).post("account/update_profile_image.json", body, headers:)
47
- end
48
-
49
- # Update the authenticating user's profile banner
50
- #
51
- # @api public
52
- # @param client [Client] the X API client
53
- # @param file_path [String] the path to the image file
54
- # @param width [Integer, nil] the width of the banner
55
- # @param height [Integer, nil] the height of the banner
56
- # @param offset_left [Integer, nil] the left offset of the banner
57
- # @param offset_top [Integer, nil] the top offset of the banner
58
- # @param boundary [String] the multipart boundary
59
- # @return [Hash, nil] nil on success (204 No Content)
60
- # @raise [RuntimeError] if the file does not exist
61
- # @raise [InvalidMediaType] if the file type is not supported
62
- # @example Update profile banner from a file
63
- # AccountUploader.update_profile_banner(client: client, file_path: "banner.png")
64
- # @example Update profile banner with dimensions
65
- # AccountUploader.update_profile_banner(client: client, file_path: "banner.png", width: 1500, height: 500)
66
- def update_profile_banner(client:, file_path:, width: nil, height: nil, offset_left: nil, offset_top: nil,
67
- boundary: SecureRandom.hex)
68
- validate_file!(file_path)
69
- upload_profile_banner_binary(client:, content: File.binread(file_path), width:, height:, offset_left:,
70
- offset_top:, boundary:)
71
- end
72
-
73
- # Update the authenticating user's profile banner from binary content
74
- #
75
- # @api public
76
- # @param client [Client] the X API client
77
- # @param content [String] the binary image content
78
- # @param width [Integer, nil] the width of the banner
79
- # @param height [Integer, nil] the height of the banner
80
- # @param offset_left [Integer, nil] the left offset of the banner
81
- # @param offset_top [Integer, nil] the top offset of the banner
82
- # @param boundary [String] the multipart boundary
83
- # @return [Hash, nil] nil on success (204 No Content)
84
- # @example Update profile banner from binary content
85
- # AccountUploader.upload_profile_banner_binary(client: client, content: image_data)
86
- def upload_profile_banner_binary(client:, content:, width: nil, height: nil, offset_left: nil, offset_top: nil,
87
- boundary: SecureRandom.hex)
88
- body = construct_banner_body(content:, width:, height:, offset_left:, offset_top:, boundary:)
89
- headers = {"Content-Type" => "multipart/form-data; boundary=#{boundary}"}
90
- v1_client(client).post("account/update_profile_banner.json", body, headers:)
91
- end
92
-
93
- private
94
-
95
- # Create a v1.1 API client from an existing client
96
- # @api private
97
- # @param client [Client] the original client
98
- # @return [Client] a client configured for v1.1 API
99
- def v1_client(client)
100
- Client.new(
101
- api_key: client.api_key,
102
- api_key_secret: client.api_key_secret,
103
- access_token: client.access_token,
104
- access_token_secret: client.access_token_secret,
105
- base_url: V1_BASE_URL
106
- )
107
- end
108
-
109
- # Validate that the file exists and has a supported extension
110
- # @api private
111
- # @param file_path [String] the file path
112
- # @return [nil]
113
- # @raise [RuntimeError] if the file does not exist
114
- # @raise [InvalidMediaType] if the file type is not supported
115
- def validate_file!(file_path)
116
- raise "File not found: #{file_path}" unless File.exist?(file_path)
117
-
118
- extension = File.extname(file_path).delete(".").downcase
119
- return if SUPPORTED_EXTENSIONS.include?(extension)
120
-
121
- raise InvalidMediaType, "Unsupported file type: #{extension}. Supported types: #{SUPPORTED_EXTENSIONS.join(", ")}"
122
- end
123
-
124
- # Construct multipart body for profile image upload
125
- # @api private
126
- # @param field_name [String] the form field name
127
- # @param content [String] the binary content
128
- # @param boundary [String] the multipart boundary
129
- # @return [String] the multipart body
130
- def construct_multipart_body(field_name:, content:, boundary:)
131
- "--#{boundary}\r\n" \
132
- "Content-Disposition: form-data; name=\"#{field_name}\"\r\n" \
133
- "Content-Type: application/octet-stream\r\n\r\n" \
134
- "#{content}\r\n" \
135
- "--#{boundary}--\r\n"
136
- end
137
-
138
- # Construct multipart body for profile banner upload with optional dimensions
139
- # @api private
140
- # @param content [String] the binary content
141
- # @param width [Integer, nil] the width
142
- # @param height [Integer, nil] the height
143
- # @param offset_left [Integer, nil] the left offset
144
- # @param offset_top [Integer, nil] the top offset
145
- # @param boundary [String] the multipart boundary
146
- # @return [String] the multipart body
147
- def construct_banner_body(content:, width:, height:, offset_left:, offset_top:, boundary:)
148
- body = ""
149
- body += multipart_field("width", width, boundary) if width
150
- body += multipart_field("height", height, boundary) if height
151
- body += multipart_field("offset_left", offset_left, boundary) if offset_left
152
- body += multipart_field("offset_top", offset_top, boundary) if offset_top
153
- body + construct_multipart_body(field_name: "banner", content:, boundary:)
154
- end
155
-
156
- # Create a multipart form field
157
- # @api private
158
- # @param name [String] the field name
159
- # @param value [Object] the field value
160
- # @param boundary [String] the multipart boundary
161
- # @return [String] the multipart field
162
- def multipart_field(name, value, boundary)
163
- "--#{boundary}\r\n" \
164
- "Content-Disposition: form-data; name=\"#{name}\"\r\n\r\n" \
165
- "#{value}\r\n"
166
- end
167
- end
168
- end
@@ -1,21 +0,0 @@
1
- # A Ruby client for the X API
2
- module X
3
- # Base class for authentication
4
- # @api public
5
- class Authenticator
6
- # The HTTP header name for authentication
7
- AUTHENTICATION_HEADER = "Authorization".freeze
8
-
9
- # Generate the authentication header for a request
10
- #
11
- # @api public
12
- # @param _request [Net::HTTPRequest] the HTTP request
13
- # @return [Hash{String => String}] the authentication header
14
- # @example Generate an empty authentication header
15
- # authenticator = X::Authenticator.new
16
- # authenticator.header(request)
17
- def header(_request)
18
- {AUTHENTICATION_HEADER => ""}
19
- end
20
- end
21
- end
@@ -1,36 +0,0 @@
1
- require_relative "authenticator"
2
-
3
- module X
4
- # Authenticator for Bearer token authentication
5
- # @api public
6
- class BearerTokenAuthenticator < Authenticator
7
- # The bearer token for authentication
8
- # @api public
9
- # @return [String] the bearer token
10
- # @example Get the bearer token
11
- # authenticator.bearer_token
12
- attr_accessor :bearer_token
13
-
14
- # Initialize a new BearerTokenAuthenticator
15
- #
16
- # @api public
17
- # @param bearer_token [String] the bearer token for authentication
18
- # @return [BearerTokenAuthenticator] a new instance
19
- # @example Create a new bearer token authenticator
20
- # authenticator = X::BearerTokenAuthenticator.new(bearer_token: "token")
21
- def initialize(bearer_token:)
22
- @bearer_token = bearer_token
23
- end
24
-
25
- # Generate the authentication header for a request
26
- #
27
- # @api public
28
- # @param _request [Net::HTTPRequest] the HTTP request
29
- # @return [Hash{String => String}] the authentication header with bearer token
30
- # @example Generate a bearer authentication header
31
- # authenticator.header(request)
32
- def header(_request)
33
- {AUTHENTICATION_HEADER => "Bearer #{bearer_token}"}
34
- end
35
- end
36
- end
data/lib/x/client.rb DELETED
@@ -1,191 +0,0 @@
1
- require "forwardable"
2
- require_relative "authenticator"
3
- require_relative "bearer_token_authenticator"
4
- require_relative "client_credentials"
5
- require_relative "connection"
6
- require_relative "oauth_authenticator"
7
- require_relative "oauth2_authenticator"
8
- require_relative "redirect_handler"
9
- require_relative "request_builder"
10
- require_relative "response_parser"
11
- require_relative "stream_parser"
12
-
13
- module X
14
- # A client for interacting with the X API
15
- # @api public
16
- class Client
17
- extend Forwardable
18
- include ClientCredentials
19
-
20
- # Default base URL for the X API
21
- DEFAULT_BASE_URL = "https://api.twitter.com/2/".freeze
22
- # Default class for parsing JSON arrays
23
- DEFAULT_ARRAY_CLASS = Array
24
- # Default class for parsing JSON objects
25
- DEFAULT_OBJECT_CLASS = Hash
26
-
27
- # The base URL for API requests
28
- # @api public
29
- # @return [String] the base URL for API requests
30
- # @example Get or set the base URL
31
- # client.base_url = "https://api.twitter.com/1.1/"
32
- attr_accessor :base_url
33
-
34
- # The default class for parsing JSON arrays
35
- # @api public
36
- # @return [Class] the default class for parsing JSON arrays
37
- # @example Get or set the default array class
38
- # client.default_array_class = Set
39
- attr_accessor :default_array_class
40
-
41
- # The default class for parsing JSON objects
42
- # @api public
43
- # @return [Class] the default class for parsing JSON objects
44
- # @example Get or set the default object class
45
- # client.default_object_class = OpenStruct
46
- attr_accessor :default_object_class
47
-
48
- # The authenticator for API requests
49
- # @api public
50
- # @return [Authenticator] the authenticator instance
51
- # @example Check if the OAuth 2.0 token has expired
52
- # client.authenticator.token_expired?
53
- attr_reader :authenticator
54
-
55
- def_delegators :@connection, :open_timeout, :read_timeout, :write_timeout, :proxy_url, :debug_output
56
- def_delegators :@connection, :open_timeout=, :read_timeout=, :write_timeout=, :proxy_url=, :debug_output=
57
- def_delegators :@redirect_handler, :max_redirects
58
- def_delegators :@redirect_handler, :max_redirects=
59
-
60
- # Initialize a new X API client
61
- #
62
- # @api public
63
- # @param api_key [String, nil] the API key for OAuth 1.0a authentication
64
- # @param api_key_secret [String, nil] the API key secret for OAuth 1.0a authentication
65
- # @param access_token [String, nil] the access token for OAuth authentication
66
- # @param access_token_secret [String, nil] the access token secret for OAuth 1.0a authentication
67
- # @param bearer_token [String, nil] the bearer token for authentication
68
- # @param client_id [String, nil] the OAuth 2.0 client ID
69
- # @param client_secret [String, nil] the OAuth 2.0 client secret
70
- # @param refresh_token [String, nil] the OAuth 2.0 refresh token
71
- # @param base_url [String] the base URL for API requests
72
- # @param open_timeout [Integer] the timeout for opening connections in seconds
73
- # @param read_timeout [Integer] the timeout for reading responses in seconds
74
- # @param write_timeout [Integer] the timeout for writing requests in seconds
75
- # @param debug_output [IO] the IO object for debug output
76
- # @param proxy_url [String, nil] the proxy URL for requests
77
- # @param default_array_class [Class] the default class for parsing JSON arrays
78
- # @param default_object_class [Class] the default class for parsing JSON objects
79
- # @param max_redirects [Integer] the maximum number of redirects to follow
80
- # @return [Client] a new client instance
81
- # @example Create a client with bearer token authentication
82
- # client = X::Client.new(bearer_token: "your_bearer_token")
83
- # @example Create a client with OAuth 1.0a authentication
84
- # client = X::Client.new(api_key: "key", api_key_secret: "secret", access_token: "token", access_token_secret: "token_secret")
85
- def initialize(api_key: nil, api_key_secret: nil, access_token: nil, access_token_secret: nil,
86
- bearer_token: nil, client_id: nil, client_secret: nil, refresh_token: nil,
87
- base_url: DEFAULT_BASE_URL,
88
- open_timeout: Connection::DEFAULT_OPEN_TIMEOUT,
89
- read_timeout: Connection::DEFAULT_READ_TIMEOUT,
90
- write_timeout: Connection::DEFAULT_WRITE_TIMEOUT,
91
- debug_output: nil,
92
- proxy_url: nil,
93
- default_array_class: DEFAULT_ARRAY_CLASS,
94
- default_object_class: DEFAULT_OBJECT_CLASS,
95
- max_redirects: RedirectHandler::DEFAULT_MAX_REDIRECTS)
96
- initialize_credentials(api_key:, api_key_secret:, access_token:, access_token_secret:, bearer_token:,
97
- client_id:, client_secret:, refresh_token:)
98
- initialize_authenticator
99
- @base_url = base_url
100
- initialize_default_classes(default_array_class:, default_object_class:)
101
- @connection = Connection.new(open_timeout:, read_timeout:, write_timeout:, debug_output:, proxy_url:)
102
- @request_builder = RequestBuilder.new
103
- @redirect_handler = RedirectHandler.new(connection: @connection, request_builder: @request_builder, max_redirects:)
104
- @response_parser = ResponseParser.new
105
- @stream_parser = StreamParser.new
106
- end
107
-
108
- # Perform a GET request to the X API
109
- #
110
- # @api public
111
- # @return [Hash, Array, nil] the parsed response body
112
- # @example Get a user by username
113
- # client.get("users/by/username/sferik")
114
- def get(endpoint, headers: {}, array_class: default_array_class, object_class: default_object_class)
115
- execute_request(:get, endpoint, headers:, array_class:, object_class:)
116
- end
117
-
118
- # Perform a POST request to the X API
119
- #
120
- # @api public
121
- # @return [Hash, Array, nil] the parsed response body
122
- # @example Create a tweet
123
- # client.post("tweets", '{"text": "Hello, World!"}')
124
- def post(endpoint, body = nil, headers: {}, array_class: default_array_class, object_class: default_object_class)
125
- execute_request(:post, endpoint, body:, headers:, array_class:, object_class:)
126
- end
127
-
128
- # Perform a PUT request to the X API
129
- #
130
- # @api public
131
- # @return [Hash, Array, nil] the parsed response body
132
- # @example Update a resource
133
- # client.put("some/endpoint", '{"key": "value"}')
134
- def put(endpoint, body = nil, headers: {}, array_class: default_array_class, object_class: default_object_class)
135
- execute_request(:put, endpoint, body:, headers:, array_class:, object_class:)
136
- end
137
-
138
- # Perform a DELETE request to the X API
139
- #
140
- # @api public
141
- # @return [Hash, Array, nil] the parsed response body
142
- # @example Delete a tweet
143
- # client.delete("tweets/1234567890")
144
- def delete(endpoint, headers: {}, array_class: default_array_class, object_class: default_object_class)
145
- execute_request(:delete, endpoint, headers:, array_class:, object_class:)
146
- end
147
-
148
- # Stream data from the X API
149
- #
150
- # @api public
151
- # @param endpoint [String] the streaming API endpoint
152
- # @param headers [Hash] additional headers for the request
153
- # @param array_class [Class] the class for parsing JSON arrays
154
- # @param object_class [Class] the class for parsing JSON objects
155
- # @yield [Hash, Array] each parsed JSON object from the stream
156
- # @return [void]
157
- # @raise [HTTPError] if the response is not successful
158
- # @example Stream filtered tweets
159
- # client.stream("tweets/search/stream") { |tweet| puts tweet }
160
- def stream(endpoint, headers: {}, array_class: default_array_class, object_class: default_object_class, &block)
161
- uri = URI.join(base_url, endpoint)
162
- request = @request_builder.build(http_method: :get, uri:, headers:, authenticator:)
163
- @connection.perform_stream(request:) do |response|
164
- @stream_parser.process(response:, response_parser: @response_parser, array_class:, object_class:, &block)
165
- end
166
- end
167
-
168
- private
169
-
170
- # Initialize default JSON parsing classes
171
- # @api private
172
- # @param default_array_class [Class] the default class for parsing JSON arrays
173
- # @param default_object_class [Class] the default class for parsing JSON objects
174
- # @return [void]
175
- def initialize_default_classes(default_array_class:, default_object_class:)
176
- @default_array_class = default_array_class
177
- @default_object_class = default_object_class
178
- end
179
-
180
- # Execute an HTTP request to the X API
181
- # @api private
182
- # @return [Hash, Array, nil] the parsed response body
183
- def execute_request(http_method, endpoint, body: nil, headers: {}, array_class: default_array_class, object_class: default_object_class)
184
- uri = URI.join(base_url, endpoint)
185
- request = @request_builder.build(http_method:, uri:, body:, headers:, authenticator:)
186
- response = @connection.perform(request:)
187
- response = @redirect_handler.handle(response:, request:, base_url:, authenticator:)
188
- @response_parser.parse(response:, array_class:, object_class:)
189
- end
190
- end
191
- end
@@ -1,208 +0,0 @@
1
- module X
2
- # Mixin for client authentication credentials
3
- # @api private
4
- module ClientCredentials
5
- # The API key for OAuth 1.0a authentication
6
- # @api public
7
- # @return [String, nil] the API key for OAuth 1.0a authentication
8
- # @example Get the API key
9
- # client.api_key
10
- attr_reader :api_key
11
-
12
- # The API key secret for OAuth 1.0a authentication
13
- # @api public
14
- # @return [String, nil] the API key secret for OAuth 1.0a authentication
15
- # @example Get the API key secret
16
- # client.api_key_secret
17
- attr_reader :api_key_secret
18
-
19
- # The access token for OAuth authentication
20
- # @api public
21
- # @return [String, nil] the access token for OAuth authentication
22
- # @example Get the access token
23
- # client.access_token
24
- attr_reader :access_token
25
-
26
- # The access token secret for OAuth 1.0a authentication
27
- # @api public
28
- # @return [String, nil] the access token secret for OAuth 1.0a authentication
29
- # @example Get the access token secret
30
- # client.access_token_secret
31
- attr_reader :access_token_secret
32
-
33
- # The bearer token for authentication
34
- # @api public
35
- # @return [String, nil] the bearer token for authentication
36
- # @example Get the bearer token
37
- # client.bearer_token
38
- attr_reader :bearer_token
39
-
40
- # The OAuth 2.0 client ID
41
- # @api public
42
- # @return [String, nil] the OAuth 2.0 client ID
43
- # @example Get the client ID
44
- # client.client_id
45
- attr_reader :client_id
46
-
47
- # The OAuth 2.0 client secret
48
- # @api public
49
- # @return [String, nil] the OAuth 2.0 client secret
50
- # @example Get the client secret
51
- # client.client_secret
52
- attr_reader :client_secret
53
-
54
- # The OAuth 2.0 refresh token
55
- # @api public
56
- # @return [String, nil] the OAuth 2.0 refresh token
57
- # @example Get the refresh token
58
- # client.refresh_token
59
- attr_reader :refresh_token
60
-
61
- # Set the API key for OAuth 1.0a authentication
62
- #
63
- # @api public
64
- # @param api_key [String] the API key for OAuth 1.0a authentication
65
- # @return [void]
66
- # @example Set the API key
67
- # client.api_key = "new_key"
68
- def api_key=(api_key)
69
- @api_key = api_key
70
- initialize_authenticator
71
- end
72
-
73
- # Set the API key secret for OAuth 1.0a authentication
74
- #
75
- # @api public
76
- # @param api_key_secret [String] the API key secret for OAuth 1.0a authentication
77
- # @return [void]
78
- # @example Set the API key secret
79
- # client.api_key_secret = "new_secret"
80
- def api_key_secret=(api_key_secret)
81
- @api_key_secret = api_key_secret
82
- initialize_authenticator
83
- end
84
-
85
- # Set the access token for OAuth authentication
86
- #
87
- # @api public
88
- # @param access_token [String] the access token for OAuth authentication
89
- # @return [void]
90
- # @example Set the access token
91
- # client.access_token = "new_token"
92
- def access_token=(access_token)
93
- @access_token = access_token
94
- initialize_authenticator
95
- end
96
-
97
- # Set the access token secret for OAuth 1.0a authentication
98
- #
99
- # @api public
100
- # @param access_token_secret [String] the access token secret for OAuth 1.0a authentication
101
- # @return [void]
102
- # @example Set the access token secret
103
- # client.access_token_secret = "new_secret"
104
- def access_token_secret=(access_token_secret)
105
- @access_token_secret = access_token_secret
106
- initialize_authenticator
107
- end
108
-
109
- # Set the bearer token for authentication
110
- #
111
- # @api public
112
- # @param bearer_token [String] the bearer token for authentication
113
- # @return [void]
114
- # @example Set the bearer token
115
- # client.bearer_token = "new_token"
116
- def bearer_token=(bearer_token)
117
- @bearer_token = bearer_token
118
- initialize_authenticator
119
- end
120
-
121
- # Set the OAuth 2.0 client ID
122
- #
123
- # @api public
124
- # @param client_id [String] the OAuth 2.0 client ID
125
- # @return [void]
126
- # @example Set the client ID
127
- # client.client_id = "new_id"
128
- def client_id=(client_id)
129
- @client_id = client_id
130
- initialize_authenticator
131
- end
132
-
133
- # Set the OAuth 2.0 client secret
134
- #
135
- # @api public
136
- # @param client_secret [String] the OAuth 2.0 client secret
137
- # @return [void]
138
- # @example Set the client secret
139
- # client.client_secret = "new_secret"
140
- def client_secret=(client_secret)
141
- @client_secret = client_secret
142
- initialize_authenticator
143
- end
144
-
145
- # Set the OAuth 2.0 refresh token
146
- #
147
- # @api public
148
- # @param refresh_token [String] the OAuth 2.0 refresh token
149
- # @return [void]
150
- # @example Set the refresh token
151
- # client.refresh_token = "new_token"
152
- def refresh_token=(refresh_token)
153
- @refresh_token = refresh_token
154
- initialize_authenticator
155
- end
156
-
157
- private
158
-
159
- # Initialize credential instance variables
160
- # @api private
161
- # @return [void]
162
- def initialize_credentials(api_key:, api_key_secret:, access_token:, access_token_secret:, bearer_token:,
163
- client_id:, client_secret:, refresh_token:)
164
- @api_key = api_key
165
- @api_key_secret = api_key_secret
166
- @access_token = access_token
167
- @access_token_secret = access_token_secret
168
- @bearer_token = bearer_token
169
- @client_id = client_id
170
- @client_secret = client_secret
171
- @refresh_token = refresh_token
172
- end
173
-
174
- # Initialize the appropriate authenticator based on available credentials
175
- # @api private
176
- # @return [Authenticator] the initialized authenticator
177
- def initialize_authenticator
178
- @authenticator = oauth_authenticator || oauth2_authenticator || bearer_authenticator || @authenticator || Authenticator.new
179
- end
180
-
181
- # Build an OAuth 1.0a authenticator if credentials are available
182
- # @api private
183
- # @return [OAuthAuthenticator, nil] the OAuth authenticator or nil
184
- def oauth_authenticator
185
- return unless api_key && api_key_secret && access_token && access_token_secret
186
-
187
- OAuthAuthenticator.new(api_key:, api_key_secret:, access_token:, access_token_secret:)
188
- end
189
-
190
- # Build an OAuth 2.0 authenticator if credentials are available
191
- # @api private
192
- # @return [OAuth2Authenticator, nil] the OAuth 2.0 authenticator or nil
193
- def oauth2_authenticator
194
- return unless client_id && client_secret && access_token && refresh_token
195
-
196
- OAuth2Authenticator.new(client_id:, client_secret:, access_token:, refresh_token:)
197
- end
198
-
199
- # Build a bearer token authenticator if credentials are available
200
- # @api private
201
- # @return [BearerTokenAuthenticator, nil] the bearer token authenticator or nil
202
- def bearer_authenticator
203
- return unless bearer_token
204
-
205
- BearerTokenAuthenticator.new(bearer_token:)
206
- end
207
- end
208
- end