webscraping_ai 2.0.1 → 3.1.2

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.
@@ -1,12 +1,12 @@
1
1
  =begin
2
2
  #WebScraping.AI
3
3
 
4
- #A client for https://webscraping.ai API. It provides a web scaping automation API with Chrome JS rendering, rotating proxies and builtin HTML parsing.
4
+ #WebScraping.AI scraping API provides GPT-powered tools with Chromium JavaScript rendering, rotating proxies, and built-in HTML parsing.
5
5
 
6
- The version of the OpenAPI document: 2.0.1
6
+ The version of the OpenAPI document: 3.1.2
7
7
  Contact: support@webscraping.ai
8
8
  Generated by: https://openapi-generator.tech
9
- OpenAPI Generator version: 4.3.1
9
+ OpenAPI Generator version: 7.2.0
10
10
 
11
11
  =end
12
12
 
@@ -14,8 +14,10 @@ require 'date'
14
14
  require 'json'
15
15
  require 'logger'
16
16
  require 'tempfile'
17
+ require 'time'
17
18
  require 'typhoeus'
18
19
 
20
+
19
21
  module WebScrapingAI
20
22
  class ApiClient
21
23
  # The Configuration object holding settings to be used in the API client.
@@ -44,9 +46,10 @@ module WebScrapingAI
44
46
  # Call an API with given options.
45
47
  #
46
48
  # @return [Array<(Object, Integer, Hash)>] an array of 3 elements:
47
- # the data deserialized from response body (could be nil), response status code and response headers.
49
+ # the data deserialized from response body (may be a Tempfile or nil), response status code and response headers.
48
50
  def call_api(http_method, path, opts = {})
49
51
  request = build_request(http_method, path, opts)
52
+ tempfile = download_file(request) if opts[:return_type] == 'File'
50
53
  response = request.run
51
54
 
52
55
  if @config.debugging
@@ -68,7 +71,9 @@ module WebScrapingAI
68
71
  end
69
72
  end
70
73
 
71
- if opts[:return_type]
74
+ if opts[:return_type] == 'File'
75
+ data = tempfile
76
+ elsif opts[:return_type]
72
77
  data = deserialize(response, opts[:return_type])
73
78
  else
74
79
  data = nil
@@ -86,12 +91,13 @@ module WebScrapingAI
86
91
  # @option opts [Object] :body HTTP body (JSON/XML)
87
92
  # @return [Typhoeus::Request] A Typhoeus Request
88
93
  def build_request(http_method, path, opts = {})
89
- url = build_request_url(path)
94
+ url = build_request_url(path, opts)
90
95
  http_method = http_method.to_sym.downcase
91
96
 
92
97
  header_params = @default_headers.merge(opts[:header_params] || {})
93
98
  query_params = opts[:query_params] || {}
94
99
  form_params = opts[:form_params] || {}
100
+ follow_location = opts[:follow_location] || true
95
101
 
96
102
  update_params_for_auth! header_params, query_params, opts[:auth_names]
97
103
 
@@ -108,7 +114,8 @@ module WebScrapingAI
108
114
  :ssl_verifyhost => _verify_ssl_host,
109
115
  :sslcert => @config.cert_file,
110
116
  :sslkey => @config.key_file,
111
- :verbose => @config.debugging
117
+ :verbose => @config.debugging,
118
+ :followlocation => follow_location
112
119
  }
113
120
 
114
121
  # set custom cert, if provided
@@ -122,9 +129,7 @@ module WebScrapingAI
122
129
  end
123
130
  end
124
131
 
125
- request = Typhoeus::Request.new(url, req_opts)
126
- download_file(request) if opts[:return_type] == 'File'
127
- request
132
+ Typhoeus::Request.new(url, req_opts)
128
133
  end
129
134
 
130
135
  # Builds the HTTP request body
@@ -155,6 +160,49 @@ module WebScrapingAI
155
160
  data
156
161
  end
157
162
 
