supportify_client 0.0.4 → 1.0.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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -4
  3. data/Gemfile.lock +47 -39
  4. data/Rakefile +4 -4
  5. data/VERSION +1 -1
  6. data/lib/supportify_client/api/supportify_api.rb +560 -0
  7. data/lib/supportify_client/api_client.rb +271 -0
  8. data/lib/supportify_client/api_error.rb +24 -0
  9. data/lib/supportify_client/configuration.rb +187 -0
  10. data/lib/supportify_client/models/base_object.rb +87 -0
  11. data/lib/supportify_client/models/category.rb +53 -0
  12. data/lib/supportify_client/models/error.rb +53 -0
  13. data/lib/supportify_client/models/faq.rb +161 -0
  14. data/lib/supportify_client/models/info.rb +45 -0
  15. data/lib/supportify_client/models/tag.rb +53 -0
  16. data/lib/supportify_client/models/user.rb +45 -0
  17. data/lib/supportify_client.rb +30 -14
  18. data/spec/features/.gitkeep +0 -0
  19. data/supportify_client.gemspec +27 -27
  20. metadata +38 -26
  21. data/lib/supportify_client/api/category.rb +0 -17
  22. data/lib/supportify_client/api/error.rb +0 -13
  23. data/lib/supportify_client/api/faq.rb +0 -23
  24. data/lib/supportify_client/api/search.rb +0 -9
  25. data/lib/supportify_client/api/tag.rb +0 -17
  26. data/lib/supportify_client/api.rb +0 -5
  27. data/lib/supportify_client/client.rb +0 -49
  28. data/lib/supportify_client/factory.rb +0 -29
  29. data/lib/supportify_client/gateway.rb +0 -32
  30. data/lib/supportify_client/repository.rb +0 -23
  31. data/spec/features/categories_spec.rb +0 -55
  32. data/spec/features/client_spec.rb +0 -50
  33. data/spec/features/errors_spec.rb +0 -96
  34. data/spec/features/faqs_spec.rb +0 -55
  35. data/spec/features/search_spec.rb +0 -29
  36. data/spec/features/tags_spec.rb +0 -55
