zendesk_api 3.1.1 → 4.0.0.pre.1

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/zendesk_api/actions.rb +31 -31
  3. data/lib/zendesk_api/association.rb +8 -8
  4. data/lib/zendesk_api/associations.rb +30 -30
  5. data/lib/zendesk_api/client.rb +69 -36
  6. data/lib/zendesk_api/collection.rb +41 -40
  7. data/lib/zendesk_api/configuration.rb +11 -8
  8. data/lib/zendesk_api/core_ext/inflection.rb +2 -2
  9. data/lib/zendesk_api/delegator.rb +1 -1
  10. data/lib/zendesk_api/helpers.rb +10 -10
  11. data/lib/zendesk_api/middleware/request/api_token_impersonate.rb +29 -0
  12. data/lib/zendesk_api/middleware/request/encode_json.rb +3 -4
  13. data/lib/zendesk_api/middleware/request/etag_cache.rb +27 -4
  14. data/lib/zendesk_api/middleware/request/raise_rate_limited.rb +3 -3
  15. data/lib/zendesk_api/middleware/request/retry.rb +56 -20
  16. data/lib/zendesk_api/middleware/request/upload.rb +1 -1
  17. data/lib/zendesk_api/middleware/request/url_based_access_token.rb +2 -2
  18. data/lib/zendesk_api/middleware/response/deflate.rb +1 -1
  19. data/lib/zendesk_api/middleware/response/gzip.rb +3 -3
  20. data/lib/zendesk_api/middleware/response/logger.rb +3 -3
  21. data/lib/zendesk_api/middleware/response/parse_iso_dates.rb +1 -1
  22. data/lib/zendesk_api/middleware/response/parse_json.rb +3 -3
  23. data/lib/zendesk_api/middleware/response/raise_error.rb +1 -1
  24. data/lib/zendesk_api/middleware/response/sanitize_response.rb +1 -1
  25. data/lib/zendesk_api/middleware/response/zendesk_request_event.rb +72 -0
  26. data/lib/zendesk_api/pagination.rb +3 -3
  27. data/lib/zendesk_api/resource.rb +16 -24
  28. data/lib/zendesk_api/resources.rb +84 -80
  29. data/lib/zendesk_api/search.rb +6 -6
  30. data/lib/zendesk_api/silent_mash.rb +1 -1
  31. data/lib/zendesk_api/track_changes.rb +2 -2
  32. data/lib/zendesk_api/trackie.rb +3 -3
  33. data/lib/zendesk_api/version.rb +1 -1
  34. data/lib/zendesk_api.rb +5 -5
  35. data/util/resource_handler.rb +5 -5
  36. data/util/verb_handler.rb +1 -1
  37. metadata +27 -16
@@ -1,7 +1,7 @@
1
- require 'zendesk_api/resource'
2
- require 'zendesk_api/resources'
3
- require 'zendesk_api/search'
4
- require 'zendesk_api/pagination'
1
+ require_relative "resource"
2
+ require_relative "resources"
3
+ require_relative "search"
4
+ require_relative "pagination"
5
5
 
6
6
  module ZendeskAPI
7
7
  # Represents a collection of resources. Lazily loaded, resources aren't
@@ -50,8 +50,8 @@ module ZendeskAPI
50
50
  end
51
51
 
52
52
  # Methods that take a Hash argument
53
- methods = %w{create find update update_many destroy create_or_update}
54
- methods += methods.map { |method| method + "!" }
53
+ methods = %w[create find update update_many destroy create_or_update]
54
+ methods += methods.map { |method| "#{method}!" }
55
55
  methods.each do |deferrable|
56
56
  # Passes arguments and the proper path to the resource class method.
57
57
  # @param [Hash] options Options or attributes to pass
@@ -61,14 +61,14 @@ module ZendeskAPI
61
61
  end
62
62
 
63
63
  args << {} unless args.last.is_a?(Hash)
64
- args.last.merge!(:association => @association)
64
+ args.last[:association] = @association
65
65
 
66
66
  @resource_class.send(deferrable, @client, *args)
67
67
  end
68
68
  end
69
69
 
70
70
  # Methods that take an Array argument