163
+ # Save response body into a file in (the defined) temporary folder, using the filename
164
+ # from the "Content-Disposition" header if provided, otherwise a random filename.
165
+ # The response body is written to the file in chunks in order to handle files which
166
+ # size is larger than maximum Ruby String or even larger than the maximum memory a Ruby
167
+ # process can use.
168
+ #
169
+ # @see Configuration#temp_folder_path
170
+ #
171
+ # @return [Tempfile] the tempfile generated
172
+ def download_file(request)
173
+ tempfile = nil
174
+ encoding = nil
175
+ request.on_headers do |response|
176
+ content_disposition = response.headers['Content-Disposition']
177
+ if content_disposition && content_disposition =~ /filename=/i
178
+ filename = content_disposition[/filename=['"]?([^'"\s]+)['"]?/, 1]
179
+ prefix = sanitize_filename(filename)
180
+ else
181
+ prefix = 'download-'
182
+ end
183
+ prefix = prefix + '-' unless prefix.end_with?('-')
184
+ encoding = response.body.encoding
185
+ tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding)
186
+ end
187
+ request.on_body do |chunk|
188
+ chunk.force_encoding(encoding)
189
+ tempfile.write(chunk)
190
+ end
191
+ # run the request to ensure the tempfile is created successfully before returning it
192
+ request.run
193
+ if tempfile
194
+ tempfile.close
195
+ @config.logger.info "Temp file written to #{tempfile.path}, please copy the file to a proper folder "\
196
+ "with e.g. `FileUtils.cp(tempfile.path, '/new/file/path')` otherwise the temp file "\
197
+ "will be deleted automatically with GC. It's also recommended to delete the temp file "\
198
+ "explicitly with `tempfile.delete`"
199
+ else
200
+ fail ApiError.new("Failed to create the tempfile based on the HTTP response from the server: #{request.inspect}")
201
+ end
202
+
203
+ tempfile
204
+ end
205
+
158
206
  # Check if the given MIME is a JSON MIME.
159
207
  # JSON MIME examples:
160
208
  # application/json
@@ -173,15 +221,10 @@ module WebScrapingAI
173
221
  # @param [String] return_type some examples: "User", "Array<User>", "Hash<String, Integer>"
174
222
  def deserialize(response, return_type)
175
223
  body = response.body
176
-
177
- # handle file downloading - return the File instance processed in request callbacks
178
- # note that response body is empty when the file is written in chunks in request on_body callback
179
- return @tempfile if return_type == 'File'
180
-
181
224
  return nil if body.nil? || body.empty?
182
225
 
183
226
  # return response body directly for String return type
184
- return body if return_type == 'String'
227
+ return body.to_s if return_type == 'String'
185
228
 
186
229
  # ensuring a default content type
187
230
  content_type = response.headers['Content-Type'] || 'application/json'
@@ -191,7 +234,7 @@ module WebScrapingAI
191
234
  begin
192
235
  data = JSON.parse("[#{body}]", :symbolize_names => true)[0]
193
236
  rescue JSON::ParserError => e
194
- if %w(String Date DateTime).include?(return_type)
237
+ if %w(String Date Time).include?(return_type)
195
238
  data = body
196
239
  else
197
240
  raise e
@@ -216,9 +259,9 @@ module WebScrapingAI
216
259
  data.to_f
217
260
  when 'Boolean'
218
261
  data == true
219
- when 'DateTime'
262
+ when 'Time'
220
263
  # parse date time (expecting ISO 8601 format)
221
- DateTime.parse data
264
+ Time.parse data
222
265
  when 'Date'
223
266
  # parse date time (expecting ISO 8601 format)
224
267
  Date.parse data
@@ -236,46 +279,9 @@ module WebScrapingAI
236
279
  data.each { |k, v| hash[k] = convert_to_type(v, sub_type) }
237
280
  end
238
281
  else