@@ -0,0 +1,271 @@
1
+ require 'date'
2
+ require 'json'
3
+ require 'logger'
4
+ require 'tempfile'
5
+ require 'typhoeus'
6
+ require 'uri'
7
+
8
+ module Supportify
9
+ class ApiClient
10
+
11
+ attr_accessor :host
12
+
13
+ # Defines the headers to be used in HTTP requests of all API calls by default.
14
+ #
15
+ # @return [Hash]
16
+ attr_accessor :default_headers
17
+
18
+ # Stores the HTTP response from the last API call using this API client.
19
+ attr_accessor :last_response
20
+
21
+ def initialize(host = nil)
22
+ @host = host || Configuration.base_url
23
+ @format = 'json'
24
+ @user_agent = "ruby-swagger-#{VERSION}"
25
+ @default_headers = {
26
+ 'Content-Type' => "application/#{@format.downcase}",
27
+ 'User-Agent' => @user_agent
28
+ }
29
+ end
30
+
31
+ def call_api(http_method, path, opts = {})
32
+ request = build_request(http_method, path, opts)
33
+ response = request.run
34
+
35
+ # record as last response
36
+ @last_response = response
37
+
38
+ if Configuration.debugging
39
+ Configuration.logger.debug "HTTP response body ~BEGIN~\n#{response.body}\n~END~\n"
40
+ end
41
+
42
+ unless response.success?
43
+ fail ApiError.new(:code => response.code,
44
+ :response_headers => response.headers,
45
+ :response_body => response.body),
46
+ response.status_message
47
+ end
48
+
49
+ if opts[:return_type]
50
+ deserialize(response, opts[:return_type])
51
+ else
52
+ nil
53
+ end
54
+ end
55
+
56
+ def build_request(http_method, path, opts = {})
57
+ url = build_request_url(path)
58
+ http_method = http_method.to_sym.downcase
59
+
60
+ header_params = @default_headers.merge(opts[:header_params] || {})
61
+ query_params = opts[:query_params] || {}
62
+ form_params = opts[:form_params] || {}
63
+
64
+
65
+ update_params_for_auth! header_params, query_params, opts[:auth_names]
66
+
67
+
68
+ req_opts = {
69
+ :method => http_method,
70
+ :headers => header_params,
71
+ :params => query_params,
72
+ :ssl_verifypeer => Configuration.verify_ssl,
73
+ :cainfo => Configuration.ssl_ca_cert,
74
+ :verbose => Configuration.debugging
75
+ }
76
+
77
+ if [:post, :patch, :put, :delete].include?(http_method)
78
+ req_body = build_request_body(header_params, form_params, opts[:body])
79
+ req_opts.update :body => req_body
80
+ if Configuration.debugging
81
+ Configuration.logger.debug "HTTP request body param ~BEGIN~\n#{req_body}\n~END~\n"
82
+ end
83
+ end
84
+
85
+ Typhoeus::Request.new(url, req_opts)
86
+ end
87
+
88
+ # Deserialize the response to the given return type.
89
+ #
90
+ # @param [String] return_type some examples: "User", "Array[User]", "Hash[String,Integer]"
91
+ def deserialize(response, return_type)
92
+ body = response.body
93
+ return nil if body.nil? || body.empty?
94
+
95
+ # handle file downloading - save response body into a tmp file and return the File instance
96
+ return download_file(response) if return_type == 'File'
97
+
98
+ # ensuring a default content type
99
+ content_type = response.headers['Content-Type'] || 'application/json'
100
+
101
+ unless content_type.start_with?('application/json')
102
+ fail "Content-Type is not supported: #{content_type}"
103
+ end
104
+
105
+ begin
106
+ data = JSON.parse("[#{body}]", :symbolize_names => true)[0]
107
+ rescue JSON::ParserError => e
108
+ if %w(String Date DateTime).include?(return_type)
109
+ data = body
110
+ else
111
+ raise e
112
+ end
113
+ end
114
+
115
+ convert_to_type data, return_type
116
+ end
117
+
118
+ # Convert data to the given return type.
119
+ def convert_to_type(data, return_type)
120
+ return nil if data.nil?
121
+ case return_type
122
+ when 'String'
123
+ data.to_s
124
+ when 'Integer'
125
+ data.to_i
126
+ when 'Float'
127
+ data.to_f
128
+ when 'BOOLEAN'
129
+ data == true
130
+ when 'DateTime'
131
+ # parse date time (expecting ISO 8601 format)
132
+ DateTime.parse data
133
+ when 'Date'
134
+ # parse date time (expecting ISO 8601 format)
135
+ Date.parse data
136
+ when 'Object'
137
+ # generic object, return directly
138
+ data
139
+ when /\AArray<(.+)>\z/
140
+ # e.g. Array<Pet>
141
+ sub_type = $1
142
+ data.map {|item| convert_to_type(item, sub_type) }
143
+ when /\AHash\<String, (.+)\>\z/
144
+ # e.g. Hash<String, Integer>
145
+ sub_type = $1
146
+ {}.tap do |hash|
147
+ data.each {|k, v| hash[k] = convert_to_type(v, sub_type) }
148
+ end
149
+ else
150
+ # models, e.g. Pet
151
+ Supportify.const_get(return_type).new.tap do |model|
152
+ model.build_from_hash data
153
+ end
154
+ end
155
+ end
156
+
157
+ # Save response body into a file in (the defined) temporary folder, using the filename
158
+ # from the "Content-Disposition" header if provided, otherwise a random filename.
159
+ #
160
+ # @see Configuration#temp_folder_path
161
+ # @return [File] the file downloaded
162
+ def download_file(response)
163
+ tmp_file = Tempfile.new '', Configuration.temp_folder_path
164
+ content_disposition = response.headers['Content-Disposition']
165
+ if content_disposition
166
+ filename = content_disposition[/filename=['"]?([^'"\s]+)['"]?/, 1]
167
+ path = File.join File.dirname(tmp_file), filename
168
+ else
169
+ path = tmp_file.path
170
+ end
171
+ # close and delete temp file
172
+ tmp_file.close!
173
+
174
+ File.open(path, 'w') { |file| file.write(response.body) }
175
+ Configuration.logger.info "File written to #{path}. Please move the file to a proper "\
176
+ "folder for further processing and delete the temp afterwards"
177
+ File.new(path)
178
+ end
179
+
180
+ def build_request_url(path)
181
+ # Add leading and trailing slashes to path
182
+ path = "/#{path}".gsub(/\/+/, '/')
183
+ URI.encode(host + path)
184
+ end
185
+
186
+ def build_request_body(header_params, form_params, body)
187
+ # http form
188
+ if header_params['Content-Type'] == 'application/x-www-form-urlencoded' ||
189
+ header_params['Content-Type'] == 'multipart/form-data'
190
+ data = form_params.dup
191
+ data.each do |key, value|
192
+ data[key] = value.to_s if value && !value.is_a?(File)
193
+ end
194
+ elsif body
195
+ data = body.is_a?(String) ? body : body.to_json
196
+ else
197
+ data = nil
198
+ end
199
+ data
200
+ end
201
+
202
+ # Update hearder and query params based on authentication settings.
203
+ def update_params_for_auth!(header_params, query_params, auth_names)
204
+ Array(auth_names).each do |auth_name|
205
+ auth_setting = Configuration.auth_settings[auth_name]
206
+ next unless auth_setting
207
+ case auth_setting[:in]
208
+ when 'header' then header_params[auth_setting[:key]] = auth_setting[:value]
209
+ when 'query' then query_params[auth_setting[:key]] = auth_setting[:value]
210
+ else fail ArgumentError, 'Authentication token must be in `query` of `header`'
211
+ end
212
+ end
213
+ end
214
+
215
+ def user_agent=(user_agent)
216
+ @user_agent = user_agent
217
+ @default_headers['User-Agent'] = @user_agent
218
+ end
219
+
220
+ # Return Accept header based on an array of accepts provided.
221
+ # @param [Array] accepts array for Accept
222
+ # @return [String] the Accept header (e.g. application/json)
223
+ def select_header_accept(accepts)
224
+ if accepts.empty?
225
+ return
226
+ elsif accepts.any?{ |s| s.casecmp('application/json') == 0 }
227
+ 'application/json' # look for json data by default
228
+ else
229
+ accepts.join(',')
230
+ end
231
+ end
232
+
233
+ # Return Content-Type header based on an array of content types provided.
234
+ # @param [Array] content_types array for Content-Type
235
+ # @return [String] the Content-Type header (e.g. application/json)
236
+ def select_header_content_type(content_types)
237
+ if content_types.empty?
238
+ 'application/json' # use application/json by default
239
+ elsif content_types.any?{ |s| s.casecmp('application/json')==0 }
240
+ 'application/json' # use application/json if it's included
241
+ else
242
+ content_types[0] # otherwise, use the first one
243
+ end
244
+ end
245
+
246
+ # Convert object (array, hash, object, etc) to JSON string.
247
+ # @param [Object] model object to be converted into JSON string
248
+ # @return [String] JSON string representation of the object
249
+ def object_to_http_body(model)
250
+ return if model.nil?
251
+ _body = nil
252
+ if model.is_a?(Array)
253
+ _body = model.map{|m| object_to_hash(m) }
254
+ else
255
+ _body = object_to_hash(model)
256
+ end
257
+ _body.to_json
258
+ end
259
+
260
+ # Convert object(non-array) to hash.
261
+ # @param [Object] obj object to be converted into JSON string
262
+ # @return [String] JSON string representation of the object
263
+ def object_to_hash(obj)
264
+ if obj.respond_to?(:to_hash)
265
+ obj.to_hash
266
+ else
267
+ obj
268
+ end
269
+ end
270
+ end
271
+ end
@@ -0,0 +1,24 @@
1
+ module Supportify
2
+ class ApiError < StandardError
3
+ attr_reader :code, :response_headers, :response_body
4
+
5
+ # Usage examples:
6
+ # ApiError.new
7
+ # ApiError.new("message")
8
+ # ApiError.new(:code => 500, :response_headers => {}, :response_body => "")
9
+ # ApiError.new(:code => 404, :message => "Not Found")
10
+ def initialize(arg = nil)
11
+ if arg.is_a? Hash
12
+ arg.each do |k, v|
13
+ if k.to_s == 'message'
14
+ super v
15
+ else
16
+ instance_variable_set "@#{k}", v
17
+ end
18
+ end
19
+ else
20
+ super arg
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,187 @@
1
+ require 'uri'
2
+ require 'singleton'
3
+
4
+ module Supportify
5
+ class Configuration
6
+
7
+ include Singleton
8
+
9
+ # Default api client
10
+ attr_accessor :api_client
11
+
12
+ # Defines url scheme
13
+ attr_accessor :scheme
14
+
15
+ # Defines url host
16
+ attr_accessor :host
17
+
18
+ # Defines url base path
19
+ attr_accessor :base_path
20
+
21
+ # Defines API keys used with API Key authentications.
22
+ #
23
+ # @return [Hash] key: parameter name, value: parameter value (API key)
24
+ #
25
+ # @example parameter name is "api_key", API key is "xxx" (e.g. "api_key=xxx" in query string)
26
+ # config.api_key['api_key'] = 'xxx'
27
+ attr_accessor :api_key
28
+
29
+ # Defines API key prefixes used with API Key authentications.
30
+ #
31
+ # @return [Hash] key: parameter name, value: API key prefix
32
+ #
33
+ # @example parameter name is "Authorization", API key prefix is "Token" (e.g. "Authorization: Token xxx" in headers)
34
+ # config.api_key_prefix['api_key'] = 'Token'
35
+ attr_accessor :api_key_prefix
36
+
37
+ # Defines the username used with HTTP basic authentication.
38
+ #
39
+ # @return [String]
40
+ attr_accessor :username
41
+
42
+ # Defines the password used with HTTP basic authentication.
43
+ #
44
+ # @return [String]
45
+ attr_accessor :password
46
+
47
+ # Set this to enable/disable debugging. When enabled (set to true), HTTP request/response
48
+ # details will be logged with `logger.debug` (see the `logger` attribute).
49
+ # Default to false.
50
+ #
51
+ # @return [true, false]
52
+ attr_accessor :debugging
53
+
54
+ # Defines the logger used for debugging.
55
+ # Default to `Rails.logger` (when in Rails) or logging to STDOUT.
56
+ #
57
+ # @return [#debug]
58
+ attr_accessor :logger
59
+
60
+ # Defines the temporary folder to store downloaded files
61
+ # (for API endpoints that have file response).
62
+ # Default to use `Tempfile`.
63
+ #
64
+ # @return [String]
65
+ attr_accessor :temp_folder_path
66
+
67
+ # Set this to false to skip verifying SSL certificate when calling API from https server.
68
+ # Default to true.
69
+ #
70
+ # @note Do NOT set it to false in production code, otherwise you would face multiple types of cryptographic attacks.
71
+ #
72
+ # @return [true, false]
73
+ attr_accessor :verify_ssl
74
+
75
+ # Set this to customize the certificate file to verify the peer.
76
+ #
77
+ # @return [String] the path to the certificate file
78
+ #
79
+ # @see The `cainfo` option of Typhoeus, `--cert` option of libcurl. Related source code:
80
+ # https://github.com/typhoeus/typhoeus/blob/master/lib/typhoeus/easy_factory.rb#L145
81
+ attr_accessor :ssl_ca_cert
82
+
83
+ attr_accessor :inject_format
84
+
85
+ attr_accessor :force_ending_format
86
+
87
+ class << self
88
+ def method_missing(method_name, *args, &block)
89
+ config = Configuration.instance
90
+ if config.respond_to?(method_name)
91
+ config.send(method_name, *args, &block)
92
+ else
93
+ super
94
+ end
95
+ end
96
+ end
97
+
98
+ def initialize
99
+ @scheme = 'https'
100
+ @host = 'api.supportify.io'
101
+ @base_path = '/v2'
102
+ @api_key = {}
103
+ @api_key_prefix = {}
104
+ @verify_ssl = true
105
+ @debugging = false
106
+ @inject_format = false
107
+ @force_ending_format = false
108
+ @logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
109
+ end
110
+
111
+ def api_client
112
+ @api_client ||= ApiClient.new
113
+ end
114
+
115
+ def scheme=(scheme)
116
+ # remove :// from scheme
117
+ @scheme = scheme.sub(/:\/\//, '')
118
+ end
119
+
120
+ def host=(host)
121
+ # remove http(s):// and anything after a slash
122
+ @host = host.sub(/https?:\/\//, '').split('/').first
123
+ end
124
+
125
+ def base_path=(base_path)
126
+ # Add leading and trailing slashes to base_path
127
+ @base_path = "/#{base_path}".gsub(/\/+/, '/')
128
+ @base_path = "" if @base_path == "/"
129
+ end
130
+
131
+ def base_url
132
+ url = "#{scheme}://#{[host, base_path].join('/').gsub(/\/+/, '/')}"
133
+ URI.encode(url)
134
+ end
135
+
136
+ # Gets API key (with prefix if set).
137
+ # @param [String] param_name the parameter name of API key auth
138
+ def api_key_with_prefix(param_name)
139
+ if @api_key_prefix[param_name]
140
+ "#{@api_key_prefix[param_name]} #{@api_key[param_name]}"
141
+ else
142
+ @api_key[param_name]
143
+ end
144
+ end
145
+
146
+ # Gets Basic Auth token string
147
+ def basic_auth_token
148
+ 'Basic ' + ["#{username}:#{password}"].pack('m').delete("\r\n")
149
+ end
150
+
151
+ def account_api_key=(value)
152
+ @api_key['X-SUPPORTIFY-APIKEY'] = value
153
+ end
154
+
155
+ def account_api_key
156
+ @api_key['X-SUPPORTIFY-APIKEY']
157
+ end
158
+
159
+ def application_api_key=(value)
160
+ @api_key['X-SUPPORTIFY-APPKEY'] = value
161
+ end
162
+
163
+ def application_api_key
164
+ @api_key['X-SUPPORTIFY-APPKEY']
165
+ end
166
+
167
+ # Returns Auth Settings hash for api client.
168
+ def auth_settings
169
+ {
170
+ 'api_key' =>
171
+ {
172
+ type: 'api_key',
173
+ in: 'header',
174
+ key: 'X-SUPPORTIFY-APIKEY',
175
+ value: api_key_with_prefix('X-SUPPORTIFY-APIKEY')
176
+ },
177
+ 'app_key' =>
178
+ {
179
+ type: 'api_key',
180
+ in: 'header',
181
+ key: 'X-SUPPORTIFY-APPKEY',
182
+ value: api_key_with_prefix('X-SUPPORTIFY-APPKEY')
183
+ },
184
+ }
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,87 @@
1
+ require 'date'
2
+
3
+ module Supportify
4
+ # base class containing fundamental method such as to_hash, build_from_hash and more
5
+ class BaseObject
6
+
7
+ # build the object from hash
8
+ def build_from_hash(attributes)
9
+ return nil unless attributes.is_a?(Hash)
10
+ self.class.swagger_types.each_pair do |key, type|
11
+ if type =~ /^Array<(.*)>/i
12
+ if attributes[self.class.attribute_map[key]].is_a?(Array)
13
+ self.send("#{key}=", attributes[self.class.attribute_map[key]].map{ |v| _deserialize($1, v) } )
14
+ else
15
+ #TODO show warning in debug mode
16
+ end
17
+ elsif !attributes[self.class.attribute_map[key]].nil?
18
+ self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
19
+ else
20
+ # data not found in attributes(hash), not an issue as the data can be optional
21
+ end
22
+ end
23
+
24
+ self
25
+ end
26
+
27
+ def _deserialize(type, value)
28
+ case type.to_sym
29
+ when :DateTime
30
+ DateTime.parse(value)
31
+ when :Date
32
+ Date.parse(value)
33
+ when :String
34
+ value.to_s
35
+ when :Integer
36
+ value.to_i
37
+ when :Float
38
+ value.to_f
39
+ when :BOOLEAN
40
+ if value =~ /^(true|t|yes|y|1)$/i
41
+ true
42
+ else
43
+ false
44
+ end
45
+ else # model
46
+ _model = Supportify.const_get(type).new
47
+ _model.build_from_hash(value)
48
+ end
49
+ end
50
+
51
+ def to_s
52
+ to_hash.to_s
53
+ end
54
+
55
+ # to_body is an alias to to_body (backward compatibility))
56
+ def to_body
57
+ to_hash
58
+ end
59
+
60
+ # return the object in the form of hash
61
+ def to_hash
62
+ hash = {}
63
+ self.class.attribute_map.each_pair do |key, value|
64
+ if self.send(key).is_a?(Array)
65
+ next if self.send(key).empty?
66
+ hash[value] = self.send(key).select{|v| !v.nil?}.map{ |v| _to_hash v} unless self.send(key).nil?
67
+ else
68
+ unless (_tmp_value = _to_hash self.send(key)).nil?
69
+ hash[value] = _tmp_value
70
+ end
71
+ end
72
+ end
73
+ hash
74
+ end
75
+
76
+ # Method to output non-array value in the form of hash
77
+ # For object, use to_hash. Otherwise, just return the value
78
+ def _to_hash(value)
79
+ if value.respond_to? :to_hash
80
+ value.to_hash
81
+ else
82
+ value
83
+ end
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,53 @@
1
+ module Supportify
2
+ #
3
+ class Category < BaseObject
4
+ attr_accessor :id, :description, :name
5
+ # attribute mapping from ruby-style variable name to JSON key
6
+ def self.attribute_map
7
+ {
8
+
9
+ # Unique identifier representing a specific category within an application.
10
+ :'id' => :'id',
11
+
12
+ # Description of the category.
13
+ :'description' => :'description',
14
+
15
+ # Display name of the category.
16
+ :'name' => :'name'
17
+
18
+ }
19
+ end
20
+
21
+ # attribute type
22
+ def self.swagger_types
23
+ {
24
+ :'id' => :'Integer',
25
+ :'description' => :'String',
26
+ :'name' => :'String'
27
+
28
+ }
29
+ end
30
+
31
+ def initialize(attributes = {})
32
+ return if !attributes.is_a?(Hash) || attributes.empty?
33
+
34
+ # convert string to symbol for hash key
35
+ attributes = attributes.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
36
+
37
+
38
+ if attributes[:'id']
39
+ self.id = attributes[:'id']
40
+ end
41
+
42
+ if attributes[:'description']
43
+ self.description = attributes[:'description']
44
+ end
45
+
46
+ if attributes[:'name']
47
+ self.name = attributes[:'name']
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,53 @@
1
+ module Supportify
2
+ #
3
+ class Error < BaseObject
4
+ attr_accessor :code, :short_description, :long_description
5
+ # attribute mapping from ruby-style variable name to JSON key
6
+ def self.attribute_map
7
+ {
8
+
9
+ # An HTTP error code.
10
+ :'code' => :'code',
11
+
12
+ # A short keyword describing the error that occurred.
13
+ :'short_description' => :'short_description',
14
+
15
+ # A more detailed description of the cause of the error.
16
+ :'long_description' => :'long_description'
17
+
18
+ }
19
+ end
20
+
21
+ # attribute type
22
+ def self.swagger_types
23
+ {
24
+ :'code' => :'Integer',
25
+ :'short_description' => :'String',
26
+ :'long_description' => :'String'
27
+
28
+ }
29
+ end
30
+
31
+ def initialize(attributes = {})
32
+ return if !attributes.is_a?(Hash) || attributes.empty?
33
+
34
+ # convert string to symbol for hash key
35
+ attributes = attributes.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
36
+
37
+
38
+ if attributes[:'code']
39
+ self.code = attributes[:'code']
40
+ end
41
+
42
+ if attributes[:'short_description']
43
+ self.short_description = attributes[:'short_description']
44
+ end
45
+
46
+ if attributes[:'long_description']
47
+ self.long_description = attributes[:'long_description']
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end