71
- methods = %w{create_many! destroy_many!}
71
+ methods = %w[create_many! destroy_many!]
72
72
  methods.each do |deferrable|
73
73
  # Passes arguments and the proper path to the resource class method.
74
74
  # @param [Array] array arguments
@@ -153,7 +153,7 @@ module ZendeskAPI
153
153
 
154
154
  # The API path to this collection
155
155
  def path
156
- @association.generate_path(:with_parent => true)
156
+ @association.generate_path(with_parent: true)
157
157
  end
158
158
 
159
159
  # Executes actual GET from API and loads resources into proper class.
@@ -161,7 +161,7 @@ module ZendeskAPI
161
161
  def fetch!(reload = false)
162
162
  if @resources && (!@fetchable || !reload)
163
163
  return @resources
164
- elsif association && association.options.parent && association.options.parent.new_record?
164
+ elsif association&.options&.parent&.new_record?
165
165
  return (@resources = [])
166
166
  end
167
167
 
@@ -188,24 +188,24 @@ module ZendeskAPI
188
188
 
189
189
  # Calls #each on every page with the passed in block
190
190
  # @param [Block] block Passed to #each
191
- def all!(start_page = @options["page"], &block)
192
- _all(start_page, :bang, &block)
191
+ def all!(start_page = @options["page"], &)
192
+ _all(start_page, :bang, &)
193
193
  end
194
194
 
195
195
  # Calls #each on every page with the passed in block
196
196
  # @param [Block] block Passed to #each
197
- def all(start_page = @options["page"], &block)
198
- _all(start_page, &block)
197
+ def all(start_page = @options["page"], &)
198
+ _all(start_page, &)
199
199
  end
200
200
 
201
- def each_page!(*args, &block)
201
+ def each_page!(...)
202
202
  warn "ZendeskAPI::Collection#each_page! is deprecated, please use ZendeskAPI::Collection#all!"
203
- all!(*args, &block)
203
+ all!(...)
204
204
  end
205
205
 
206
- def each_page(*args, &block)
206
+ def each_page(...)
207
207
  warn "ZendeskAPI::Collection#each_page is deprecated, please use ZendeskAPI::Collection#all"
208
- all(*args, &block)
208
+ all(...)
209
209
  end
210
210
 
211
211
  # Replaces the current (loaded or not) resources with the passed in collection
@@ -271,13 +271,13 @@ module ZendeskAPI
271
271
  end
272
272
 
273
273
  # Sends methods to underlying array of resources.
274
- def method_missing(name, *args, &block)
274
+ def method_missing(name, ...)
275
275
  if resource_methods.include?(name)
276
- collection_method(name, *args, &block)
276
+ collection_method(name, ...)
277
277
  elsif [].respond_to?(name, false)
278
- array_method(name, *args, &block)
278
+ array_method(name, ...)
279
279
  else
280
- next_collection(name, *args, &block)
280
+ next_collection(name, ...)
281
281
  end
282
282
  end
283
283
 
@@ -289,11 +289,11 @@ module ZendeskAPI
289
289
  inspect = []
290
290
  inspect << "options=#{@options.inspect}" if @options.any?
291
291
  inspect << "path=#{path}"
292
- "#{Inflection.singular(@resource)} collection [#{inspect.join(',')}]"
292
+ "#{Inflection.singular(@resource)} collection [#{inspect.join(",")}]"
293
293
  end
294
294
  end
295
295
 
296
- alias to_str to_s
296
+ alias_method :to_str, :to_s
297
297
 
298
298
  def to_param
299
299
  map(&:to_param)
@@ -303,7 +303,7 @@ module ZendeskAPI
303
303
  link = original_response_body["links"]["next"]
304
304
  result_key = @resource_class.model_key || "results"
305
305
  while link
306
- response = @client.connection.send("get", link).body
306
+ response = @client.connection.send(:get, link).body
307
307
 
308
308
  original_response_body[result_key] = original_response_body[result_key] + response[result_key]
309
309
 
@@ -338,7 +338,7 @@ module ZendeskAPI
338
338
  page(start_page)
339
339
  clear_cache
340
340
 
341
- while (bang ? fetch! : fetch)
341
+ while bang ? fetch! : fetch
342
342
  each do |resource|