239
- # models, e.g. Pet
240
- WebScrapingAI.const_get(return_type).build_from_hash(data)
241
- end
242
- end
243
-
244
- # Save response body into a file in (the defined) temporary folder, using the filename
245
- # from the "Content-Disposition" header if provided, otherwise a random filename.
246
- # The response body is written to the file in chunks in order to handle files which
247
- # size is larger than maximum Ruby String or even larger than the maximum memory a Ruby
248
- # process can use.
249
- #
250
- # @see Configuration#temp_folder_path
251
- def download_file(request)
252
- tempfile = nil
253
- encoding = nil
254
- request.on_headers do |response|
255
- content_disposition = response.headers['Content-Disposition']
256
- if content_disposition && content_disposition =~ /filename=/i
257
- filename = content_disposition[/filename=['"]?([^'"\s]+)['"]?/, 1]
258
- prefix = sanitize_filename(filename)
259
- else
260
- prefix = 'download-'
261
- end
262
- prefix = prefix + '-' unless prefix.end_with?('-')
263
- encoding = response.body.encoding
264
- tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding)
265
- @tempfile = tempfile
266
- end
267
- request.on_body do |chunk|
268
- chunk.force_encoding(encoding)
269
- tempfile.write(chunk)
270
- end
271
- request.on_complete do |response|
272
- if tempfile
273
- tempfile.close
274
- @config.logger.info "Temp file written to #{tempfile.path}, please copy the file to a proper folder "\
275
- "with e.g. `FileUtils.cp(tempfile.path, '/new/file/path')` otherwise the temp file "\
276
- "will be deleted automatically with GC. It's also recommended to delete the temp file "\
277
- "explicitly with `tempfile.delete`"
278
- end
282
+ # models (e.g. Pet) or oneOf
283
+ klass = WebScrapingAI.const_get(return_type)
284
+ klass.respond_to?(:openapi_one_of) ? klass.build(data) : klass.build_from_hash(data)
279
285
  end
280
286
  end
281
287
 
@@ -288,13 +294,13 @@ module WebScrapingAI
288
294
  filename.gsub(/.*[\/\\]/, '')
289
295
  end
290
296
 
291
- def build_request_url(path)
297
+ def build_request_url(path, opts = {})
292
298
  # Add leading and trailing slashes to path
293
299
  path = "/#{path}".gsub(/\/+/, '/')
294
- @config.base_url + path
300
+ @config.base_url(opts[:operation]) + path
295
301
  end
296
302
 
297
- # Update hearder and query params based on authentication settings.
303
+ # Update header and query params based on authentication settings.
298
304
  #
299
305
  # @param [Hash] header_params Header parameters
300
306
  # @param [Hash] query_params Query parameters
@@ -306,7 +312,7 @@ module WebScrapingAI
306
312
  case auth_setting[:in]
307
313
  when 'header' then header_params[auth_setting[:key]] = auth_setting[:value]
308
314
  when 'query' then query_params[auth_setting[:key]] = auth_setting[:value]
309
- else fail ArgumentError, 'Authentication token must be in `query` of `header`'
315
+ else fail ArgumentError, 'Authentication token must be in `query` or `header`'
310
316
  end
311
317
  end
312
318
  end
@@ -333,8 +339,8 @@ module WebScrapingAI
333
339
  # @param [Array] content_types array for Content-Type
334
340
  # @return [String] the Content-Type header (e.g. application/json)
335
341
  def select_header_content_type(content_types)
336
- # use application/json by default
337
- return 'application/json' if content_types.nil? || content_types.empty?
342
+ # return nil by default
343
+ return if content_types.nil? || content_types.empty?
338
344
  # use JSON when present, otherwise use the first one
339
345
  json_content_type = content_types.find { |s| json_mime?(s) }
340
346
  json_content_type || content_types.first
@@ -1,12 +1,12 @@
1
1
  =begin
2
2
  #WebScraping.AI
3
3
 
4
- #A client for https://webscraping.ai API. It provides a web scaping automation API with Chrome JS rendering, rotating proxies and builtin HTML parsing.
4
+ #WebScraping.AI scraping API provides GPT-powered tools with Chromium JavaScript rendering, rotating proxies, and built-in HTML parsing.
5
5
 
6
- The version of the OpenAPI document: 2.0.1
6
+ The version of the OpenAPI document: 3.1.2
7
7
  Contact: support@webscraping.ai
8
8
  Generated by: https://openapi-generator.tech
