betsy 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ba97ebe9949b2fa6512f323b2ff4e9214e26bee642afbec58fb83bb2f16af83
4
- data.tar.gz: fbfdb2302982e26ec76e0f205c14d2a70929befa5813d99bdd54c9eb70e50cd7
3
+ metadata.gz: be84657637faf15358471454761e8f48181ce8907741f64120ce17837d777119
4
+ data.tar.gz: f7b0948911a4271e09423591f7bd55e6be04612c5502c32bc2cb9d2713bd279f
5
5
  SHA512:
6
- metadata.gz: 630d6f49d34e9f1e7b66cf3e369442c2b28884c23db693a31174b1442838f37eeb134e8937cca8ea018ee6397d9f74c3db444e9aff6f0feb547491e22626145e
7
- data.tar.gz: 7d420367b78b8313a940e31c9d878d416e5469cb7d0fad91f85552fdabce0ef293d591131ace10ef36032d5327dbb3b74127eff5f799a4c8fbb9a5893eabf53f
6
+ metadata.gz: e34859ed8deb1e858c2284c2a0691d4a5ddaa09e6efa2b1a867f58956cb73456161285356603500ecd287d15455667e82422f77ec01c2aa2138296a61327510e
7
+ data.tar.gz: 75120021566c48ece0adf0ca7abf44b61efb9903d77a950fcac75383eb9ad2a985a8a496a2f50665f18fdecbefc9611ce3efb81a497bf8114015ac04438863cc
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2026-05-14
4
+
5
+ ### Breaking changes
6
+
7
+ - The account model (default `EtsyAccount`) must now implement a `token_expired?` instance method. If you ran the install generator in v0.2.x, you need to add this method manually. See the [migration guide](#migrating-from-v02x-to-v03x) in the README.
8
+
9
+ ### Changed
10
+
11
+ - Token expiration checking now delegates to `token_expired?` on the account model instead of using inline logic in the gem
12
+ - Replaced Faraday with Ruby's stdlib `Net::HTTP`, removing the only external runtime dependency
13
+ - Declared `activesupport` as an explicit runtime dependency (was previously undeclared)
14
+
15
+ ### Fixed
16
+
17
+ - Fixed `TypeError` crash in `check_token_expiration` when `expires_in` or `last_token_refresh` is nil
18
+ - Failed token refresh responses no longer save nil credentials back to the account
19
+
3
20
  ## [0.2.0] - 2021-05-04
4
21
 
5
22
  - Initial release
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- betsy (0.1.0)
5
- faraday (= 1.5.1)
4
+ betsy (0.3.0)
5
+ activesupport (>= 5.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -83,23 +83,6 @@ GEM
83
83
  diff-lcs (1.4.4)
84
84
  docile (1.4.0)
85
85
  erubi (1.10.0)
86
- faraday (1.5.1)
87
- faraday-em_http (~> 1.0)
88
- faraday-em_synchrony (~> 1.0)
89
- faraday-excon (~> 1.1)
90
- faraday-httpclient (~> 1.0.1)
91
- faraday-net_http (~> 1.0)
92
- faraday-net_http_persistent (~> 1.1)
93
- faraday-patron (~> 1.0)
94
- multipart-post (>= 1.2, < 3)
95
- ruby2_keywords (>= 0.0.4)
96
- faraday-em_http (1.0.0)
97
- faraday-em_synchrony (1.0.0)
98
- faraday-excon (1.1.0)
99
- faraday-httpclient (1.0.1)
100
- faraday-net_http (1.0.1)
101
- faraday-net_http_persistent (1.2.0)
102
- faraday-patron (1.0.0)
103
86
  globalid (0.5.2)
104
87
  activesupport (>= 5.0)
105
88
  hashdiff (1.0.1)
@@ -115,9 +98,8 @@ GEM
115
98
  method_source (1.0.0)
116
99
  mini_mime (1.1.0)
117
100
  minitest (5.14.4)
118
- multipart-post (2.1.1)
119
101
  nio4r (2.5.8)
120
- nokogiri (1.12.2-x86_64-linux)
102
+ nokogiri (1.19.3-x86_64-linux-gnu)
121
103
  racc (~> 1.4)
122
104
  parallel (1.20.1)
123
105
  parser (3.0.2.0)
@@ -185,7 +167,6 @@ GEM
185
167
  rubocop (>= 1.7.0, < 2.0)
186
168
  rubocop-ast (>= 0.4.0)
187
169
  ruby-progressbar (1.11.0)
188
- ruby2_keywords (0.0.5)
189
170
  simplecov (0.16.1)
190
171
  docile (~> 1.1)
191
172
  json (>= 1.8, < 3)
@@ -234,4 +215,4 @@ DEPENDENCIES
234
215
  webmock (~> 3.13.0)
235
216
 
236
217
  BUNDLED WITH
237
- 2.2.17
218
+ 2.2.33
data/README.md CHANGED
@@ -66,6 +66,32 @@ Betsy::UserAddress.get_user_addresses(etsy_account: EtsyAccount.first)
66
66
 
67
67
  By default, Betsy handles the refreshing of authentication tokens for you.
68
68
 
69
+ ## Migrating from v0.2.x to v0.3.x
70
+
71
+ ### Account model requires `token_expired?`
72
+
73
+ In v0.3.0, the token expiration check was moved out of the gem and into your account model. You need to add a `token_expired?` method to your `EtsyAccount` model (or whatever model you configured via `Betsy.account_model`):
74
+
75
+ ```ruby
76
+ class EtsyAccount < ApplicationRecord
77
+ def token_expired?
78
+ last_token_refresh.nil? || expires_in.nil? || last_token_refresh + expires_in <= DateTime.now
79
+ end
80
+ end
81
+ ```
82
+
83
+ This gives you full control over the expiration logic. For example, you could add a buffer to refresh tokens early:
84
+
85
+ ```ruby
86
+ def token_expired?
87
+ last_token_refresh.nil? || expires_in.nil? || last_token_refresh + expires_in - 5.minutes <= DateTime.now
88
+ end
89
+ ```
90
+
91
+ ### Faraday removed
92
+
93
+ Betsy no longer depends on Faraday. It uses Ruby's built-in `Net::HTTP` instead. If your app was relying on Betsy to pull in Faraday, you'll need to add it to your own Gemfile.
94
+
69
95
  ## License
70
96
 
71
97
  The gem is available as open-source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/betsy.gemspec CHANGED
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
37
37
  spec.add_development_dependency("webmock", "~> 3.13.0")
38
38
  spec.add_development_dependency("coveralls")
39
39
 
40
- spec.add_dependency("faraday", "1.5.1")
40
+ spec.add_dependency("activesupport", ">= 5.0")
41
41
 
42
42
  # For more information and examples about making a new gem, checkout our
43
43
  # guide at: https://bundler.io/guides/creating_gem.html
data/lib/betsy/model.rb CHANGED
@@ -9,22 +9,52 @@ module Betsy
9
9
  end
10
10
  end
11
11
 
12
+ REQUEST_CLASSES = {
13
+ get: Net::HTTP::Get,
14
+ post: Net::HTTP::Post,
15
+ put: Net::HTTP::Put,
16
+ patch: Net::HTTP::Patch,
17
+ delete: Net::HTTP::Delete
18
+ }.freeze
19
+
12
20
  def make_request(request_type, endpoint, options = {})
13
21
  check_token_expiration(options[:etsy_account]) if options[:etsy_account]
14
22
  headers = access_credentials(options[:etsy_account])
15
23
  options.delete(:etsy_account)
16
- response = Faraday.method(request_type).call("#{BASE_ETSY_API_URL}#{endpoint}", options, headers)
24
+
25
+ uri = URI("#{BASE_ETSY_API_URL}#{endpoint}")
26
+
27
+ if [:post, :put, :patch].include?(request_type)
28
+ headers = headers.reverse_merge(content_type: "application/json")
29
+ request = REQUEST_CLASSES[request_type].new(uri)
30
+ request.body = options.to_json
31
+ else
32
+ uri.query = URI.encode_www_form(options) if options.any?
33
+ request = REQUEST_CLASSES[request_type].new(uri)
34
+ end
35
+
36
+ headers.each { |key, value| request[key.to_s] = value }
37
+
38
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
39
+ http.request(request)
40
+ end
41
+
17
42
  handle_response(response)
18
43
  end
19
44
 
20
45
  def check_token_expiration(etsy_account)
21
- if etsy_account.last_token_refresh + etsy_account.expires_in <= DateTime.now
46
+ if etsy_account.token_expired?
22
47
  options = {
23
48
  grant_type: "refresh_token",
24
49
  refresh_token: etsy_account.refresh_token,
25
50
  client_id: Betsy.api_key
26
51
  }
27
- response = JSON.parse(Faraday.post("https://api.etsy.com/v3/public/oauth/token", options).body)
52
+ response = JSON.parse(Net::HTTP.post_form(URI("https://api.etsy.com/v3/public/oauth/token"), options).body)
53
+
54
+ if response["access_token"].nil?
55
+ raise "Etsy token refresh failed: #{response}"
56
+ end
57
+
28
58
  etsy_account.access_token = response["access_token"]
29
59
  etsy_account.expires_in = response["expires_in"]
30
60
  etsy_account.refresh_token = response["refresh_token"]
@@ -40,12 +70,12 @@ module Betsy
40
70
  end
41
71
 
42
72
  def handle_response(response)
43
- if response.status == 200
73
+ if response.code.to_i == 200
44
74
  return nil if response.body.empty?
45
75
  response = JSON.parse(response.body)
46
76
  build_objects(response)
47
77
  else
48
- Betsy::Error.new(JSON.parse(response.body).merge!("status" => response.status))
78
+ Betsy::Error.new(JSON.parse(response.body).merge!("status" => response.code.to_i))
49
79
  end
50
80
  end
51
81
 
data/lib/betsy/review.rb CHANGED
@@ -18,5 +18,9 @@ module Betsy
18
18
  def self.get_reviews_by_shop(shop_id, options = {})
19
19
  make_request(:get, "/v3/application/shops/#{shop_id}/reviews", options)
20
20
  end
21
+
22
+ def self.get_reviews_by_listing(listing_id, options = {})
23
+ make_request(:get, "/v3/application/listings/#{listing_id}/reviews", options)
24
+ end
21
25
  end
22
26
  end
@@ -52,6 +52,9 @@ module Betsy
52
52
  attribute :language
53
53
  attribute :price
54
54
  attribute :taxonomy_id
55
+ attribute :production_partners
56
+ attribute :skus
57
+ attribute :views
55
58
 
56
59
  # listing properties
57
60
  attribute :property_id
@@ -10,6 +10,7 @@ module Betsy
10
10
  attribute :seller_user_id
11
11
  attribute :buyer_user_id
12
12
  attribute :create_timestamp
13
+ attribute :created_timestamp
13
14
  attribute :paid_timestamp
14
15
  attribute :shipped_timestamp
15
16
  attribute :quantity
@@ -20,9 +21,19 @@ module Betsy
20
21
  attribute :listing_id
21
22
  attribute :transaction_type
22
23
  attribute :product_id
24
+ attribute :sku
23
25
  attribute :price
24
26
  attribute :shipping_cost
25
27
  attribute :variations
28
+ attribute :product_data
29
+ attribute :shipping_profile_id
30
+ attribute :min_processing_days
31
+ attribute :max_processing_days
32
+ attribute :shipping_method
33
+ attribute :shipping_upgrade
34
+ attribute :expected_ship_date
35
+ attribute :buyer_coupon
36
+ attribute :shop_coupon
26
37
 
27
38
  def self.get_shop_receipt_transactions_by_listing(shop_id, listing_id, options = {})
28
39
  make_request(:get, "/v3/application/shops/#{shop_id}/listings/#{listing_id}/transactions", options)
data/lib/betsy/user.rb CHANGED
@@ -5,23 +5,18 @@ module Betsy
5
5
  include Betsy::Model
6
6
 
7
7
  attribute :user_id
8
- attribute :login_name
8
+ attribute :shop_id
9
9
  attribute :primary_email
10
10
  attribute :first_name
11
11
  attribute :last_name
12
- attribute :create_timestamp
13
- attribute :referred_by_user_id
14
- attribute :use_new_inventory_endpoints
15
- attribute :is_seller
16
- attribute :bio
17
- attribute :gender
18
- attribute :birth_month
19
- attribute :birth_day
20
- attribute :transaction_buy_count
21
- attribute :transaction_sold_count
12
+ attribute :image_url_75x75
22
13
 
23
14
  def self.get_user(user_id, options = {})
24
15
  make_request(:get, "/v3/application/users/#{user_id}", options)
25
16
  end
17
+
18
+ def self.get_me(options = {})
19
+ make_request(:get, "/v3/application/users/me", options)
20
+ end
26
21
  end
27
22
  end
data/lib/betsy/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Betsy
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/betsy.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support"
4
- require "faraday"
4
+ require "net/http"
5
+ require "uri"
6
+ require "json"
5
7
 
6
8
  require_relative "betsy/version"
7
9
  require_relative "betsy/model"
@@ -33,6 +35,7 @@ module Betsy
33
35
 
34
36
  mattr_accessor :api_key
35
37
  mattr_accessor :redirect_uri_base
38
+ mattr_accessor :account_model, default: "EtsyAccount"
36
39
 
37
40
  ALL_SCOPES = ["address_r",
38
41
  "address_w",
@@ -72,7 +75,7 @@ module Betsy
72
75
  code_verifier = generate_code_verifier
73
76
  code_challenge = Digest::SHA256.base64digest(code_verifier).tr("+/", "-_").tr("=", "")
74
77
 
75
- EtsyAccount.create(state: state, code_verifier: code_verifier)
78
+ account_class.create(state: state, code_verifier: code_verifier)
76
79
 
77
80
  "https://www.etsy.com/oauth/connect" \
78
81
  "?response_type=code" \
@@ -85,7 +88,7 @@ module Betsy
85
88
  end
86
89
 
87
90
  def self.request_access_token(params)
88
- etsy_account = EtsyAccount.find_by(state: params[:state])
91
+ etsy_account = account_class.find_by(state: params[:state])
89
92
  if etsy_account.present?
90
93
  options = {
91
94
  grant_type: "authorization_code",
@@ -94,7 +97,7 @@ module Betsy
94
97
  code: params[:code],
95
98
  code_verifier: etsy_account.code_verifier
96
99
  }
97
- response = JSON.parse(Faraday.post("https://api.etsy.com/v3/public/oauth/token", options).body)
100
+ response = JSON.parse(Net::HTTP.post_form(URI("https://api.etsy.com/v3/public/oauth/token"), options).body)
98
101
  etsy_account.access_token = response["access_token"]
99
102
  etsy_account.refresh_token = response["refresh_token"]
100
103
  etsy_account.expires_in = response["expires_in"]
@@ -105,6 +108,10 @@ module Betsy
105
108
  end
106
109
  end
107
110
 
111
+ def self.account_class
112
+ @@account_class ||= account_model.constantize
113
+ end
114
+
108
115
  class << self
109
116
  private
110
117
 
@@ -11,7 +11,8 @@ module Betsy
11
11
  source_root File.expand_path("../templates", __FILE__)
12
12
 
13
13
  def copy_betsy_model
14
- template "etsy_account.rb", "app/models/etsy_account.rb"
14
+ model_file = Betsy.account_model.underscore
15
+ template "etsy_account.rb", "app/models/#{model_file}.rb"
15
16
  end
16
17
 
17
18
  def copy_betsy_migration
@@ -1,6 +1,6 @@
1
1
  class CreateEtsyAccounts < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
- create_table :etsy_accounts do |t|
3
+ create_table "<%= Betsy.account_class.table_name %>" do |t|
4
4
  t.string :access_token
5
5
  t.string :refresh_token
6
6
  t.integer :expires_in
@@ -0,0 +1,5 @@
1
+ class <%= Betsy.account_model %> < ApplicationRecord
2
+ def token_expired?
3
+ last_token_refresh.nil? || expires_in.nil? || last_token_refresh + expires_in <= DateTime.now
4
+ end
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: betsy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jace Bayless
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-23 00:00:00.000000000 Z
11
+ date: 2026-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -109,19 +109,19 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: faraday
112
+ name: activesupport
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: 1.5.1
117
+ version: '5.0'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '='
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: 1.5.1
124
+ version: '5.0'
125
125
  description: This gem allows users to simply interact with the Etsy V3 API.
126
126
  email:
127
127
  - jacebayless@gmail.com
@@ -131,6 +131,7 @@ extra_rdoc_files: []
131
131
  files:
132
132
  - ".gitignore"
133
133
  - ".rspec"
134
+ - ".ruby-version"
134
135
  - ".travis.yml"
135
136
  - CHANGELOG.md
136
137
  - CODE_OF_CONDUCT.md
@@ -141,7 +142,6 @@ files:
141
142
  - Rakefile
142
143
  - app/controllers/betsy/response_listener_controller.rb
143
144
  - app/views/betsy/response_listener/etsy_response_listener.html.erb
144
- - betsy-0.1.0.gem
145
145
  - betsy.gemspec
146
146
  - bin/console
147
147
  - bin/setup
@@ -174,8 +174,8 @@ files:
174
174
  - lib/betsy/version.rb
175
175
  - lib/generators/betsy/install_generator.rb
176
176
  - lib/generators/betsy/templates/betsy.rb
177
- - lib/generators/betsy/templates/create_etsy_accounts.rb
178
- - lib/generators/betsy/templates/etsy_account.rb
177
+ - lib/generators/betsy/templates/create_etsy_accounts.rb.tt
178
+ - lib/generators/betsy/templates/etsy_account.rb.tt
179
179
  homepage: https://github.com/JaceBayless/betsy
180
180
  licenses:
181
181
  - MIT
@@ -184,7 +184,7 @@ metadata:
184
184
  homepage_uri: https://github.com/JaceBayless/betsy
185
185
  source_code_uri: https://github.com/JaceBayless/betsy
186
186
  changelog_uri: https://github.com/JaceBayless/betsy/blob/main/CHANGELOG.md
187
- post_install_message:
187
+ post_install_message:
188
188
  rdoc_options: []
189
189
  require_paths:
190
190
  - lib
@@ -199,8 +199,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
199
199
  - !ruby/object:Gem::Version
200
200
  version: '0'
201
201
  requirements: []
202
- rubygems_version: 3.2.17
203
- signing_key:
202
+ rubygems_version: 3.4.20
203
+ signing_key:
204
204
  specification_version: 4
205
205
  summary: A gem for the Etsy API V3
206
206
  test_files: []
data/betsy-0.1.0.gem DELETED
Binary file
@@ -1,2 +0,0 @@
1
- class EtsyAccount < ApplicationRecord
2
- end