Skip to content

Commit

Permalink
Updates for Ruby 3.2
Browse files Browse the repository at this point in the history
  • Loading branch information
sferik committed Feb 27, 2024
1 parent 67dc80a commit 3ea2663
Show file tree
Hide file tree
Showing 25 changed files with 163 additions and 183 deletions.
49 changes: 45 additions & 4 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,53 @@ require:
- standard
- standard-performance

inherit_gem:
standard: config/base.yml

AllCops:
NewCops: enable
TargetRubyVersion: 3.0
TargetRubyVersion: 3.2

Layout/ArgumentAlignment:
EnforcedStyle: with_fixed_indentation
IndentationWidth: 2

Layout/CaseIndentation:
EnforcedStyle: end

Layout/EndAlignment:
EnforcedStyleAlignWith: start_of_line

Layout/LineLength:
Max: 140

Layout/ParameterAlignment:
EnforcedStyle: with_fixed_indentation
IndentationWidth: 2

Layout/SpaceInsideHashLiteralBraces:
EnforcedStyle: no_space

Metrics/ParameterLists:
CountKeywordArgs: false

Minitest/MultipleAssertions:
Max: 5

Style/Alias:
EnforcedStyle: prefer_alias_method

Style/Documentation:
Enabled: false

Style/FrozenStringLiteralComment:
EnforcedStyle: never

Style/OpenStructUse:
Enabled: false

Style/StringLiterals:
EnforcedStyle: double_quotes

Style/StringLiteralsInInterpolation:
EnforcedStyle: double_quotes

Style/TernaryParentheses:
EnforcedStyle: require_parentheses
4 changes: 2 additions & 2 deletions examples/chunked_media_upload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
file_path = "path/to/your/media.mp4"
media_category = "tweet_video" # other options include: tweet_image, tweet_gif, dm_image, dm_video, dm_gif, subtitles

media = X::MediaUploader.chunked_upload(client: client, file_path: file_path, media_category: media_category)
media = X::MediaUploader.chunked_upload(client:, file_path:, media_category:)

X::MediaUploader.await_processing(client: client, media: media)
X::MediaUploader.await_processing(client:, media:)

tweet_body = {text: "Posting media from @gem!", media: {media_ids: [media["media_id_string"]]}}

Expand Down
2 changes: 1 addition & 1 deletion examples/post_media_upload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
file_path = "path/to/your/media.jpg"
media_category = "tweet_image" # other options include: tweet_video, tweet_gif, dm_image, dm_video, dm_gif, subtitles

media = X::MediaUploader.upload(client: client, file_path: file_path, media_category: media_category)
media = X::MediaUploader.upload(client:, file_path:, media_category:)

tweet_body = {text: "Posting media from @gem!", media: {media_ids: [media["media_id_string"]]}}

Expand Down
14 changes: 0 additions & 14 deletions lib/x/cgi.rb

This file was deleted.