9
- OpenAPI Generator version: 4.3.1
9
+ OpenAPI Generator version: 7.2.0
10
10
 
11
11
  =end
12
12
 
@@ -32,6 +32,7 @@ module WebScrapingAI
32
32
  end
33
33
  else
34
34
  super arg
35
+ @message = arg
35
36
  end
36
37
  end
37
38
 
@@ -1,12 +1,12 @@
1
1
  =begin
2
2
  #WebScraping.AI
3
3
 
4
- #A client for https://webscraping.ai API. It provides a web scaping automation API with Chrome JS rendering, rotating proxies and builtin HTML parsing.
4
+ #WebScraping.AI scraping API provides GPT-powered tools with Chromium JavaScript rendering, rotating proxies, and built-in HTML parsing.
5
5
 
6
- The version of the OpenAPI document: 2.0.1
6
+ The version of the OpenAPI document: 3.1.2
7
7
  Contact: support@webscraping.ai
8
8
  Generated by: https://openapi-generator.tech
9
- OpenAPI Generator version: 4.3.1
9
+ OpenAPI Generator version: 7.2.0
10
10
 
11
11
  =end
12
12
 
@@ -21,6 +21,18 @@ module WebScrapingAI
21
21
  # Defines url base path
22
22
  attr_accessor :base_path
23
23
 
24
+ # Define server configuration index
25
+ attr_accessor :server_index
26
+
27
+ # Define server operation configuration index
28
+ attr_accessor :server_operation_index
29
+
30
+ # Default server variables
31
+ attr_accessor :server_variables
32
+
33
+ # Default server operation variables
34
+ attr_accessor :server_operation_variables
35
+
24
36
  # Defines API keys used with API Key authentications.
25
37
  #
26
38
  # @return [Hash] key: parameter name, value: parameter value (API key)
@@ -50,6 +62,16 @@ module WebScrapingAI
50
62
  # Defines the access token (Bearer) used with OAuth2.
51
63
  attr_accessor :access_token
52
64
 
65
+ # Defines a Proc used to fetch or refresh access tokens (Bearer) used with OAuth2.
66
+ # Overrides the access_token if set
67
+ # @return [Proc]
68
+ attr_accessor :access_token_getter
69
+
70
+ # Set this to return data as binary instead of downloading a temp file. When enabled (set to true)
71
+ # HTTP responses with return type `File` will be returned as a stream of binary data.
72
+ # Default to false.
73
+ attr_accessor :return_binary_data
74
+
53
75
  # Set this to enable/disable debugging. When enabled (set to true), HTTP request/response
54
76
  # details will be logged with `logger.debug` (see the `logger` attribute).
55
77
  # Default to false.
@@ -121,6 +143,7 @@ module WebScrapingAI
121
143
  # https://github.com/typhoeus/ethon/blob/master/lib/ethon/easy/queryable.rb#L96
122
144
  attr_accessor :params_encoding
123
145
 
146
+
124
147
  attr_accessor :inject_format
125
148
 
126
149
  attr_accessor :force_ending_format
@@ -129,15 +152,19 @@ module WebScrapingAI
129
152
  @scheme = 'https'
130
153
  @host = 'api.webscraping.ai'
131
154
  @base_path = ''
155
+ @server_index = nil
156
+ @server_operation_index = {}
157
+ @server_variables = {}
158
+ @server_operation_variables = {}
132
159
  @api_key = {}
133
160
  @api_key_prefix = {}
134
- @timeout = 0
135
161
  @client_side_validation = true
136
162
  @verify_ssl = true
137
163
  @verify_ssl_host = true
138
- @params_encoding = nil
139
164
  @cert_file = nil
140
165
  @key_file = nil
166
+ @timeout = 0
167
+ @params_encoding = nil
141
168
  @debugging = false
142
169
  @inject_format = false
143
170
  @force_ending_format = false
@@ -171,20 +198,34 @@ module WebScrapingAI
171
198
  @base_path = '' if @base_path == '/'
172
199
  end
173
200
 
