shoptet 0.0.21 → 0.0.26
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/lib/shoptet.rb +59 -102
- data/lib/shoptet/api_enumerator.rb +44 -0
- data/lib/shoptet/request.rb +14 -26
- data/shoptet.gemspec +2 -0
- metadata +18 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cf65c602c4c267d61e5fb7bd64a993d1da6b2911ea857eea8ca78022eae03a33
|
|
4
|
+
data.tar.gz: 1e9ce67fb7dd3fa9059c7a2eb5faa21f32de6ca802aff9ac99244f27687420be
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 72637f126f47c2e7ff0eb2ac9bf797f4b9108f5be4af8a6f43e3e1eae4b11a92a6fa2bcf7db48224904eb97ee1a4c51a86b66e9c8db98d50a6cdcecf3563f251
|
|
7
|
+
data.tar.gz: d149fc9bd73a3c5e4135e1f4956a9426b5d8edacd7963698e384454858556aa313473ec87734c2ae5e6ac15f6a4c4dfbe9052290ffd1d1b98255f6dce2a8f198
|
data/lib/shoptet.rb
CHANGED
|
@@ -1,78 +1,29 @@
|
|
|
1
1
|
require 'delegate'
|
|
2
2
|
require_relative 'shoptet/request'
|
|
3
|
+
require_relative 'shoptet/api_enumerator'
|
|
3
4
|
|
|
4
5
|
class Shoptet
|
|
5
|
-
include Shoptet::UrlHelpers
|
|
6
|
-
|
|
7
6
|
class Error < StandardError; end
|
|
8
7
|
class AddonSuspended < StandardError; end
|
|
9
8
|
class AddonNotInstalled < StandardError; end
|
|
10
9
|
class InvalidTokenNoRights < StandardError; end
|
|
11
|
-
class
|
|
10
|
+
class EmptyResponse < StandardError; end
|
|
12
11
|
class MaxPageReached < StandardError; end
|
|
12
|
+
class StockNotFound < StandardError; end
|
|
13
|
+
class ProductNotFound < StandardError; end
|
|
14
|
+
class SystemMaintenance < StandardError; end
|
|
15
|
+
class UnknownError < StandardError; end
|
|
13
16
|
|
|
14
17
|
EXPIRED_TOKEN_CODE = 'expired-token'
|
|
15
18
|
INVALID_TOKEN_CODE = 'invalid-token'
|
|
16
19
|
ADDON_NOT_INSTALLED = 'Addon installation is not approved.'
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
ON_TOKEN_ERROR = -> (api) do
|
|
19
22
|
api.api_token = api.new_api_token
|
|
20
23
|
end
|
|
21
24
|
|
|
22
|
-
class ApiEnumerator < SimpleDelegator
|
|
23
|
-
def initialize base_url, filters, data_key, api
|
|
24
|
-
@base_url = base_url
|
|
25
|
-
@filters = filters
|
|
26
|
-
@data_key = data_key || URI(base_url).path.split('/').last
|
|
27
|
-
@api = api
|
|
28
|
-
|
|
29
|
-
@enum = Enumerator.new do |y|
|
|
30
|
-
first_page.dig('data', @data_key).each { y.yield _1 }
|
|
31
|
-
|
|
32
|
-
if total_pages > 1
|
|
33
|
-
other_pages = 2..(total_pages - 1)
|
|
34
|
-
other_pages.each do |page|
|
|
35
|
-
uri = @api.assemble_uri base_url, filters.merge(page: page)
|
|
36
|
-
result = @api.request uri
|
|
37
|
-
result.dig('data', @data_key).each { y.yield _1 }
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
last_page.dig('data', @data_key).each { y.yield _1 }
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
super @enum
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def first_page
|
|
48
|
-
@first_page ||=
|
|
49
|
-
begin
|
|
50
|
-
uri = @api.assemble_uri @base_url, @filters
|
|
51
|
-
@api.request uri
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def total_pages
|
|
56
|
-
first_page.dig('data', 'paginator', 'pageCount') || 0
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def last_page
|
|
60
|
-
return first_page if total_pages < 2
|
|
61
|
-
|
|
62
|
-
@last_page ||=
|
|
63
|
-
begin
|
|
64
|
-
uri = @api.assemble_uri @base_url, @filters.merge(page: total_pages)
|
|
65
|
-
@api.request uri
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def size
|
|
70
|
-
first_page['data']['paginator']['totalCount']
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
25
|
def self.version
|
|
75
|
-
'0.0.
|
|
26
|
+
'0.0.26'
|
|
76
27
|
end
|
|
77
28
|
|
|
78
29
|
def self.ar_on_token_error(model)
|
|
@@ -102,7 +53,7 @@ class Shoptet
|
|
|
102
53
|
'scope' => 'api'
|
|
103
54
|
}
|
|
104
55
|
|
|
105
|
-
Shoptet::Request.post
|
|
56
|
+
Shoptet::Request.post(url, data)
|
|
106
57
|
end
|
|
107
58
|
|
|
108
59
|
def self.login_token url, code, client_id, client_secret, redirect_url
|
|
@@ -115,11 +66,11 @@ class Shoptet
|
|
|
115
66
|
scope: 'basic_eshop'
|
|
116
67
|
}
|
|
117
68
|
|
|
118
|
-
Shoptet::Request.post
|
|
69
|
+
Shoptet::Request.post(url, data)
|
|
119
70
|
end
|
|
120
71
|
|
|
121
72
|
def self.basic_eshop url, access_token
|
|
122
|
-
Shoptet::Request.get
|
|
73
|
+
Shoptet::Request.get(url, { 'Authorization' => "Bearer #{access_token}" })
|
|
123
74
|
end
|
|
124
75
|
|
|
125
76
|
attr_accessor :api_token
|
|
@@ -130,11 +81,11 @@ class Shoptet
|
|
|
130
81
|
@shop_url = shop_url
|
|
131
82
|
@client_id = client_id
|
|
132
83
|
@api_token = api_token
|
|
133
|
-
@on_token_error = on_token_error ||
|
|
84
|
+
@on_token_error = on_token_error || ON_TOKEN_ERROR
|
|
134
85
|
end
|
|
135
86
|
|
|
136
87
|
def endpoints api_params = {}
|
|
137
|
-
enumerize
|
|
88
|
+
enumerize('https://api.myshoptet.com/api/system/endpoints', api_params)
|
|
138
89
|
end
|
|
139
90
|
|
|
140
91
|
def endpoint_approved? endpoint
|
|
@@ -156,101 +107,101 @@ class Shoptet
|
|
|
156
107
|
redirect_uri: redirect_url
|
|
157
108
|
}.to_query
|
|
158
109
|
|
|
159
|
-
URI("#{@shop_url}action/OAuthServer/authorize?#{query}")
|
|
110
|
+
URI("#{@shop_url}action/OAuthServer/authorize?#{query}")
|
|
160
111
|
end
|
|
161
112
|
|
|
162
113
|
def shop_info api_params = {}
|
|
163
|
-
|
|
164
|
-
result = request url
|
|
114
|
+
result = request('https://api.myshoptet.com/api/eshop', api_params)
|
|
165
115
|
result['data']
|
|
166
116
|
end
|
|
167
117
|
|
|
168
118
|
def design_info api_params = {}
|
|
169
|
-
|
|
170
|
-
result = request url
|
|
119
|
+
result = request('https://api.myshoptet.com/api/eshop/design', api_params)
|
|
171
120
|
|
|
172
121
|
result['data']
|
|
173
122
|
end
|
|
174
123
|
|
|
175
124
|
def stocks api_params = {}
|
|
176
|
-
enumerize
|
|
125
|
+
enumerize('https://api.myshoptet.com/api/stocks', api_params)
|
|
177
126
|
end
|
|
178
127
|
|
|
179
128
|
def products api_params = {}
|
|
180
|
-
enumerize
|
|
129
|
+
enumerize("https://api.myshoptet.com/api/products", api_params)
|
|
181
130
|
end
|
|
182
131
|
|
|
183
132
|
def supplies warehouse_id, api_params = {}
|
|
184
|
-
|
|
185
|
-
enumerize uri, api_params
|
|
133
|
+
enumerize("https://api.myshoptet.com/api/stocks/#{warehouse_id}/supplies", api_params)
|
|
186
134
|
end
|
|
187
135
|
|
|
188
136
|
def stocks_movements warehouse_id, api_params = {}
|
|
189
|
-
|
|
190
|
-
enumerize uri, api_params
|
|
137
|
+
enumerize("https://api.myshoptet.com/api/stocks/#{warehouse_id}/movements", api_params)
|
|
191
138
|
end
|
|
192
139
|
|
|
193
140
|
def product_categories api_params = {}
|
|
194
|
-
enumerize
|
|
141
|
+
enumerize('https://api.myshoptet.com/api/categories', api_params)
|
|
195
142
|
end
|
|
196
143
|
|
|
197
144
|
def products_changes api_params = {}
|
|
198
|
-
|
|
199
|
-
enumerize uri, api_params
|
|
145
|
+
enumerize('https://api.myshoptet.com/api/products/changes', api_params)
|
|
200
146
|
end
|
|
201
147
|
|
|
202
148
|
def price_lists api_params = {}
|
|
203
|
-
enumerize
|
|
149
|
+
enumerize('https://api.myshoptet.com/api/pricelists', api_params)
|
|
204
150
|
end
|
|
205
151
|
|
|
206
152
|
def prices price_list_id, api_params = {}
|
|
207
|
-
|
|
208
|
-
enumerize uri, api_params, 'pricelist'
|
|
153
|
+
enumerize("https://api.myshoptet.com/api/pricelists/#{price_list_id}", api_params, 'pricelist')
|
|
209
154
|
end
|
|
210
155
|
|
|
211
156
|
def orders api_params = {}
|
|
212
|
-
enumerize
|
|
157
|
+
enumerize('https://api.myshoptet.com/api/orders', api_params)
|
|
213
158
|
end
|
|
214
159
|
|
|
215
|
-
def orders_changes
|
|
216
|
-
|
|
217
|
-
enumerize
|
|
160
|
+
def orders_changes from:
|
|
161
|
+
api_params = { from: from.iso8601 }
|
|
162
|
+
enumerize('https://api.myshoptet.com/api/orders/changes', api_params)
|
|
218
163
|
end
|
|
219
164
|
|
|
220
165
|
def order code, api_params = {}
|
|
221
|
-
|
|
222
|
-
result
|
|
223
|
-
result.dig 'data', 'order'
|
|
166
|
+
result = request("https://api.myshoptet.com/api/orders/#{code}", api_params)
|
|
167
|
+
result.dig('data', 'order')
|
|
224
168
|
end
|
|
225
169
|
|
|
226
170
|
def product guid, api_params = {}
|
|
227
|
-
|
|
228
|
-
result
|
|
171
|
+
result = request("https://api.myshoptet.com/api/products/#{guid}", api_params)
|
|
172
|
+
result['data']
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def product_by_code code, api_params = {}
|
|
176
|
+
result = request("https://api.myshoptet.com/api/products/code/#{code}", api_params)
|
|
229
177
|
result['data']
|
|
230
178
|
end
|
|
231
179
|
|
|
232
180
|
def new_api_token
|
|
233
181
|
headers = { 'Authorization' => "Bearer #{@oauth_token}" }
|
|
234
182
|
|
|
235
|
-
result = Shoptet::Request.get
|
|
236
|
-
handle_errors
|
|
183
|
+
result = Shoptet::Request.get(URI(@oauth_url), headers)
|
|
184
|
+
handle_errors(result)
|
|
237
185
|
|
|
238
|
-
result.fetch
|
|
186
|
+
result.fetch('access_token')
|
|
239
187
|
end
|
|
240
188
|
|
|
241
|
-
def request
|
|
189
|
+
def request url, api_params = {}, retry_on_token_error = true
|
|
190
|
+
url = URI(url)
|
|
191
|
+
url.query = URI.encode_www_form(api_params) if api_params.any?
|
|
192
|
+
|
|
242
193
|
headers = { 'Shoptet-Access-Token' => @api_token,
|
|
243
194
|
'Content-Type' => 'application/vnd.shoptet.v1.0' }
|
|
244
195
|
|
|
245
|
-
result = Shoptet::Request.get
|
|
246
|
-
token_errors = handle_errors
|
|
196
|
+
result = Shoptet::Request.get(url, headers)
|
|
197
|
+
token_errors = handle_errors(result)
|
|
247
198
|
|
|
248
199
|
if token_errors.any?
|
|
249
200
|
if retry_on_token_error
|
|
250
|
-
@on_token_error.call
|
|
251
|
-
request
|
|
201
|
+
@on_token_error.call(self)
|
|
202
|
+
request(url, api_params, false)
|
|
252
203
|
else
|
|
253
|
-
raise Error.new
|
|
204
|
+
raise Error.new(result)
|
|
254
205
|
end
|
|
255
206
|
else
|
|
256
207
|
result
|
|
@@ -258,9 +209,7 @@ class Shoptet
|
|
|
258
209
|
end
|
|
259
210
|
|
|
260
211
|
def suspended?
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
false if data
|
|
212
|
+
false if shop_info
|
|
264
213
|
rescue Shoptet::AddonSuspended
|
|
265
214
|
true
|
|
266
215
|
end
|
|
@@ -268,10 +217,10 @@ class Shoptet
|
|
|
268
217
|
private
|
|
269
218
|
|
|
270
219
|
def enumerize base_url, filters = {}, data_key = nil
|
|
271
|
-
ApiEnumerator.new
|
|
220
|
+
ApiEnumerator.new(base_url, filters, data_key, self)
|
|
272
221
|
end
|
|
273
222
|
|
|
274
|
-
def handle_errors result
|
|
223
|
+
def handle_errors result
|
|
275
224
|
error = result['error']
|
|
276
225
|
errors = result['errors'] || []
|
|
277
226
|
token_errors, non_token_errors = errors.partition do |err|
|
|
@@ -289,6 +238,14 @@ class Shoptet
|
|
|
289
238
|
raise AddonNotInstalled
|
|
290
239
|
elsif errors.any? { |err| err["errorCode"] == 'invalid-token-no-rights' }
|
|
291
240
|
raise InvalidTokenNoRights
|
|
241
|
+
elsif errors.any? { |err| err["errorCode"] == 'stock-not-found' }
|
|
242
|
+
raise StockNotFound
|
|
243
|
+
elsif errors.any? { |err| err["errorCode"] == 'product-not-found' }
|
|
244
|
+
raise ProductNotFound
|
|
245
|
+
elsif errors.any? { |err| err["errorCode"] == 'system-maintenance' }
|
|
246
|
+
raise SystemMaintenance
|
|
247
|
+
elsif errors.any? { |err| err["errorCode"] == 'unknown-error' }
|
|
248
|
+
raise UnknownError
|
|
292
249
|
elsif errors.any? { |err| err["errorCode"] == 'page-not-found' && err['message'].include?('max page is') }
|
|
293
250
|
raise MaxPageReached
|
|
294
251
|
else
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
class Shoptet
|
|
2
|
+
class ApiEnumerator < SimpleDelegator
|
|
3
|
+
def initialize base_url, filters, data_key, api
|
|
4
|
+
@base_url = base_url
|
|
5
|
+
@filters = filters
|
|
6
|
+
@data_key = data_key || URI(base_url).path.split('/').last
|
|
7
|
+
@api = api
|
|
8
|
+
|
|
9
|
+
@enum = Enumerator.new do |y|
|
|
10
|
+
first_page.dig('data', @data_key).each { y.yield _1 }
|
|
11
|
+
|
|
12
|
+
if total_pages > 1
|
|
13
|
+
other_pages = 2..(total_pages - 1)
|
|
14
|
+
other_pages.each do |page|
|
|
15
|
+
result = @api.request(base_url, filters.merge(page: page))
|
|
16
|
+
result.dig('data', @data_key).each { y.yield _1 }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
last_page.dig('data', @data_key).each { y.yield _1 }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
super @enum
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def first_page
|
|
27
|
+
@first_page ||= @api.request(@base_url, @filters)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def last_page
|
|
31
|
+
return first_page if total_pages < 2
|
|
32
|
+
|
|
33
|
+
@last_page ||= @api.request(@base_url, @filters.merge(page: total_pages))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def total_pages
|
|
37
|
+
first_page.dig('data', 'paginator', 'pageCount') || 0
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def size
|
|
41
|
+
first_page.dig('data', 'paginator', 'totalCount')
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/shoptet/request.rb
CHANGED
|
@@ -1,53 +1,41 @@
|
|
|
1
1
|
require 'net/http'
|
|
2
|
-
|
|
3
|
-
#TODO: keep_alive_timeout ?
|
|
2
|
+
require 'oj'
|
|
4
3
|
|
|
5
4
|
class Shoptet
|
|
6
|
-
module UrlHelpers
|
|
7
|
-
def assemble_uri base, params = {}
|
|
8
|
-
u = URI(base)
|
|
9
|
-
u.query = URI.encode_www_form(params) if params.any?
|
|
10
|
-
|
|
11
|
-
u.to_s
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
5
|
class Request
|
|
16
|
-
def self.get
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
http = Net::HTTP.new parsed_uri.host, parsed_uri.port
|
|
6
|
+
def self.get url, headers
|
|
7
|
+
http = Net::HTTP.new(url.host, url.port)
|
|
20
8
|
http.use_ssl = true
|
|
21
9
|
http.open_timeout = 60
|
|
22
10
|
http.read_timeout = 60
|
|
23
11
|
http.write_timeout = 60
|
|
24
12
|
http.ssl_timeout = 60
|
|
25
13
|
|
|
26
|
-
request = Net::HTTP::Get.new
|
|
14
|
+
request = Net::HTTP::Get.new(url)
|
|
27
15
|
headers.each do |key, value|
|
|
28
16
|
request[key] = value
|
|
29
17
|
end
|
|
30
18
|
|
|
31
|
-
response = http.request
|
|
32
|
-
parsed_body =
|
|
19
|
+
response = http.request(request)
|
|
20
|
+
parsed_body = Oj.load(response.body, mode: :compat)
|
|
33
21
|
|
|
34
22
|
unless parsed_body
|
|
35
|
-
message = "Status code: #{response.code}, url: #{
|
|
36
|
-
fail Shoptet::
|
|
23
|
+
message = "Status code: #{response.code}, url: #{url}"
|
|
24
|
+
fail Shoptet::EmptyResponse.new(message)
|
|
37
25
|
end
|
|
38
26
|
|
|
39
27
|
parsed_body
|
|
40
28
|
end
|
|
41
29
|
|
|
42
|
-
def self.post
|
|
43
|
-
|
|
44
|
-
|
|
30
|
+
def self.post url, body
|
|
31
|
+
request = Net::HTTP::Post.new(url)
|
|
32
|
+
request.set_form_data(body)
|
|
45
33
|
|
|
46
|
-
|
|
47
|
-
http.request
|
|
34
|
+
response = Net::HTTP.start(url.host, url.port, use_ssl: true) do |http|
|
|
35
|
+
http.request(request)
|
|
48
36
|
end
|
|
49
37
|
|
|
50
|
-
|
|
38
|
+
Oj.load(response.body, mode: :compat)
|
|
51
39
|
end
|
|
52
40
|
end
|
|
53
41
|
end
|
data/shoptet.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shoptet
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.26
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Premysl Donat
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-05-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: oj
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: irb
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -40,6 +54,7 @@ files:
|
|
|
40
54
|
- bin/console
|
|
41
55
|
- bin/setup
|
|
42
56
|
- lib/shoptet.rb
|
|
57
|
+
- lib/shoptet/api_enumerator.rb
|
|
43
58
|
- lib/shoptet/request.rb
|
|
44
59
|
- shoptet.gemspec
|
|
45
60
|
homepage: https://github.com/Masa331/shoptet
|
|
@@ -63,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
63
78
|
- !ruby/object:Gem::Version
|
|
64
79
|
version: '0'
|
|
65
80
|
requirements: []
|
|
66
|
-
rubygems_version: 3.
|
|
81
|
+
rubygems_version: 3.2.15
|
|
67
82
|
signing_key:
|
|
68
83
|
specification_version: 4
|
|
69
84
|
summary: API wrapper for interacting with Shoptet api
|