343
343
  block.call(resource, @options["page"] || 1)
344
344
  end
@@ -370,7 +370,7 @@ module ZendeskAPI
370
370
  # some params use comma-joined strings instead of query-based arrays for multiple values
371
371
  @options.each do |k, v|
372
372
  if SPECIALLY_JOINED_PARAMS.include?(k.to_sym) && v.is_a?(Array)
373
- @options[k] = v.join(',')
373
+ @options[k] = v.join(",")
374
374
  end
375
375
  end
376
376
  end
@@ -378,9 +378,9 @@ module ZendeskAPI
378
378
  def set_association_from_options
379
379
  @collection_path = @options.delete(:collection_path)
380
380
 
381
- association_options = { :path => @options.delete(:path) }
381
+ association_options = {path: @options.delete(:path)}
382
382
  association_options[:path] ||= @collection_path.join("/") if @collection_path
383
- @association = @options.delete(:association) || Association.new(association_options.merge(:class => @resource_class))
383
+ @association = @options.delete(:association) || Association.new(association_options.merge(class: @resource_class))
384
384
  @collection_path ||= [@resource]
385
385
  end
386
386
 
@@ -389,9 +389,9 @@ module ZendeskAPI
389
389
  @client.connection.send(@verb || "get", path) do |req|
390
390
  opts = @options.delete_if { |_, v| v.nil? }
391
391
 
392
- req.params.merge!(:include => @includes.join(",")) if @includes.any?
392
+ req.params[:include] = @includes.join(",") if @includes.any?
393
393
 
394
- if %w{put post}.include?(@verb.to_s)
394
+ if %w[put post].include?(@verb.to_s)
395
395
  req.body = opts
396
396
  else
397
397
  req.params.merge!(opts)
@@ -440,11 +440,11 @@ module ZendeskAPI
440
440
  when Array
441
441
  wrap_resource(Hash[*res], with_association)
442
442
  when Hash
443
- res = res.merge(:association => @association) if with_association
443
+ res = res.merge(association: @association) if with_association
444
444
  @resource_class.new(@client, res)
445
445
  else
446
- res = { :id => res }
447
- res.merge!(:association => @association) if with_association
446
+ res = {id: res}
447
+ res[:association] = @association if with_association
448
448
  @resource_class.new(@client, res)
449
449
  end
450
450
  end
@@ -457,22 +457,23 @@ module ZendeskAPI
457
457
 
458
458
  ## Method missing
459
459
 
460
- def array_method(name, *args, &block)
461
- to_a.public_send(name, *args, &block)
460
+ def array_method(name, ...)
461
+ to_a.public_send(name, ...)
462
462
  end
463
463
 
464
464
  # If you call client.tickets.foo - and foo is not an attribute nor an association, it ends up here, as a new collection
465
- def next_collection(name, *args, &block)
465
+ def next_collection(name, *args, &)
466
466
  opts = args.last.is_a?(Hash) ? args.last : {}
467
- opts.merge!(collection_path: [*@collection_path, name], page: nil)
467
+ opts[:collection_path] = [*@collection_path, name]
468
+ opts[:page] = nil
468
469
  # Why `page: nil`?
469
470
  # when you do client.tickets.fetch followed by client.tickets.foos => the request to /tickets/foos will
470
471
  # have the options page set to whatever the last options were for the tickets collection
471
472
  self.class.new(@client, @resource_class, @options.merge(opts))
472
473
  end
473
474
 
474
- def collection_method(name, *args, &block)
475
- @resource_class.send(name, @client, *args, &block)
475
+ def collection_method(name, ...)
476
+ @resource_class.send(name, @client, ...)
476
477
  end
477
478
 
478
479
  def resource_methods
@@ -54,6 +54,9 @@ module ZendeskAPI
54
54
  # specify if you want a (network layer) exception to elicit a retry
55
55
  attr_accessor :retry_on_exception
56
56
 
57
+ # specify if you want instrumentation to be used
58
+ attr_accessor :instrumentation
59
+
57
60
  def initialize
58
61
  @client_options = {}
59
62
  @use_resource_cache = true