174
- def base_url
175
- "#{scheme}://#{[host, base_path].join('/').gsub(/\/+/, '/')}".sub(/\/+\z/, '')
201
+ # Returns base URL for specified operation based on server settings
202
+ def base_url(operation = nil)
203
+ if operation_server_settings.key?(operation) then
204
+ index = server_operation_index.fetch(operation, server_index)
205
+ server_url(index.nil? ? 0 : index, server_operation_variables.fetch(operation, server_variables), operation_server_settings[operation])
206
+ else
207
+ server_index.nil? ? "#{scheme}://#{[host, base_path].join('/').gsub(/\/+/, '/')}".sub(/\/+\z/, '') : server_url(server_index, server_variables, nil)
208
+ end
176
209
  end
177
210
 
178
211
  # Gets API key (with prefix if set).
179
212
  # @param [String] param_name the parameter name of API key auth
180
- def api_key_with_prefix(param_name)
213
+ def api_key_with_prefix(param_name, param_alias = nil)
214
+ key = @api_key[param_name]
215
+ key = @api_key.fetch(param_alias, key) unless param_alias.nil?
181
216
  if @api_key_prefix[param_name]
182
- "#{@api_key_prefix[param_name]} #{@api_key[param_name]}"
217
+ "#{@api_key_prefix[param_name]} #{key}"
183
218
  else
184
- @api_key[param_name]
219
+ key
185
220
  end
186
221
  end
187
222
 
223
+ # Gets access_token using access_token_getter or uses the static access_token
224
+ def access_token_with_refresh
225
+ return access_token if access_token_getter.nil?
226
+ access_token_getter.call
227
+ end
228
+
188
229
  # Gets Basic Auth token string
189
230
  def basic_auth_token
190
231
  'Basic ' + ["#{username}:#{password}"].pack('m').delete("\r\n")
@@ -213,25 +254,32 @@ module WebScrapingAI
213
254
  ]
214
255
  end
215
256
 
257
+ def operation_server_settings
258
+ {
259
+ }
260
+ end
261
+
216
262
  # Returns URL based on server settings
217
263
  #
218
264
  # @param index array index of the server settings
219
265
  # @param variables hash of variable and the corresponding value
220
- def server_url(index, variables = {})
221
- servers = server_settings
266
+ def server_url(index, variables = {}, servers = nil)
267
+ servers = server_settings if servers == nil
222
268
 
223
269
  # check array index out of bound
224
- if (index < 0 || index >= servers.size)
225
- fail ArgumentError, "Invalid index #{index} when selecting the server. Must be less than #{servers.size}"
270
+ if (index.nil? || index < 0 || index >= servers.size)
271
+ fail ArgumentError, "Invalid index #{index} when selecting the server. Must not be nil and must be less than #{servers.size}"
226
272
  end
227
273
 
228
274
  server = servers[index]
229
275
  url = server[:url]
230
276
 
277
+ return url unless server.key? :variables
278
+
231
279
  # go through variable and assign a value
232
280
  server[:variables].each do |name, variable|
233
281
  if variables.key?(name)
234
- if (server[:variables][name][:enum_values].include? variables[name])
282
+ if (!server[:variables][name].key?(:enum_values) || server[:variables][name][:enum_values].include?(variables[name]))
235
283
  url.gsub! "{" + name.to_s + "}", variables[name]
236
284
  else
237
285
  fail ArgumentError, "The variable `#{name}` in the server URL has invalid value #{variables[name]}. Must be #{server[:variables][name][:enum_values]}."
@@ -244,5 +292,7 @@ module WebScrapingAI
244
292
 
245
293
  url
246
294
  end
295
+
296
+
247
297
  end
248
298
  end
@@ -1,38 +1,49 @@
1
1
  =begin
2
2
  #WebScraping.AI
3
3
 
4
- #A client for https://webscraping.ai API. It provides a web scaping automation API with Chrome JS rendering, rotating proxies and builtin HTML parsing.
4
+ #WebScraping.AI scraping API provides GPT-powered tools with Chromium JavaScript rendering, rotating proxies, and built-in HTML parsing.
5
5
 
