vainglory-api 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: df230271ab484d16bf6be0704412c6c738adbc50
4
- data.tar.gz: 4e8f5f358709b76ceb99f394cd0d5d1d40a8dad9
3
+ metadata.gz: 77529bebc4c054437e5568b468cab881c10e4c45
4
+ data.tar.gz: 0e605b5f0f1291c6b5ad72b5883c1b2a60087605
5
5
  SHA512:
6
- metadata.gz: 98837caf5b1f58a0ec473f87585b972863048079ae6ffb00e7d83ac7dd937b37ae297ff4d8004c194fe73e7b9e6e160170f75261b2be8cc5898c2229d8f9e294
7
- data.tar.gz: 3dfcf7e3aa98c1f9392c9900de72d10ee704c76d1c2564c7e7042013217a0f407406f166d7a50d00c689c415af6b0125397415a46a29528952fde455e3a9e205
6
+ metadata.gz: e3b5a08e3ee00f30e09f182b074a090f5944a74c863e8c0e0b38743394667f4d52b250216ab0f4f6d8e0bc5d463cd02a533486c86efeba5cbd3592955fd6da38
7
+ data.tar.gz: dd326e89fe122bbdaa7fe6cb92c5e7c29cdd49e4a64d5914b7b31f74b766b7e4f823824971009a4c832732d60f9fa8eb630f6b7559a9cafaf8c1289d2b4d032a
@@ -0,0 +1,50 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ Gemfile.lock
46
+ .ruby-version
47
+ .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ # .rvmrc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,2 @@
1
+ Documentation:
2
+ Enabled: false
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.4.0
4
+ - 2.3.3
5
+ - 2.2
6
+ - 2.1
7
+ - 2.0
8
+ sudo: false
9
+ gemfile: Gemfile
10
+ script: bundle exec rspec spec
11
+ addons:
12
+ code_climate:
13
+ repo_token: d20c1b4862616550a65962ceecf0299c70a844cbce54a230b5234804ac2725dc
14
+ after_success:
15
+ - bundle exec codeclimate-test-reporter
@@ -0,0 +1,6 @@
1
+ ### 0.0.3 - 2017-03-28
2
+ - Ruby version >= 2.0 is required
3
+
4
+ ### 0.0.2 - 2017-03-28
5
+
6
+ ### 0.0.1 - 2017-03-28
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Chet Bortz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,112 @@
1
+ # vainglory-api
2
+ [![Gem Version](https://badge.fury.io/rb/vainglory-api.svg)](https://badge.fury.io/rb/vainglory-api)
3
+ [![Travis CI](https://travis-ci.org/cbortz/vainglory-api-ruby.svg?branch=master)](https://travis-ci.org/cbortz/vainglory-api-ruby)
4
+ [![Code Climate](https://codeclimate.com/github/cbortz/vainglory-api-ruby/badges/gpa.svg)](https://codeclimate.com/github/cbortz/vainglory-api-ruby)
5
+ [![Test Coverage](https://codeclimate.com/github/cbortz/vainglory-api-ruby/badges/coverage.svg)](https://codeclimate.com/github/cbortz/vainglory-api-ruby/coverage)
6
+ [![Inline docs](http://inch-ci.org/github/cbortz/vainglory-api-ruby.svg?branch=master)](http://inch-ci.org/github/cbortz/vainglory-api-ruby)
7
+
8
+ - [YARD Documentation](http://www.rubydoc.info/github/cbortz/vainglory-api-ruby)
9
+ - [Official Vainglory API Documentation](https://developer.vainglorygame.com/docs)
10
+
11
+ ---
12
+
13
+ ## Getting Started
14
+
15
+ VaingloryAPI works with Ruby 2.0 onwards. Please refer to the [YARD Documentation](http://www.rubydoc.info/github/cbortz/vainglory-api-ruby) for a better understanding of how everything works.
16
+
17
+ ### Installation
18
+
19
+ You can add it to your Gemfile with:
20
+
21
+ ```ruby
22
+ gem 'vainglory-api'
23
+ ```
24
+
25
+ Then run `bundle install`
26
+
27
+ You can also install it manually with:
28
+
29
+ ```bash
30
+ gem install vainglory-api
31
+ ```
32
+
33
+ ### Usage
34
+
35
+ You can create an instance of the API client by initializing with your API key and [specified region](https://developer.vainglorygame.com/docs#regions) (`na` is the default):
36
+
37
+ ```ruby
38
+ client = VaingloryAPI.new('YOUR_API_KEY', 'na')
39
+ ```
40
+
41
+ #### Helper Attributes
42
+
43
+ All client methods return an `OpenStruct` object containing the response attributes with some additional helper attributes.
44
+
45
+ ```ruby
46
+ response = client.samples
47
+
48
+ response.code # The HTTP response code
49
+ response.success? # Returns true if the response code is less than 300
50
+ response.raw # The complete HTTP response
51
+ ```
52
+
53
+ #### Rate Limits
54
+
55
+ Each request will return data about your rate limits.
56
+
57
+ ```ruby
58
+ response.rate_limit # Request limit per day / per minute
59
+ response.rate_remaining # The number of requests left for the time window
60
+ response.rate_reset # The remaining window before the rate limit is refilled in UTC epoch nanoseconds.
61
+ ```
62
+
63
+ More information: https://developer.vainglorygame.com/docs#rate-limits
64
+
65
+ #### Filtering
66
+
67
+ Currently, filters are supported by these client methods:
68
+
69
+ - `VaingloryAPI::Client#matches`
70
+ - `VaingloryAPI::Client#samples`
71
+
72
+ You can pass filters in as a hash using the exact Query Parameter key names outlined in the [Vainglory API Documentation](https://developer.vainglorygame.com/docs).
73
+
74
+ ```ruby
75
+ # Example matches request with filter
76
+ client.matches('filter[playerNames]' => 'boombastic04,IHaveNoIdea')
77
+ ```
78
+
79
+ #### Methods
80
+
81
+ To get __multiple matches__:
82
+
83
+ ```ruby
84
+ client.matches
85
+ ```
86
+
87
+ To get __single match data__, you must provide the ID of a match:
88
+
89
+ ```ruby
90
+ client.match('37f94e56-1360-11e7-a250-062445d3d668')
91
+ ```
92
+
93
+ You can search for data of __one or more players__ by passing their in-game names (IGNs):
94
+
95
+ ```ruby
96
+ client.players('boombastic04', 'IHaveNoIdea')
97
+ ```
98
+
99
+ To get data about a __single player__, you must provide the ID of the player:
100
+
101
+ ```ruby
102
+ client.player('6abb30de-7cb8-11e4-8bd3-06eb725f8a76')
103
+ ```
104
+
105
+ To get __Telemetry__ data, you must provide the data URL:
106
+
107
+ ```ruby
108
+ client.telemetry('https://gl-prod-us-east-1.s3.amazonaws.com/assets/semc-vainglory/na/2017/03/28/03/07/b0bb7faf-1363-11e7-b11e-0242ac110006-telemetry.json')
109
+ ```
110
+
111
+ ## License
112
+ [MIT License](LICENSE). Copyright 2017 Chet Bortz
@@ -1,110 +1,21 @@
1
- require 'json'
2
- require 'ostruct'
3
- require 'openssl'
4
- require 'net/http'
5
-
6
- class VaingloryAPI
7
- BASE_URL = "https://api.dc01.gamelockerapp.com"
8
-
9
- def initialize(api_key, region = "na")
10
- @api_key = api_key
11
- @region = region
12
- end
13
-
14
- def samples(filter_params = {})
15
- get_request(endpoint_uri("shards/#{@region}/samples", filter_params))
16
- end
17
-
18
- def matches(filter_params = {})
19
- get_request(endpoint_uri("shards/#{@region}/matches", filter_params))
20
- end
21
-
22
- def match(match_id)
23
- get_request(endpoint_uri("shards/#{@region}/matches/#{match_id}"))
24
- end
25
-
26
- def players(*names)
27
- filter_params = {"filter[playerNames]" => names.join(',')}
28
- get_request(endpoint_uri("shards/#{@region}/players", filter_params))
29
- end
30
-
31
- def player(player_id)
32
- get_request(endpoint_uri("shards/#{@region}/players/#{player_id}"))
33
- end
34
-
35
- def telemetry(url)
36
- get_request(URI(url), true, false)
37
- end
38
-
39
- def teams(filter_params = {})
40
- raise(NotImplementedError, "Coming soon!")
41
- end
42
-
43
- def team(team_id)
44
- raise(NotImplementedError, "Coming soon!")
45
- end
46
-
47
- def link(link_id)
48
- raise(NotImplementedError, "Coming soon!")
49
- end
50
-
51
- def status
52
- get_request_without_headers(endpoint_uri('status'))
53
- end
54
-
55
- private
56
-
57
- def get_request_without_headers(uri)
58
- get_request(uri, false)
59
- end
60
-
61
- def get_request(uri, with_headers = true, with_auth = true)
62
- req = Net::HTTP::Get.new(uri)
63
- req = apply_headers(req, with_auth) if with_headers
64
-
65
- request(uri, req)
66
- end
67
-
68
- def apply_headers(req, with_auth = true)
69
- req['Authorization'] = "Bearer #{@api_key}" if with_auth
70
- req['X-TITLE-ID'] = "semc-vainglory"
71
- req['Accept'] = "application/vnd.api+json"
72
-
73
- req
74
- end
75
-
76
- def request(uri, req)
77
- http = Net::HTTP.new(uri.host, uri.port)
78
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
79
- http.use_ssl = true
80
-
81
- response(http.request(req))
82
- end
83
-
84
- def endpoint_uri(path, filter_params = {})
85
- uri = URI(endpoint_url(path))
86
- uri.query = URI.encode_www_form(filter_params)
87
-
88
- uri
89
- end
90
-
91
- def endpoint_url(path)
92
- [BASE_URL, path].join('/')
93
- end
94
-
95
- def response(response_data)
96
- parsed_body = JSON.parse(response_data.body, object_class: OpenStruct)
97
- parsed_code = response_data.code.to_i
98
-
99
- OpenStruct.new({
100
- code: parsed_code,
101
- success?: parsed_code < 300,
102
- rate_limit: response_data['X-RateLimit-Limit'].to_i,
103
- rate_remaining: response_data['X-RateLimit-Remaining'].to_i,
104
- rate_reset: response_data['X-RateLimit-Reset'].to_i,
105
- data: parsed_body.respond_to?(:data) ? parsed_body.data : parsed_body,
106
- error: parsed_body.respond_to?(:error)? parsed_body.error : nil,
107
- raw: response_data
108
- })
109
- end
1
+ require 'vainglory_api/client'
2
+
3
+ # A Ruby libary wrapper for the Vainglory API
4
+ #
5
+ # @author Chet Bortz
6
+ module VaingloryAPI
7
+ # Alias for VaingloryAPI::Client constructor
8
+ #
9
+ # @overload new(api_key, region)
10
+ # @param api_key (String) your Vainglory API key
11
+ # @param region (String) the short name for your specified Region shard
12
+ # @param (see VaingloryAPI::Client#initialize)
13
+ # @example Initialize a new client
14
+ # client = VaingloryAPI.new('API_KEY', 'na')
15
+ # @return [VaingloryAPI::Client] an instance of the client
16
+ # @see VaingloryAPI::Client#initialize
17
+ def new(*args)
18
+ Client.new(*args)
19
+ end
20
+ module_function :new
110
21
  end
@@ -0,0 +1,244 @@
1
+ require 'json'
2
+ require 'ostruct'
3
+ require 'openssl'
4
+ require 'net/http'
5
+
6
+ module VaingloryAPI
7
+ # Used to interface with the official Vainglory API
8
+ #
9
+ # @see https://developer.vainglorygame.com/docs Vainglory API Documentation
10
+ # @see https://developer.vainglorygame.com/docs#payload Vainglory API "Payload"
11
+ # @see https://developer.vainglorygame.com/docs#rate-limits Vainglory API "Rate Limits"
12
+ class Client
13
+ # The base URL used for most requests
14
+ BASE_URL = 'https://api.dc01.gamelockerapp.com'.freeze
15
+
16
+ # A new instance of Client.
17
+ #
18
+ # @param (String) api_key your Vainglory API key
19
+ # @param (String) region the short name for your specified Region shard
20
+ # @example Initialize a new client
21
+ # client = VaingloryAPI::Client.new('API_KEY', 'na')
22
+ # @return [Client] a new instance of the client
23
+ def initialize(api_key, region = 'na')
24
+ @api_key = api_key
25
+ @region = region
26
+ end
27
+
28
+ # Gets batches of random match data
29
+ #
30
+ # @param [Hash] filter_params the parameters used to filter results
31
+ # @option filter_params [String] 'page[offset]' (0) Allows paging over results
32
+ # @option filter_params [String] 'page[limit]' (50) Values less than 50 and great than 2 are supported.
33
+ # @option filter_params [String] 'sort' (createdAt) By default, Matches are sorted by creation time ascending.
34
+ # @option filter_params [String] 'filter[createdAt-start]' (3hrs ago) Must occur before end time. Format is iso8601
35
+ # @option filter_params [String] 'filter[createdAt-end]' (Now) Queries search the last 3 hrs. Format is iso8601
36
+ # @example Get samples
37
+ # client = VaingloryAPI::Client.new('API_KEY', 'na')
38
+ # client.samples
39
+ # @return [OpenStruct] the response and metadata
40
+ # @see https://developer.vainglorygame.com/docs#samples Vainglory API "Samples"
41
+ # @see https://developer.vainglorygame.com/docs#pagination Vainglory API "Pagination"
42
+ # @see https://developer.vainglorygame.com/docs#sorting Vainglory API "Sorting"
43
+ def samples(filter_params = {})
44
+ get_request(endpoint_uri("shards/#{@region}/samples", filter_params))
45
+ end
46
+
47
+ # Gets data from matches (multiple)
48
+ #
49
+ # @param [Hash] filter_params the parameters used to filter results
50
+ # @option filter_params [String] 'page[offset]' (0) Allows paging over results
51
+ # @option filter_params [String] 'page[limit]' (50) Values less than 50 and great than 2 are supported.
52
+ # @option filter_params [String] 'sort' (createdAt) By default, Matches are sorted by creation time ascending.
53
+ # @option filter_params [String] 'filter[createdAt-start]' (3hrs ago) Must occur before end time. Format is iso8601
54
+ # @option filter_params [String] 'filter[createdAt-end]' (Now) Queries search the last 3 hrs. Format is iso8601
55
+ # @option filter_params [String] 'filter[playerNames]' Filters by player name, separated by commas.
56
+ # @option filter_params [String] 'filter[playerIds]' Filters by player Id, separated by commas.
57
+ # @option filter_params [String] 'filter[teamNames]' Filters by team names. Team names are the same as the in game team tags.
58
+ # @option filter_params [String] 'filter[gameMode]' Filters by Game Mode
59
+ # @example Get matches
60
+ # client = VaingloryAPI::Client.new('API_KEY', 'na')
61
+ # client.matches
62
+ # @example Get matches with a filter
63
+ # client = VaingloryAPI::Client.new('API_KEY', 'na')
64
+ # client.matches('filter[playerNames]' => 'player_name')
65
+ # @return [OpenStruct] the response and metadata
66
+ # @see https://developer.vainglorygame.com/docs#get-a-collection-of-matches Vainglory API "Get a collection of Matches"
67
+ # @see https://developer.vainglorygame.com/docs#rosters Vainglory API "Rosters"
68
+ # @see https://developer.vainglorygame.com/docs#match-data-summary Vainglory API "Match Data Summary"
69
+ # @see https://developer.vainglorygame.com/docs#pagination Vainglory API "Pagination"
70
+ # @see https://developer.vainglorygame.com/docs#sorting Vainglory API "Sorting"
71
+ def matches(filter_params = {})
72
+ get_request(endpoint_uri("shards/#{@region}/matches", filter_params))
73
+ end
74
+
75
+ # Gets data for a single match
76
+ # @param [String] match_id the ID of the requested match
77
+ # @example Get a single match
78
+ # client = VaingloryAPI::Client.new('API_KEY', 'na')
79
+ # client.match('MATCH_ID')
80
+ #
81
+ # @return [OpenStruct] the response and metadata
82
+ # @see https://developer.vainglorygame.com/docs#get-a-single-match Vainglory API "Get a single Match"
83
+ # @see https://developer.vainglorygame.com/docs#rosters Vainglory API "Rosters"
84
+ # @see https://developer.vainglorygame.com/docs#match-data-summary Vainglory API "Match Data Summary"
85
+ def match(match_id)
86
+ get_request(endpoint_uri("shards/#{@region}/matches/#{match_id}"))
87
+ end
88
+
89
+ # Gets data about players (one or more)
90
+ #
91
+ # @param [String] player_name the in-game name (IGN) of a player
92
+ # @param [String] additional_player_names additional IGNs for search for
93
+ # @example Search for a player
94
+ # client = VaingloryAPI::Client.new('API_KEY', 'na')
95
+ # client.players('player_name')
96
+ # @example Search for multiple players
97
+ # client = VaingloryAPI::Client.new('API_KEY', 'na')
98
+ # client.players('player_name', 'player_name2')
99
+ # @return [OpenStruct] the response and metadata
100
+ # @see https://developer.vainglorygame.com/docs#get-a-collection-of-players Vainglory API "Get a collection of players"
101
+ def players(player_name, *additional_player_names)
102
+ player_names = [player_name].concat(additional_player_names)
103
+ filter_params = { 'filter[playerNames]' => player_names.join(',') }
104
+ get_request(endpoint_uri("shards/#{@region}/players", filter_params))
105
+ end
106
+
107
+ # Gets data for a single player
108
+ #
109
+ # @param [String] player_id the ID of the requested player
110
+ # @example Get a single player
111
+ # client = VaingloryAPI::Client.new('API_KEY', 'na')
112
+ # client.match('PLAYER_ID')
113
+ # @return [OpenStruct] the response and metadata
114
+ # @see https://developer.vainglorygame.com/docs#get-a-single-player Vainglory API "Get a single Player"
115
+ def player(player_id)
116
+ get_request(endpoint_uri("shards/#{@region}/players/#{player_id}"))
117
+ end
118
+
119
+ # Gets telemtry data from a specified URL
120
+ #
121
+ # @param [String] url the URL of the requested Telemetry data
122
+ # @example Get telemetry data
123
+ # client = VaingloryAPI::Client.new('API_KEY', 'na')
124
+ # client.telemetry('TELEMETRY_URL')
125
+ # @return [OpenStruct] the response and metadata
126
+ # @see https://developer.vainglorygame.com/docs#telemetry Vainglory API "Telemetry"
127
+ def telemetry(url)
128
+ get_request(URI(url), true, false)
129
+ end
130
+
131
+ # Gets aggregated lifetime information about teams (multiple)
132
+ #
133
+ # @param [Hash] _filter_params the parameters used to filter results
134
+ # @option _filter_params [String] 'filter[teamNames]' Filters by team name
135
+ # @option _filter_params [String] 'filter[teamIds]' Filters by team ID
136
+ # @raise [NotImplementedError] this endpoint is not yet available
137
+ # @see https://developer.vainglorygame.com/docs#teams-coming-soon Vainglory API "Get a collection of Teams"
138
+ def teams(_filter_params = {})
139
+ raise(NotImplementedError, 'Coming soon!')
140
+ end
141
+
142
+ # Gets aggregated lifetime information about a single team
143
+ #
144
+ # @raise [NotImplementedError] this endpoint is not yet available
145
+ # @see https://developer.vainglorygame.com/docs#get-a-single-team Vainglory API "Get a single Team"
146
+ def team(_team_id)
147
+ raise(NotImplementedError, 'Coming soon!')
148
+ end
149
+
150
+ # Checks to see if a link object exists for a given code
151
+ #
152
+ # @raise [NotImplementedError] this endpoint is not yet available
153
+ # @see https://developer.vainglorygame.com/docs#links-coming-soon Vainglory API "Links"
154
+ def link(_link_id)
155
+ raise(NotImplementedError, 'Coming soon!')
156
+ end
157
+
158
+ # Gets current API version and release date
159
+ #
160
+ # @example Get the API's status information
161
+ # client = VaingloryAPI::Client.new('API_KEY', 'na')
162
+ # client.status
163
+ # @return [OpenStruct] the response and metadata
164
+ # @see https://developer.vainglorygame.com/docs#versioning Vainglory API "Versioning"
165
+ def status
166
+ get_request_without_headers(endpoint_uri('status'))
167
+ end
168
+
169
+ private
170
+
171
+ def get_request_without_headers(uri)
172
+ get_request(uri, false)
173
+ end
174
+
175
+ def get_request(uri, with_headers = true, with_auth = true)
176
+ req = Net::HTTP::Get.new(uri)
177
+ req = apply_headers(req, with_auth) if with_headers
178
+
179
+ request(uri, req)
180
+ end
181
+
182
+ def apply_headers(req, with_auth = true)
183
+ req['Authorization'] = "Bearer #{@api_key}" if with_auth
184
+ req['X-TITLE-ID'] = 'semc-vainglory'
185
+ req['Accept'] = 'application/vnd.api+json'
186
+
187
+ req
188
+ end
189
+
190
+ def request(uri, req)
191
+ http = Net::HTTP.new(uri.host, uri.port)
192
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
193
+ http.use_ssl = true
194
+
195
+ response(http.request(req))
196
+ end
197
+
198
+ def endpoint_uri(path, filter_params = {})
199
+ uri = URI(endpoint_url(path))
200
+ uri.query = URI.encode_www_form(filter_params)
201
+
202
+ uri
203
+ end
204
+
205
+ def endpoint_url(path)
206
+ [BASE_URL, path].join('/')
207
+ end
208
+
209
+ def response(response_data)
210
+ response_object = serialize_response_data(response_data.body)
211
+ metadata = serialize_response_metadata(response_data)
212
+
213
+ # Add metadata members to response_object
214
+ metadata.each do |k, v|
215
+ response_object[k] = v
216
+ end
217
+
218
+ response_object
219
+ end
220
+
221
+ def serialize_response_metadata(response_data)
222
+ response_code = response_data.code.to_i
223
+
224
+ {
225
+ code: response_code,
226
+ success?: response_code < 300,
227
+ rate_limit: response_data['X-RateLimit-Limit'].to_i,
228
+ rate_remaining: response_data['X-RateLimit-Remaining'].to_i,
229
+ rate_reset: response_data['X-RateLimit-Reset'].to_i,
230
+ raw: response_data
231
+ }
232
+ end
233
+
234
+ def serialize_response_data(raw_response_body)
235
+ data = JSON.parse(raw_response_body, object_class: OpenStruct)
236
+
237
+ if data.is_a?(Array)
238
+ OpenStruct.new(data: data)
239
+ else
240
+ data
241
+ end
242
+ end
243
+ end
244
+ end