swgoh_comlink 0.1.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.
- checksums.yaml +7 -0
- data/lib/comlink_api_request.rb +62 -0
- data/lib/swgoh_comlink.rb +213 -0
- metadata +87 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c9c4144173f292a053e64ace25b86b5f3937db8cd4de91c95420414f7edb942b
|
4
|
+
data.tar.gz: 3f194112a1082053ff9cea729522efca2ee1c7e0fc770d4666964eaaec6360b2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 261e30c5d1efbd7732d9d1c63495850611a1e53e1a1cf104b5f259b9784d64086edb6290c86fdd6d7fcbc7c3f54d2b00bd0997f9afdb8aea2c5e711a029e63e6
|
7
|
+
data.tar.gz: 334865c1ac341fdaea813ae8071ba92cf94f31a9eca900471f4352f6f0163e5d9e9a59df8c9a80d2db504f110d0394e183dba4e3b785abd77a73969222310ad1
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'digest'
|
3
|
+
require 'json'
|
4
|
+
require 'net/http'
|
5
|
+
require 'uri'
|
6
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
7
|
+
|
8
|
+
class ComlinkApiRequest
|
9
|
+
attr_accessor :hmac_enabled, :comlink_url
|
10
|
+
|
11
|
+
def initialize(comlink_url, keys)
|
12
|
+
@comlink_url = comlink_url.start_with?('http') ? comlink_url : "https://#{comlink_url}"
|
13
|
+
@hmac_enabled = false
|
14
|
+
return if keys.empty?
|
15
|
+
|
16
|
+
keys = keys.with_indifferent_access
|
17
|
+
@secret_key = keys['secret_key']
|
18
|
+
@access_key = keys['access_key']
|
19
|
+
|
20
|
+
raise ArgumentError, 'Secret key missing' unless @secret_key
|
21
|
+
raise ArgumentError, 'Access key missing' unless @access_key
|
22
|
+
|
23
|
+
@hmac_enabled = true
|
24
|
+
end
|
25
|
+
|
26
|
+
def get(path)
|
27
|
+
uri = URI.parse("#{@comlink_url}#{path}")
|
28
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
29
|
+
http.use_ssl = true
|
30
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
31
|
+
|
32
|
+
http.request(request).body
|
33
|
+
end
|
34
|
+
|
35
|
+
def post(path, body)
|
36
|
+
uri = URI.parse("#{@comlink_url}#{path}")
|
37
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
38
|
+
http.use_ssl = true
|
39
|
+
|
40
|
+
request = Net::HTTP::Post.new(uri.request_uri, 'Content-Type' => 'application/json')
|
41
|
+
add_hmac_headers(request, 'POST', path, body)
|
42
|
+
request.body = body
|
43
|
+
|
44
|
+
http.request(request).body
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def add_hmac_headers(request, type, endpoint, payload = '')
|
50
|
+
return unless @hmac_enabled
|
51
|
+
|
52
|
+
req_time = (Time.now.to_i * 1000).to_s
|
53
|
+
|
54
|
+
payload_hash_digest = Digest::MD5.hexdigest(payload)
|
55
|
+
|
56
|
+
hmac_obj = OpenSSL::HMAC.new(@secret_key, OpenSSL::Digest.new('sha256'))
|
57
|
+
hmac_obj.update(req_time + type + endpoint + payload_hash_digest)
|
58
|
+
|
59
|
+
request['X-Date'] = req_time
|
60
|
+
request['Authorization'] = "HMAC-SHA256 Credential=#{@access_key},Signature=#{hmac_obj.hexdigest}"
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/hash'
|
4
|
+
require 'active_support/core_ext/string'
|
5
|
+
require_relative 'comlink_api_request'
|
6
|
+
|
7
|
+
# Base class for the gem, a wrapper for Comlink
|
8
|
+
# See https://github.com/swgoh-utils/swgoh-comlink for more info on Comlink
|
9
|
+
class SwgohComlink
|
10
|
+
def initialize(comlink_url, keys = {})
|
11
|
+
@api_requester = ComlinkApiRequest.new(comlink_url, keys)
|
12
|
+
end
|
13
|
+
|
14
|
+
def enums
|
15
|
+
JSON.parse(@api_requester.get('/enums'))
|
16
|
+
end
|
17
|
+
|
18
|
+
def localization(id, unzip = false, enums = false)
|
19
|
+
body = {
|
20
|
+
payload: {
|
21
|
+
id: id
|
22
|
+
},
|
23
|
+
unzip: unzip,
|
24
|
+
enums: enums
|
25
|
+
}
|
26
|
+
|
27
|
+
JSON.parse(@api_requester.post('/localization', body.to_json))
|
28
|
+
end
|
29
|
+
|
30
|
+
def metadata(client_specs = {}, enums = false)
|
31
|
+
body = {}
|
32
|
+
body['payload'] = { "clientSpecs" => verify_parameters(client_specs, ['platform', 'bundleId', 'externalVersion', 'internalVersion', 'region']) } unless client_specs.empty?
|
33
|
+
body['enums'] = false
|
34
|
+
|
35
|
+
JSON.parse(@api_requester.post('/metadata', body.to_json))
|
36
|
+
end
|
37
|
+
|
38
|
+
def data(version, include_pve_units = true, request_segment = 0, enums = false)
|
39
|
+
body = {
|
40
|
+
payload: {
|
41
|
+
version: version,
|
42
|
+
includePveUnits: include_pve_units,
|
43
|
+
requestSegment: request_segment
|
44
|
+
},
|
45
|
+
enums: enums
|
46
|
+
}
|
47
|
+
|
48
|
+
body_validation(body, [ { validation: (0..4), error_message: 'Request segment must be between 0 and 4', path: [:payload, :requestSegment] } ])
|
49
|
+
|
50
|
+
JSON.parse(@api_requester.post('/data', body.to_json))
|
51
|
+
end
|
52
|
+
|
53
|
+
def player(player_id, enums = false)
|
54
|
+
body = {
|
55
|
+
payload: format_player_id_hash(player_id),
|
56
|
+
enums: enums
|
57
|
+
}
|
58
|
+
|
59
|
+
JSON.parse(@api_requester.post('/player', body.to_json))
|
60
|
+
end
|
61
|
+
|
62
|
+
def player_arena(player_id, enums = false)
|
63
|
+
body = {
|
64
|
+
payload: format_player_id_hash(player_id),
|
65
|
+
enums: enums
|
66
|
+
}
|
67
|
+
|
68
|
+
JSON.parse(@api_requester.post('/playerArena', body.to_json))
|
69
|
+
end
|
70
|
+
|
71
|
+
def guild(guild_id, include_recent_guild_activity = false, enums = false)
|
72
|
+
body = {
|
73
|
+
payload: {
|
74
|
+
guildId: guild_id,
|
75
|
+
includeRecentGuildActivityInfo: include_recent_guild_activity
|
76
|
+
},
|
77
|
+
enums: enums
|
78
|
+
}
|
79
|
+
|
80
|
+
JSON.parse(@api_requester.post('/guild', body.to_json))
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_guilds(filter_type, name = nil, search_criteria = nil, count = 10, enums = false)
|
84
|
+
body = {
|
85
|
+
payload: {
|
86
|
+
filterType: filter_type,
|
87
|
+
count: count,
|
88
|
+
enums: enums
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
validations = [ { validation: [4, 5], error_message: 'filterType must be 4 or 5', path: [:payload, :filterType], required: true } ]
|
93
|
+
|
94
|
+
if filter_type == 4
|
95
|
+
body[:payload][:name] = name
|
96
|
+
validations << { error_message: 'Name is required when filterType is 4', path: [:payload, :name], required: true }
|
97
|
+
elsif filter_type == 5
|
98
|
+
body[:payload][:searchCriteria] = search_criteria && verify_parameters(search_criteria, ['minMemberCount', 'maxMemberCount', 'includeInviteOnly', 'minGuildGalacticPower', 'maxGuildGalacticPower', 'recentTbParticipatedIn'])
|
99
|
+
validations << { error_message: 'searchCriteria is required when filterType is 5', path: [:payload, :searchCriteria], required: true }
|
100
|
+
end
|
101
|
+
|
102
|
+
body_validation(body, validations)
|
103
|
+
|
104
|
+
JSON.parse(@api_requester.post('/getGuilds', body.to_json))
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_events(enums = false)
|
108
|
+
body = {
|
109
|
+
enums: enums
|
110
|
+
}
|
111
|
+
|
112
|
+
JSON.parse(@api_requester.post('/getEvents', body.to_json))
|
113
|
+
end
|
114
|
+
|
115
|
+
def get_leaderboard(payload, enums = false)
|
116
|
+
body_validation(payload, [ { validation: [4, 6], error_message: 'leaderboardType must be 4 or 6', path: [:leaderboardType] } ])
|
117
|
+
|
118
|
+
if payload[:leaderboardType] == 4 || payload[:leaderboard_type] == 4
|
119
|
+
payload = verify_parameters(payload, ['leaderboardType', 'eventInstanceId', 'groupId'])
|
120
|
+
body_validation(payload, [
|
121
|
+
{ error_message: 'eventInstanceId must be present', path: [:eventInstanceId], required: true },
|
122
|
+
{ error_message: 'groupId must be present', path: [:groupId], required: true }
|
123
|
+
])
|
124
|
+
else
|
125
|
+
payload = verify_parameters(payload, ['leaderboardType', 'league', 'division'])
|
126
|
+
body_validation(payload, [
|
127
|
+
{ validation: [20, 40, 60, 80, 100], error_message: 'league must be in [20, 40, 60, 80, 100]', path: [:league], required: true },
|
128
|
+
{ validation: [5, 10, 15, 20, 25], error_message: 'division must be in [5, 10, 15, 20, 25]', path: [:division], required: true }
|
129
|
+
])
|
130
|
+
end
|
131
|
+
|
132
|
+
body = {
|
133
|
+
payload: payload,
|
134
|
+
enums: false
|
135
|
+
}
|
136
|
+
|
137
|
+
JSON.parse(@api_requester.post('/getLeaderboard', body.to_json))
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_guild_leaderboard(leaderboards, count, enums = false)
|
141
|
+
def_ids = [
|
142
|
+
'sith_raid',
|
143
|
+
'rancor',
|
144
|
+
'aat',
|
145
|
+
'kraytdragon',
|
146
|
+
'speederbike',
|
147
|
+
't01D',
|
148
|
+
't02D',
|
149
|
+
't03D',
|
150
|
+
't04D',
|
151
|
+
't05D',
|
152
|
+
'TERRITORY_WAR_LEADERBOARD',
|
153
|
+
'GUILD:RAIDS:NORMAL_DIFF:RANCOR:DIFF06',
|
154
|
+
'GUILD:RAIDS:NORMAL_DIFF:RANCOR:HEROIC80',
|
155
|
+
'GUILD:RAIDS:NORMAL_DIFF:AAT:DIFF06',
|
156
|
+
'GUILD:RAIDS:NORMAL_DIFF:AAT:HEROIC85',
|
157
|
+
'GUILD:RAIDS:NORMAL_DIFF:SITH_RAID:DIFF06',
|
158
|
+
'GUILD:RAIDS:NORMAL_DIFF:SITH_RAID:HEROIC85',
|
159
|
+
'GUILD:RAIDS:NORMAL_DIFF:KRAYTDRAGON:DIFF01',
|
160
|
+
'GUILD:RAIDS:NORMAL_DIFF:ROTJ:SPEEDERBIKE'
|
161
|
+
]
|
162
|
+
|
163
|
+
leaderboards.each do |leaderboard|
|
164
|
+
payload = verify_parameters(leaderboard, ['leaderboardType', 'defId', 'monthOffset'])
|
165
|
+
body_validation(leaderboard, [
|
166
|
+
{ validation: [0, 2, 3, 4, 5, 6], error_message: 'leaderboardType must in [0, 2, 3, 4, 5, 6]', path: [:leaderboardType], required: true },
|
167
|
+
{ validation: def_ids, error_message: 'defId must be certain values, see docs', path: [:defId], required: [2, 4, 5, 6].include?(leaderboard.with_indifferent_access[:leaderboardType]) },
|
168
|
+
{ validation: [0, 1], error_message: 'monthOffset must 0 or 1', path: [:monthOffset] }
|
169
|
+
])
|
170
|
+
end
|
171
|
+
|
172
|
+
body = {
|
173
|
+
payload: {
|
174
|
+
leaderboardId: leaderboards,
|
175
|
+
count: count
|
176
|
+
},
|
177
|
+
enums: enums
|
178
|
+
}
|
179
|
+
|
180
|
+
JSON.parse(@api_requester.post('/getGuildLeaderboard', body.to_json))
|
181
|
+
end
|
182
|
+
|
183
|
+
private
|
184
|
+
|
185
|
+
def format_player_id_hash(player_id_original)
|
186
|
+
# This can accept the 9 digit ally code (ex: 123-456-789)
|
187
|
+
# OR it can accept the full playerId (ex: HFuvf-OURK202WASUgpayw)
|
188
|
+
player_id = player_id_original.dup
|
189
|
+
player_id.gsub!('-', '') if player_id.length == 11
|
190
|
+
player_id.length == 9 ? { allyCode: player_id } : { playerID: player_id }
|
191
|
+
end
|
192
|
+
|
193
|
+
def verify_parameters(original_hash, permitted_keys)
|
194
|
+
original_hash = original_hash.with_indifferent_access
|
195
|
+
|
196
|
+
original_hash.transform_keys! { |key| key.to_s.camelize(:lower) }
|
197
|
+
original_hash.slice!(*permitted_keys)
|
198
|
+
|
199
|
+
original_hash
|
200
|
+
end
|
201
|
+
|
202
|
+
def body_validation(body, requirements)
|
203
|
+
requirements.each do |req_set|
|
204
|
+
value = body.dig(*req_set[:path])
|
205
|
+
next if !value && !req_set[:required]
|
206
|
+
next if value && (!req_set[:validation] || req_set[:validation].include?(value))
|
207
|
+
|
208
|
+
raise ArgumentError, req_set[:error_message]
|
209
|
+
end
|
210
|
+
|
211
|
+
true
|
212
|
+
end
|
213
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: swgoh_comlink
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zach Moses
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-10-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: webmock
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A wrapper to connect to SWGOH Comlink APIs
|
56
|
+
email: zmoses93@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- lib/comlink_api_request.rb
|
62
|
+
- lib/swgoh_comlink.rb
|
63
|
+
homepage: https://github.com/zmoses/SwgohComlink
|
64
|
+
licenses:
|
65
|
+
- MIT
|
66
|
+
metadata: {}
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.7.0
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubygems_version: 3.5.18
|
83
|
+
signing_key:
|
84
|
+
specification_version: 4
|
85
|
+
summary: 'Created to connect with deployed Star Wars: Galaxy of Heroes Comlink APIs.
|
86
|
+
For more information on Comlink, see their Github page: https://github.com/swgoh-utils/swgoh-comlink'
|
87
|
+
test_files: []
|