6
- The version of the OpenAPI document: 2.0.1
6
+ The version of the OpenAPI document: 3.1.2
7
7
  Contact: support@webscraping.ai
8
8
  Generated by: https://openapi-generator.tech
9
- OpenAPI Generator version: 4.3.1
9
+ OpenAPI Generator version: 7.2.0
10
10
 
11
11
  =end
12
12
 
13
13
  require 'date'
14
+ require 'time'
14
15
 
15
16
  module WebScrapingAI
16
- class PageError
17
- # Response HTTP status code (403, 500, etc)
18
- attr_accessor :status_code
17
+ class Account
18
+ # Remaining API credits quota
19
+ attr_accessor :remaining_api_calls
19
20
 
20
- # Response HTTP status message
21
- attr_accessor :status_message
21
+ # Next billing cycle start time (UNIX timestamp)
22
+ attr_accessor :resets_at
23
+
24
+ # Remaining concurrent requests
25
+ attr_accessor :remaining_concurrency
22
26
 
23
27
  # Attribute mapping from ruby-style variable name to JSON key.
24
28
  def self.attribute_map
25
29
  {
26
- :'status_code' => :'status_code',
27
- :'status_message' => :'status_message'
30
+ :'remaining_api_calls' => :'remaining_api_calls',
31
+ :'resets_at' => :'resets_at',
32
+ :'remaining_concurrency' => :'remaining_concurrency'
28
33
  }
29
34
  end
30
35
 
36
+ # Returns all the JSON keys this model knows about
37
+ def self.acceptable_attributes
38
+ attribute_map.values
39
+ end
40
+
31
41
  # Attribute type mapping.
32
42
  def self.openapi_types
33
43
  {
34
- :'status_code' => :'Integer',
35
- :'status_message' => :'String'
44
+ :'remaining_api_calls' => :'Integer',
45
+ :'resets_at' => :'Integer',
46
+ :'remaining_concurrency' => :'Integer'
36
47
  }
37
48
  end
38
49
 
@@ -46,29 +57,34 @@ module WebScrapingAI
46
57
  # @param [Hash] attributes Model attributes in the form of hash
47
58
  def initialize(attributes = {})
48
59
  if (!attributes.is_a?(Hash))
49
- fail ArgumentError, "The input argument (attributes) must be a hash in `WebScrapingAI::PageError` initialize method"
60
+ fail ArgumentError, "The input argument (attributes) must be a hash in `WebScrapingAI::Account` initialize method"
50
61
  end
51
62
 
52
63
  # check to see if the attribute exists and convert string to symbol for hash key
53
64
  attributes = attributes.each_with_object({}) { |(k, v), h|
54
65
  if (!self.class.attribute_map.key?(k.to_sym))
55
- fail ArgumentError, "`#{k}` is not a valid attribute in `WebScrapingAI::PageError`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
66
+ fail ArgumentError, "`#{k}` is not a valid attribute in `WebScrapingAI::Account`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
56
67
  end
57
68
  h[k.to_sym] = v
58
69
  }
59
70
 
60
- if attributes.key?(:'status_code')
61
- self.status_code = attributes[:'status_code']
71
+ if attributes.key?(:'remaining_api_calls')
72
+ self.remaining_api_calls = attributes[:'remaining_api_calls']
73
+ end
74
+
75
+ if attributes.key?(:'resets_at')
76
+ self.resets_at = attributes[:'resets_at']
62
77
  end
63
78
 
64
- if attributes.key?(:'status_message')
65
- self.status_message = attributes[:'status_message']
79
+ if attributes.key?(:'remaining_concurrency')
80
+ self.remaining_concurrency = attributes[:'remaining_concurrency']
66
81
  end
67
82
  end
68
83
 
69
84
  # Show invalid properties with the reasons. Usually used together with valid?
70
85
  # @return Array for valid properties with the reasons
71
86
  def list_invalid_properties
87
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
72
88
  invalid_properties = Array.new
73
89
  invalid_properties
74
90
  end
@@ -76,6 +92,7 @@ module WebScrapingAI
76
92
  # Check to see if the all the properties in the model are valid
