howlongtobeat 0.2.2 → 0.2.3
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/howlongtobeat/html_requests.rb +37 -10
- data/lib/howlongtobeat/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b94e6610de0b221a6a9913bcddc28648dc7fb7bbb79991e6e512dee9a7359cbc
|
|
4
|
+
data.tar.gz: 5daf1faf915be4b7f33ccb1542d801b079cf6386bcb1d8ae56dbb988a81bc4a9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b7e115db1b5c3ba6444d1fd5e2bf76082f830a6bb55c0c9a55da132b05dc33d364ded99036ef448872221aa99aaea84b2ac17e3d7ee37dfc97ee529f813898f6
|
|
7
|
+
data.tar.gz: dfaf4acae0ed822a1c59900a8c6a78131e4548aff26b0d59f2baaf91505fa533ff23f708d5627de6a84c7b04c2d27679bcfc3164ce31fab0e300e0f03b38f82b
|
data/CHANGELOG.md
CHANGED
|
@@ -25,6 +25,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
25
25
|
### Security
|
|
26
26
|
- None
|
|
27
27
|
|
|
28
|
+
## [0.2.3] - 2026-04-15
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
- Send `x-hp-key` and `x-hp-val` headers extracted from the `/init` response, matching HLTB's updated API authentication (mirrors Python package v1.0.21)
|
|
32
|
+
- Inject the dynamic key/value pair from `/init` into the search request payload
|
|
33
|
+
|
|
28
34
|
## [0.2.2] - 2026-03-24
|
|
29
35
|
|
|
30
36
|
### Fixed
|
|
@@ -70,18 +70,28 @@ module HowLongToBeat
|
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
+
AuthStruct = Struct.new(:auth_token, :auth_key, :auth_value)
|
|
74
|
+
|
|
73
75
|
class << self
|
|
74
|
-
def get_search_request_headers
|
|
75
|
-
{
|
|
76
|
+
def get_search_request_headers(auth_struct = nil)
|
|
77
|
+
headers = {
|
|
76
78
|
'content-type' => 'application/json',
|
|
77
79
|
'accept' => '*/*',
|
|
78
80
|
'User-Agent' => random_user_agent,
|
|
79
|
-
'
|
|
80
|
-
'
|
|
81
|
+
'Referer' => REFERER_HEADER,
|
|
82
|
+
'Origin' => BASE_URL
|
|
81
83
|
}
|
|
84
|
+
|
|
85
|
+
if auth_struct
|
|
86
|
+
headers['x-auth-token'] = auth_struct.auth_token.to_s if auth_struct.auth_token
|
|
87
|
+
headers['x-hp-key'] = auth_struct.auth_key.to_s if auth_struct.auth_key
|
|
88
|
+
headers['x-hp-val'] = auth_struct.auth_value.to_s if auth_struct.auth_value
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
headers
|
|
82
92
|
end
|
|
83
93
|
|
|
84
|
-
def get_search_request_data(game_name, search_modifiers = SearchModifiers::NONE, page = 1, search_info = nil)
|
|
94
|
+
def get_search_request_data(game_name, search_modifiers = SearchModifiers::NONE, page = 1, search_info = nil, auth_struct = nil)
|
|
85
95
|
payload = {
|
|
86
96
|
searchType: 'games',
|
|
87
97
|
searchTerms: game_name.split,
|
|
@@ -123,6 +133,10 @@ module HowLongToBeat
|
|
|
123
133
|
payload[:searchOptions][:users][:id] = search_info.api_key
|
|
124
134
|
end
|
|
125
135
|
|
|
136
|
+
if auth_struct&.auth_key && auth_struct&.auth_value
|
|
137
|
+
payload[auth_struct.auth_key] = auth_struct.auth_value
|
|
138
|
+
end
|
|
139
|
+
|
|
126
140
|
payload.to_json
|
|
127
141
|
end
|
|
128
142
|
|
|
@@ -135,11 +149,11 @@ module HowLongToBeat
|
|
|
135
149
|
endpoint_candidates = build_endpoint_candidates(search_info&.search_url)
|
|
136
150
|
|
|
137
151
|
endpoint_candidates.each do |endpoint|
|
|
138
|
-
|
|
139
|
-
next unless
|
|
152
|
+
auth_struct = fetch_search_token(endpoint)
|
|
153
|
+
next unless auth_struct
|
|
140
154
|
|
|
141
|
-
headers = get_search_request_headers
|
|
142
|
-
payload = get_search_request_data(game_name, search_modifiers, page, search_info)
|
|
155
|
+
headers = get_search_request_headers(auth_struct)
|
|
156
|
+
payload = get_search_request_data(game_name, search_modifiers, page, search_info, auth_struct)
|
|
143
157
|
search_url = "#{BASE_URL}#{endpoint}"
|
|
144
158
|
response = make_request(search_url, headers, payload)
|
|
145
159
|
return response if response
|
|
@@ -180,7 +194,20 @@ module HowLongToBeat
|
|
|
180
194
|
json = JSON.parse(response) rescue nil
|
|
181
195
|
return nil unless json.is_a?(Hash)
|
|
182
196
|
|
|
183
|
-
json['token'] || json.dig('data', 'token') || json['auth_token'] || json['authToken']
|
|
197
|
+
token = json['token'] || json.dig('data', 'token') || json['auth_token'] || json['authToken']
|
|
198
|
+
|
|
199
|
+
auth_key = nil
|
|
200
|
+
auth_value = nil
|
|
201
|
+
json.each do |field_name, field_value|
|
|
202
|
+
lower = field_name.downcase
|
|
203
|
+
if lower.match?(/key/)
|
|
204
|
+
auth_key = field_value
|
|
205
|
+
elsif lower.match?(/val/)
|
|
206
|
+
auth_value = field_value
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
AuthStruct.new(token, auth_key, auth_value)
|
|
184
211
|
rescue StandardError
|
|
185
212
|
nil
|
|
186
213
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: howlongtobeat
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dmitrii Pashutskii
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-04-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: nokogiri
|