31 changes: 12 additions & 19 deletions lib/x/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,26 @@ def initialize(api_key: nil, api_key_secret: nil, access_token: nil, access_toke
initialize_authenticator
@base_url = base_url
initialize_default_classes(default_array_class, default_object_class)
@connection = Connection.new(open_timeout: open_timeout, read_timeout: read_timeout,
write_timeout: write_timeout, debug_output: debug_output, proxy_url: proxy_url)
@connection = Connection.new(open_timeout:, read_timeout:, write_timeout:, debug_output:, proxy_url:)
@request_builder = RequestBuilder.new
@redirect_handler = RedirectHandler.new(connection: @connection, request_builder: @request_builder,
max_redirects: max_redirects)
@redirect_handler = RedirectHandler.new(connection: @connection, request_builder: @request_builder, max_redirects:)
@response_parser = ResponseParser.new
end

def get(endpoint, headers: {}, array_class: default_array_class, object_class: default_object_class)
execute_request(:get, endpoint, headers: headers, array_class: array_class, object_class: object_class)
execute_request(:get, endpoint, headers:, array_class:, object_class:)
end

def post(endpoint, body = nil, headers: {}, array_class: default_array_class, object_class: default_object_class)
execute_request(:post, endpoint, body: body, headers: headers, array_class: array_class,
object_class: object_class)
execute_request(:post, endpoint, body:, headers:, array_class:, object_class:)
end

def put(endpoint, body = nil, headers: {}, array_class: default_array_class, object_class: default_object_class)
execute_request(:put, endpoint, body: body, headers: headers, array_class: array_class,
object_class: object_class)
execute_request(:put, endpoint, body:, headers:, array_class:, object_class:)
end

def delete(endpoint, headers: {}, array_class: default_array_class, object_class: default_object_class)
execute_request(:delete, endpoint, headers: headers, array_class: array_class, object_class: object_class)
execute_request(:delete, endpoint, headers:, array_class:, object_class:)
end

def api_key=(api_key)
Expand Down Expand Up @@ -106,10 +102,9 @@ def initialize_default_classes(default_array_class, default_object_class)

def initialize_authenticator
@authenticator = if api_key && api_key_secret && access_token && access_token_secret
OAuthAuthenticator.new(api_key: api_key, api_key_secret: api_key_secret, access_token: access_token,
access_token_secret: access_token_secret)
OAuthAuthenticator.new(api_key:, api_key_secret:, access_token:, access_token_secret:)
elsif bearer_token
BearerTokenAuthenticator.new(bearer_token: bearer_token)
BearerTokenAuthenticator.new(bearer_token:)
elsif @authenticator.nil?
Authenticator.new
else
Expand All @@ -119,12 +114,10 @@ def initialize_authenticator

def execute_request(http_method, endpoint, body: nil, headers: {}, array_class: default_array_class, object_class: default_object_class)
uri = URI.join(base_url, endpoint)
request = @request_builder.build(http_method: http_method, uri: uri, body: body, headers: headers,
authenticator: @authenticator)
response = @connection.perform(request: request)
response = @redirect_handler.handle(response: response, request: request, base_url: base_url,
authenticator: @authenticator)
@response_parser.parse(response: response, array_class: array_class, object_class: object_class)
request = @request_builder.build(http_method:, uri:, body:, headers:, authenticator: @authenticator)
response = @connection.perform(request:)
response = @redirect_handler.handle(response:, request:, base_url:, authenticator: @authenticator)
@response_parser.parse(response:, array_class:, object_class:)
end
end
end
2 changes: 1 addition & 1 deletion lib/x/errors/too_many_requests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def rate_limit

def rate_limits
@rate_limits ||= RateLimit::TYPES.filter_map do |type|
RateLimit.new(type: type, response: response) if response["x-#{type}-remaining"].eql?("0")
RateLimit.new(type:, response:) if response["x-#{type}-remaining"].eql?("0")
end
end

Expand Down
21 changes: 9 additions & 12 deletions lib/x/media_uploader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,20 @@ module MediaUploader

def upload(client:, file_path:, media_category:, media_type: infer_media_type(file_path, media_category),
boundary: SecureRandom.hex)
validate!(file_path: file_path, media_category: media_category)
validate!(file_path:, media_category:)
upload_client = client.dup.tap { |c| c.base_url = "https://upload.twitter.com/1.1/" }
upload_body = construct_upload_body(file_path: file_path, media_type: media_type, boundary: boundary)
upload_body = construct_upload_body(file_path:, media_type:, boundary:)
headers = {"Content-Type" => "multipart/form-data, boundary=#{boundary}"}
upload_client.post("media/upload.json?media_category=#{media_category}", upload_body, headers: headers)
upload_client.post("media/upload.json?media_category=#{media_category}", upload_body, headers:)
end

def chunked_upload(client:, file_path:, media_category:, media_type: infer_media_type(file_path,
media_category), boundary: SecureRandom.hex, chunk_size_mb: 8)
validate!(file_path: file_path, media_category: media_category)
validate!(file_path:, media_category:)
upload_client = client.dup.tap { |c| c.base_url = "https://upload.twitter.com/1.1/" }
media = init(upload_client: upload_client, file_path: file_path, media_type: media_type,
media_category: media_category)
media = init(upload_client:, file_path:, media_type:, media_category:)
chunk_size = chunk_size_mb * BYTES_PER_MB
append(upload_client: upload_client, file_paths: split(file_path, chunk_size), media: media,
media_type: media_type, boundary: boundary)
append(upload_client:, file_paths: split(file_path, chunk_size), media:, media_type:, boundary:)
upload_client.post("media/upload.json?command=FINALIZE&media_id=#{media["media_id"]}")
end

Expand Down Expand Up @@ -89,18 +87,17 @@ def init(upload_client:, file_path:, media_type:, media_category:)
def append(upload_client:, file_paths:, media:, media_type:, boundary: SecureRandom.hex)
threads = file_paths.map.with_index do |file_path, index|
Thread.new do
upload_body = construct_upload_body(file_path: file_path, media_type: media_type, boundary: boundary)
upload_body = construct_upload_body(file_path:, media_type:, boundary:)
query = "command=APPEND&media_id=#{media["media_id"]}&segment_index=#{index}"
headers = {"Content-Type" => "multipart/form-data, boundary=#{boundary}"}
upload_chunk(upload_client: upload_client, query: query, upload_body: upload_body, file_path: file_path,
headers: headers)
upload_chunk(upload_client:, query:, upload_body:, file_path:, headers:)
end
end
threads.each(&:join)
end

def upload_chunk(upload_client:, query:, upload_body:, file_path:, headers: {})
upload_client.post("media/upload.json?#{query}", upload_body, headers: headers)
upload_client.post("media/upload.json?#{query}", upload_body, headers:)
rescue NetworkError, ServerError
retries ||= 0
((retries += 1) < MAX_RETRIES) ? retry : raise
Expand Down
6 changes: 3 additions & 3 deletions lib/x/oauth_authenticator.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
require "base64"
require "cgi"
require "json"
require "openssl"
require "securerandom"
require "uri"
require_relative "authenticator"
require_relative "cgi"

module X
class OAuthAuthenticator < Authenticator
Expand Down Expand Up @@ -71,15 +71,15 @@ def hmac_signature(base_string)
end

def signature_base_string(method, url, params)
"#{method}&#{CGI.escape(url)}&#{CGI.escape(CGI.escape_params(params.sort))}"
"#{method}&#{CGI.escapeURIComponent(url)}&#{CGI.escapeURIComponent(URI.encode_www_form(params.sort))}"
end

def signing_key
"#{api_key_secret}&#{access_token_secret}"
end

def format_oauth_header(params)
"OAuth #{params.sort.map { |k, v| "#{k}=\"#{CGI.escape(v)}\"" }.join(", ")}"
"OAuth #{params.sort.map { |k, v| "#{k}=\"#{CGI.escapeURIComponent(v)}\"" }.join(", ")}"
end
end
end
4 changes: 2 additions & 2 deletions lib/x/redirect_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def handle(response:, request:, base_url:, authenticator: Authenticator.new, red
new_request = build_request(request, new_uri, Integer(response.code), authenticator)
new_response = connection.perform(request: new_request)

handle(response: new_response, request: new_request, base_url: base_url, redirect_count: redirect_count + 1)
handle(response: new_response, request: new_request, base_url:, redirect_count: redirect_count + 1)
else
response
end
Expand All @@ -50,7 +50,7 @@ def build_request(request, new_uri, response_code, authenticator)
[:get, nil]
end

request_builder.build(http_method: http_method, uri: new_uri, body: body, authenticator: authenticator)
request_builder.build(http_method:, uri: new_uri, body:, authenticator:)
end
end
end
9 changes: 4 additions & 5 deletions lib/x/request_builder.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
require "net/http"
require "uri"
require_relative "authenticator"
require_relative "cgi"
require_relative "version"

module X
Expand All @@ -18,9 +17,9 @@ class RequestBuilder
}.freeze

def build(http_method:, uri:, body: nil, headers: {}, authenticator: Authenticator.new)
request = create_request(http_method: http_method, uri: uri, body: body)
add_headers(request: request, headers: headers)
add_authentication(request: request, authenticator: authenticator)
request = create_request(http_method:, uri:, body:)
add_headers(request:, headers:)
add_authentication(request:, authenticator:)
request
end

Expand Down Expand Up @@ -51,7 +50,7 @@ def add_headers(request:, headers:)
end

def escape_query_params(uri)
URI(uri).tap { |u| u.query = CGI.escape_params(URI.decode_www_form(u.query)) if u.query }
URI(uri).tap { |u| u.query = URI.encode_www_form(URI.decode_www_form(u.query)) if u.query }
end
end
end
4 changes: 2 additions & 2 deletions lib/x/response_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ def parse(response:, array_class: nil, object_class: nil)

return unless json?(response)

JSON.parse(response.body, array_class: array_class, object_class: object_class)
JSON.parse(response.body, array_class:, object_class:)
end

private

def error(response)
error_class(response).new(response: response)
error_class(response).new(response:)
end

def error_class(response)
Expand Down
5 changes: 0 additions & 5 deletions sig/x.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,4 @@ module X
def finalize: (upload_client: Client, media: untyped) -> untyped
def construct_upload_body: (file_path: String, media_type: String, ?boundary: String) -> String
end

class CGI
def self.escape: (String value) -> String
def self.escape_params: (Hash[String, String] | Array[[String, String]] params) -> String
end
end
9 changes: 9 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@
TEST_OAUTH_TIMESTAMP = Time.utc(1983, 11, 24).to_i.to_s
TEST_MEDIA_ID = 1_234_567_890

def test_oauth_credentials
{
api_key: TEST_API_KEY,
api_key_secret: TEST_API_KEY_SECRET,
access_token: TEST_ACCESS_TOKEN,
access_token_secret: TEST_ACCESS_TOKEN_SECRET
}
end

def test_oauth_params
{
"oauth_consumer_key" => TEST_API_KEY,
Expand Down
20 changes: 0 additions & 20 deletions test/x/cgi_test.rb

This file was deleted.

Loading

0 comments on commit 3ea2663

Please sign in to comment.