@@ -66,16 +69,16 @@ module ZendeskAPI
66
69
  # @return [Hash] Faraday-formatted hash of options.
67
70
  def options
68
71
  {
69
- :headers => {
70
- :accept => 'application/json',
71
- :accept_encoding => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
72
- :user_agent => "ZendeskAPI Ruby #{ZendeskAPI::VERSION}"
72
+ headers: {
73
+ accept: "application/json",
74
+ accept_encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3",
75
+ user_agent: "ZendeskAPI Ruby #{ZendeskAPI::VERSION}"
73
76
  },
74
- :request => {
75
- :open_timeout => 10,
76
- :timeout => 60
77
+ request: {
78
+ open_timeout: 10,
79
+ timeout: 60
77
80
  },
78
- :url => @url
81
+ url: @url
79
82
  }.merge(client_options)
80
83
  end
81
84
  end
@@ -1,3 +1,3 @@
1
- require 'inflection'
1
+ require "inflection"
2
2
 
3
- Inflection.plural_rule 'forum', 'forums'
3
+ Inflection.plural_rule "forum", "forums"
@@ -1,4 +1,4 @@
1
- require 'delegate'
1
+ require "delegate"
2
2
 
3
3
  module ZendeskAPI
4
4
  class Delegator < SimpleDelegator; end
@@ -21,10 +21,10 @@ module ZendeskAPI
21
21
  # @return [string] a string that can become a class, `Module::ClassName`
22
22
  def self.modulize_string(string)
23
23
  # gsub('__','/'). # why was this ever here?
24
- string.gsub(/__(.?)/) { "::#{$1.upcase}" }.
25
- gsub(/\/(.?)/) { "::#{$1.upcase}" }.
26
- gsub(/(?:_+|-+)([a-z])/) { $1.upcase }.
27
- gsub(/(\A|\s)([a-z])/) { $1 + $2.upcase }
24
+ string.gsub(/__(.?)/) { "::#{$1.upcase}" }
25
+ .gsub(/\/(.?)/) { "::#{$1.upcase}" }
26
+ .gsub(/(?:_+|-+)([a-z])/) { $1.upcase }
27
+ .gsub(/(\A|\s)([a-z])/) { $1 + $2.upcase }
28
28
  end
29
29
 
30
30
  # From https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/snakecase.rb
@@ -38,12 +38,12 @@ module ZendeskAPI
38
38
  # "Snake - Case".snakecase #=> "snake_case"
39
39
  def self.snakecase_string(string)
40
40
  # gsub(/::/, '/').
41
- string.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
42
- gsub(/([a-z\d])([A-Z])/, '\1_\2').
43
- tr('-', '_').
44
- gsub(/\s/, '_').
45
- gsub(/__+/, '_').
46
- downcase
41
+ string.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
42
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
43
+ .tr("-", "_")
44
+ .gsub(/\s/, "_")
45
+ .gsub(/__+/, "_")
46
+ .downcase
47
47
  end
48
48
  end
49
49
  end
@@ -0,0 +1,29 @@
1
+ require "base64"
2
+
3
+ module ZendeskAPI
4
+ # @private
5
+ module Middleware
6
+ # @private
7
+ module Request
8
+ # ApiTokenImpersonate
9
+ # If Thread.current[:zendesk_thread_local_username] is set, it will modify the Authorization header
10
+ # to impersonate that user using the API token from the current Authorization header.
11
+ class ApiTokenImpersonate < Faraday::Middleware
12
+ def call(env)
13
+ if Thread.current[:zendesk_thread_local_username] && env[:request_headers][:authorization] =~ /^Basic /
14
+ current_u_p_encoded = env[:request_headers][:authorization].split(/\s+/)[1]
15
+ current_u_p = Base64.urlsafe_decode64(current_u_p_encoded)
16
+ unless current_u_p.include?("/token:") && (parts = current_u_p.split(":")) && parts.length == 2 && parts[0].include?("/token")
17
+ warn "WARNING: ApiTokenImpersonate passed in invalid format. It should be in the format username/token:APITOKEN"
18
+ return @app.call(env)
19
+ end
20
+
21
+ next_u_p = "#{Thread.current[:zendesk_thread_local_username]}/token:#{parts[1]}"
22
+ env[:request_headers][:authorization] = "Basic #{Base64.urlsafe_encode64(next_u_p)}"
23
+ end
24
+ @app.call(env)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -4,13 +4,12 @@ module ZendeskAPI
4
4
  # @private
5
5
  module Request
6
6
  class EncodeJson < Faraday::Middleware
7
- CONTENT_TYPE = 'Content-Type'.freeze
8
- MIME_TYPE = 'application/json'.freeze
7
+ CONTENT_TYPE = "Content-Type".freeze
8
+ MIME_TYPE = "application/json".freeze
9
9
 
10
10
  def call(env)
11
11
  type = env[:request_headers][CONTENT_TYPE].to_s
12
- type = type.split(';', 2).first if type.index(';')
13
- type
12
+ type = type.split(";", 2).first if type.index(";")
14
13
 
15
14
  if env[:body] && !(env[:body].respond_to?(:to_str) && env[:body].empty?) && (type.empty? || type == MIME_TYPE)
16
15
  env[:body] = JSON.dump(env[:body])
@@ -9,6 +9,7 @@ module ZendeskAPI
9
9
  class EtagCache < Faraday::Middleware
10
10
  def initialize(app, options = {})
11
11
  @app = app
12
+ @instrumentation = options[:instrumentation] if options[:instrumentation].respond_to?(:instrument)
12
13
  @cache = options[:cache] ||
13
14
  raise("need :cache option e.g. ActiveSupport::Cache::MemoryStore.new")
14
15
  @cache_key_prefix = options.fetch(:cache_key_prefix, :faraday_etags)
@@ -36,13 +37,35 @@ module ZendeskAPI
36
37
  env[:response_body] = cached[:response_body]
37
38
 
38
39
  env[:response_headers].merge!(
39
- :etag => cached[:response_headers][:etag],
40
- :content_type => cached[:response_headers][:content_type],
41
- :content_length => cached[:response_headers][:content_length],
42
- :content_encoding => cached[:response_headers][:content_encoding]
40
+ etag: cached[:response_headers][:etag],
41
+ content_type: cached[:response_headers][:content_type],
42
+ content_length: cached[:response_headers][:content_length],
43
+ content_encoding: cached[:response_headers][:content_encoding]
43
44
  )
45
+ if @instrumentation
46
+ begin
47
+ @instrumentation.instrument("zendesk.cache_hit",
48
+ {
49
+ endpoint: env[:url]&.path,
50
+ status: env[:status]
51
+ })
52
+ rescue
53
+ # Swallow instrumentation errors to maintain cache behavior
54
+ end
55
+ end
44
56
  elsif env[:status] == 200 && env[:response_headers]["Etag"] # modified and cacheable
45
57
  @cache.write(cache_key(env), env.to_hash)
58
+ if @instrumentation
59
+ begin
60
+ @instrumentation.instrument("zendesk.cache_miss",
61
+ {
62
+ endpoint: env[:url]&.path,
63
+ status: env[:status]
64
+ })
65
+ rescue
66
+ # Swallow instrumentation errors to maintain cache behavior
67
+ end
68
+ end
46
69
  end
47
70
  end
48
71
  end
@@ -1,5 +1,5 @@
1
- require 'faraday/middleware'
2
- require 'zendesk_api/error'
1
+ require "faraday/middleware"
2
+ require_relative "../../error"
3
3
 
4
4
  module ZendeskAPI
5
5
  module Middleware
@@ -19,7 +19,7 @@ module ZendeskAPI
19
19
  response = @app.call(env)
20
20
 
21
21
  if ERROR_CODES.include?(response.env[:status])
22
- @logger&.warn 'You have been rate limited. Raising error...'
22
+ @logger&.warn "You have been rate limited. Raising error..."
23
23
  raise Error::RateLimited, env
24
24
  else
25
25
  response
@@ -1,4 +1,5 @@
1
1
  require "faraday/middleware"
2
+
2
3
  module ZendeskAPI
3
4
  module Middleware
4
5
  # @private
@@ -12,46 +13,81 @@ module ZendeskAPI
12
13
  def initialize(app, options = {})
13
14
  super(app)
14
15
  @logger = options[:logger]
15
- @error_codes = options.key?(:retry_codes) && options[:retry_codes] ? options[:retry_codes] : DEFAULT_ERROR_CODES
16
- @retry_on_exception = options.key?(:retry_on_exception) && options[:retry_on_exception] ? options[:retry_on_exception] : false
16
+ @error_codes = (options.key?(:retry_codes) && options[:retry_codes]) ? options[:retry_codes] : DEFAULT_ERROR_CODES
17
+ @retry_on_exception = (options.key?(:retry_on_exception) && options[:retry_on_exception]) ? options[:retry_on_exception] : false
18
+ @instrumentation = options[:instrumentation]
17
19
  end
18
20
 
19
21
  def call(env)
22
+ # Duplicate env for retries but keep attempt counter persistent
20
23
  original_env = env.dup
24
+ original_env[:call_attempt] = (env[:call_attempt] || 0)
25
+
21
26
  exception_happened = false
27
+ response = nil
28
+
22
29
  if @retry_on_exception
23
30
  begin
24
31
  response = @app.call(env)
25
- rescue StandardError => e
32
+ rescue => ex
26
33
  exception_happened = true
34
+ exception = ex
27
35
  end
28
36
  else
37
+ # Allow exceptions to propagate normally when not retrying
29
38
  response = @app.call(env)
30
39
  end
31
40
 
32
- if exception_happened || @error_codes.include?(response.env[:status])
41
+ if exception_happened
42
+ original_env[:call_attempt] += 1
43
+ seconds_left = DEFAULT_RETRY_AFTER.to_i
44
+ @logger&.warn "An exception happened, waiting #{seconds_left} seconds... #{exception}"
45
+ instrument_retry(original_env, "exception", seconds_left)
46
+ sleep_with_logging(seconds_left)
47
+ return @app.call(original_env)
48
+ end
33
49
 
34
- if exception_happened
35
- seconds_left = DEFAULT_RETRY_AFTER.to_i
36
- @logger.warn "An exception happened, waiting #{seconds_left} seconds... #{e}" if @logger
37
- else
38
- seconds_left = (response.env[:response_headers][:retry_after] || DEFAULT_RETRY_AFTER).to_i
39
- end
50
+ # Retry once if response has a retryable error code
51
+ if response && @error_codes.include?(response.env[:status])
52
+ original_env[:call_attempt] += 1
53
+ seconds_left = (response.env[:response_headers][:retry_after] || DEFAULT_RETRY_AFTER).to_i
54
+ @logger&.warn "You may have been rate limited. Retrying in #{seconds_left} seconds..."
55
+ instrument_retry(original_env, (response.env[:status] == 429) ? "rate_limited" : "server_error", seconds_left)
56
+ sleep_with_logging(seconds_left)
57
+ response = @app.call(original_env)
58
+ end
40
59
 
41
- @logger.warn "You have been rate limited. Retrying in #{seconds_left} seconds..." if @logger
60
+ response
61
+ end
42
62
 
43
- seconds_left.times do |i|
44
- sleep 1
45
- time_left = seconds_left - i
46
- @logger.warn "#{time_left}..." if time_left > 0 && time_left % 5 == 0 && @logger
47
- end
63
+ private
48
64
 
49
- @logger.warn "" if @logger
65
+ def instrument_retry(env, reason, delay)
66
+ return unless @instrumentation
50
67
 
51
- @app.call(original_env)
52
- else
53
- response
68
+ begin
69
+ @instrumentation.instrument(
70
+ "zendesk.retry",
71
+ {
72
+ attempt: env[:call_attempt],
73
+ endpoint: env[:url]&.path,
74
+ method: env[:method],
75
+ reason: reason,
76
+ delay: delay
77
+ }
78
+ )
79
+ rescue => e
80
+ @logger&.debug("zendesk.retry instrumentation failed: #{e.message}")
81
+ end
82
+ end
83
+
84
+ def sleep_with_logging(seconds_left)
85
+ seconds_left.times do |i|
86
+ sleep 1
87
+ time_left = seconds_left - i
88
+ @logger&.warn "#{time_left}..." if time_left > 0 && time_left % 5 == 0
54
89
  end
90
+ @logger&.warn "" if seconds_left > 0
55
91
  end
56
92
  end
57
93
  end
@@ -1,6 +1,6 @@
1
1
  require "faraday/middleware"
2
2
  require "mini_mime"
3
- require 'tempfile'
3
+ require "tempfile"
4
4
 
5
5
  module ZendeskAPI
6
6
  module Middleware
@@ -11,9 +11,9 @@ module ZendeskAPI
11
11
 
12
12
  def call(env)
13
13
  if env[:url].query
14
- env[:url].query += '&'
14
+ env[:url].query += "&"
15
15
  else
16
- env[:url].query = ''
16
+ env[:url].query = ""
17
17
  end
18
18
 
19
19
  env[:url].query += "access_token=#{@token}"
@@ -7,7 +7,7 @@ module ZendeskAPI
7
7
  # @private
8
8
  class Deflate < Faraday::Middleware
9
9
  def on_complete(env)
10
- return if env[:response_headers]['content-encoding'] != "deflate"
10
+ return if env[:response_headers]["content-encoding"] != "deflate"
11
11
  return if env.body.strip.empty?
12
12
 
13
13
  env.body = Zlib::Inflate.inflate(env.body)
@@ -1,5 +1,5 @@
1
- require 'zlib'
2
- require 'stringio'
1
+ require "zlib"
2
+ require "stringio"
3
3
 
4
4
  module ZendeskAPI
5
5
  # @private
@@ -9,7 +9,7 @@ module ZendeskAPI
9
9
  # Faraday middleware to handle content-encoding = gzip
10
10
  class Gzip < Faraday::Middleware
11
11
  def on_complete(env)
12
- return if env[:response_headers]['content-encoding'] != "gzip"
12
+ return if env[:response_headers]["content-encoding"] != "gzip"
13
13
  return if env[:body].force_encoding(Encoding::BINARY).strip.empty?
14
14
 
15
15
  env[:body] = Zlib::GzipReader.new(StringIO.new(env[:body])).read
@@ -10,13 +10,13 @@ module ZendeskAPI
10
10
  super(app)
11
11
 
12
12
  @logger = logger || begin
13
- require 'logger'
14
- ::Logger.new(STDOUT)
13
+ require "logger"
14
+ ::Logger.new($stdout)
15
15
  end
16
16
  end
17
17
 
18
18
  def call(env)
19
- @logger.info "#{env[:method]} #{env[:url].to_s}"
19
+ @logger.info "#{env[:method]} #{env[:url]}"
20
20
  @logger.debug dump_debug(env, :request_headers)
21
21
 
22
22
  @app.call(env).on_complete do |env|
@@ -1,4 +1,4 @@
1
- require 'time'
1
+ require "time"
2
2
  require "faraday/response"
3
3
 
4
4
  module ZendeskAPI
@@ -4,13 +4,13 @@ module ZendeskAPI
4
4
  # @private
5
5
  module Response
6
6
  class ParseJson < Faraday::Middleware
7
- CONTENT_TYPE = 'Content-Type'.freeze
7
+ CONTENT_TYPE = "Content-Type".freeze
8
8
 
9
9
  def on_complete(env)
10
10
  type = env[:response_headers][CONTENT_TYPE].to_s
11
- type = type.split(';', 2).first if type.index(';')
11
+ type = type.split(";", 2).first if type.index(";")
12
12
 
13
- return unless type == 'application/json'
13
+ return unless type == "application/json"
14
14
 
15
15
  unless env[:body].strip.empty?
16
16
  env[:body] = JSON.parse(env[:body])
@@ -1,4 +1,4 @@
1
- require 'zendesk_api/error'
1
+ require_relative "../../error"
2
2
 
3
3
  module ZendeskAPI
4
4
  module Middleware
@@ -3,7 +3,7 @@ module ZendeskAPI
3
3
  module Response
4
4
  class SanitizeResponse < Faraday::Middleware
5
5
  def on_complete(env)
6
- env[:body].scrub!('')
6
+ env[:body].scrub!("")
7
7
  end
8
8
  end
9
9
  end