77
93
  # @return true if the model is valid
78
94
  def valid?
95
+ warn '[DEPRECATED] the `valid?` method is obsolete'
79
96
  true
80
97
  end
81
98
 
@@ -84,8 +101,9 @@ module WebScrapingAI
84
101
  def ==(o)
85
102
  return true if self.equal?(o)
86
103
  self.class == o.class &&
87
- status_code == o.status_code &&
88
- status_message == o.status_message
104
+ remaining_api_calls == o.remaining_api_calls &&
105
+ resets_at == o.resets_at &&
106
+ remaining_concurrency == o.remaining_concurrency
89
107
  end
90
108
 
91
109
  # @see the `==` method
@@ -97,44 +115,40 @@ module WebScrapingAI
97
115
  # Calculates hash code according to all attributes.
98
116
  # @return [Integer] Hash code
99
117
  def hash
100
- [status_code, status_message].hash
118
+ [remaining_api_calls, resets_at, remaining_concurrency].hash
101
119
  end
102
120
 
103
121
  # Builds the object from hash
104
122
  # @param [Hash] attributes Model attributes in the form of hash
105
123
  # @return [Object] Returns the model itself
106
124
  def self.build_from_hash(attributes)
107
- new.build_from_hash(attributes)
108
- end
109
-
110
- # Builds the object from hash
111
- # @param [Hash] attributes Model attributes in the form of hash
112
- # @return [Object] Returns the model itself
113
- def build_from_hash(attributes)
114
125
  return nil unless attributes.is_a?(Hash)
115
- self.class.openapi_types.each_pair do |key, type|
116
- if type =~ /\AArray<(.*)>/i
126
+ attributes = attributes.transform_keys(&:to_sym)
127
+ transformed_hash = {}
128
+ openapi_types.each_pair do |key, type|
129
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
130
+ transformed_hash["#{key}"] = nil
131
+ elsif type =~ /\AArray<(.*)>/i
117
132
  # check to ensure the input is an array given that the attribute
118
133
  # is documented as an array but the input is not
119
- if attributes[self.class.attribute_map[key]].is_a?(Array)
120
- self.send("#{key}=", attributes[self.class.attribute_map[key]].map { |v| _deserialize($1, v) })
134
+ if attributes[attribute_map[key]].is_a?(Array)
135
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
121
136
  end
122
- elsif !attributes[self.class.attribute_map[key]].nil?
123
- self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
124
- end # or else data not found in attributes(hash), not an issue as the data can be optional
137
+ elsif !attributes[attribute_map[key]].nil?
138
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
139
+ end
125
140
  end
126
-
127
- self
141
+ new(transformed_hash)
128
142
  end
129
143
 
130
144
  # Deserializes the data based on type
131
145
  # @param string type Data type
132
146
  # @param string value Value to be deserialized
133
147
  # @return [Object] Deserialized data
134
- def _deserialize(type, value)
148
+ def self._deserialize(type, value)
135
149
  case type.to_sym
136
- when :DateTime
137
- DateTime.parse(value)
150
+ when :Time
151
+ Time.parse(value)
138
152
  when :Date
139
153
  Date.parse(value)
140
154
  when :String
@@ -164,7 +178,9 @@ module WebScrapingAI
164
178
  end
165
179
  end
166
180
  else # model
167
- WebScrapingAI.const_get(type).build_from_hash(value)
181
+ # models (e.g. Pet) or oneOf
182
+ klass = WebScrapingAI.const_get(type)
183
+ klass.respond_to?(:openapi_any_of) || klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
168
184
  end
169
185
  end
170
186
 
@@ -190,7 +206,7 @@ module WebScrapingAI
190
206
  is_nullable = self.class.openapi_nullable.include?(attr)
191
207
  next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
192
208
  end
193
-
209
+
194
210
  hash[param] = _to_hash(value)
195
211
  end
196
212
  hash
@@ -213,5 +229,7 @@ module WebScrapingAI
213
229
  value
214
230
  end
215
231
  end
232
+
216
233
  end
234
+
217
235
  end