Skip to content

Commit b76c427

Browse files
committed
Added key to async and fixed requests
1 parent 1ee428b commit b76c427

File tree

5 files changed

+80
-8
lines changed

5 files changed

+80
-8
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
],
55
"python.testing.unittestEnabled": false,
66
"python.testing.pytestEnabled": true
7-
}
7+
}

howlongtobeatpy/howlongtobeatpy/HTMLRequests.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,9 @@ async def send_async_web_request(game_name: str, search_modifiers: SearchModifie
116116
headers = HTMLRequests.get_search_request_headers()
117117
payload = HTMLRequests.get_search_request_data(game_name, search_modifiers, page)
118118
# Make the post request and return the result if is valid
119+
search_url_with_key = HTMLRequests.SEARCH_URL + "/" + HTMLRequests.SEARCH_API_KEY
119120
async with aiohttp.ClientSession() as session:
120-
async with session.post(HTMLRequests.SEARCH_URL, headers=headers, data=payload) as resp:
121+
async with session.post(search_url_with_key, headers=headers, data=payload) as resp:
121122
if resp is not None and str(resp.status) == "200":
122123
return await resp.text()
123124
return None
@@ -226,3 +227,38 @@ def send_website_request_getcode(parse_all_scripts: bool):
226227
for match in matches:
227228
return match
228229
return None
230+
231+
@staticmethod
232+
async def async_send_website_request_getcode(parse_all_scripts: bool):
233+
"""
234+
Function that send a request to howlongtobeat to scrape the /api/search key
235+
@return: The string key to use on /api/search
236+
"""
237+
# Make the post request and return the result if is valid
238+
headers = HTMLRequests.get_title_request_headers()
239+
async with aiohttp.ClientSession() as session:
240+
async with session.get(HTMLRequests.BASE_URL, headers=headers) as resp:
241+
if resp is not None and str(resp.status) == "200":
242+
resp_text = await resp.text()
243+
# Parse the HTML content using BeautifulSoup
244+
soup = BeautifulSoup(resp_text, 'html.parser')
245+
# Find all <script> tags with a src attribute containing the substring
246+
scripts = soup.find_all('script', src=True)
247+
if parse_all_scripts:
248+
matching_scripts = [script['src'] for script in scripts]
249+
else:
250+
matching_scripts = [script['src'] for script in scripts if '_app-' in script['src']]
251+
for script_url in matching_scripts:
252+
script_url = HTMLRequests.BASE_URL + script_url
253+
async with aiohttp.ClientSession() as session:
254+
async with session.get(script_url, headers=headers) as script_resp:
255+
if script_resp is not None and str(resp.status) == "200":
256+
script_resp_text = await script_resp.text()
257+
pattern = r'"/api/search/".concat\("([a-zA-Z0-9]+)"\)'
258+
matches = re.findall(pattern, script_resp_text)
259+
for match in matches:
260+
return match
261+
else:
262+
return None
263+
else:
264+
return None

howlongtobeatpy/howlongtobeatpy/HowLongToBeat.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ async def async_search(self, game_name: str, search_modifiers: SearchModifiers =
4444
"""
4545
if game_name is None or len(game_name) == 0:
4646
return None
47+
# Fetch the API Key
48+
if HTMLRequests.SEARCH_API_KEY is None:
49+
api_key_result = await HTMLRequests.async_send_website_request_getcode(False)
50+
if api_key_result is None:
51+
api_key_result = await HTMLRequests.async_send_website_request_getcode(True)
52+
if api_key_result is not None:
53+
# Set it for Caching
54+
HTMLRequests.SEARCH_API_KEY = api_key_result
55+
else:
56+
return None
57+
# Fetch the other data
4758
html_result = await HTMLRequests.send_async_web_request(game_name, search_modifiers)
4859
if html_result is not None:
4960
return self.__parse_web_result(game_name, html_result, None, similarity_case_sensitive)
@@ -60,6 +71,7 @@ def search(self, game_name: str, search_modifiers: SearchModifiers = SearchModif
6071
"""
6172
if game_name is None or len(game_name) == 0:
6273
return None
74+
# Fetch the API Key
6375
if HTMLRequests.SEARCH_API_KEY is None:
6476
api_key_result = HTMLRequests.send_website_request_getcode(False)
6577
if api_key_result is None:
@@ -68,7 +80,8 @@ def search(self, game_name: str, search_modifiers: SearchModifiers = SearchModif
6880
# Set it for Caching
6981
HTMLRequests.SEARCH_API_KEY = api_key_result
7082
else:
71-
return None
83+
return None
84+
# Fetch the other data
7285
html_result = HTMLRequests.send_web_request(game_name, search_modifiers)
7386
if html_result is not None:
7487
return self.__parse_web_result(game_name, html_result, None, similarity_case_sensitive)
@@ -88,6 +101,17 @@ async def async_search_from_id(self, game_id: int):
88101
"""
89102
if game_id is None or game_id == 0:
90103
return None
104+
# Fetch the API Key
105+
if HTMLRequests.SEARCH_API_KEY is None:
106+
api_key_result = await HTMLRequests.async_send_website_request_getcode(False)
107+
if api_key_result is None:
108+
api_key_result = await HTMLRequests.async_send_website_request_getcode(True)
109+
if api_key_result is not None:
110+
# Set it for Caching
111+
HTMLRequests.SEARCH_API_KEY = api_key_result
112+
else:
113+
return None
114+
# Fetch the other data
91115
game_title = await HTMLRequests.async_get_game_title(game_id)
92116
if game_title is not None:
93117
html_result = await HTMLRequests.send_async_web_request(game_title)
@@ -108,6 +132,17 @@ def search_from_id(self, game_id: int):
108132
"""
109133
if game_id is None or game_id == 0:
110134
return None
135+
# Fetch the API Key
136+
if HTMLRequests.SEARCH_API_KEY is None:
137+
api_key_result = HTMLRequests.send_website_request_getcode(False)
138+
if api_key_result is None:
139+
api_key_result = HTMLRequests.send_website_request_getcode(True)
140+
if api_key_result is not None:
141+
# Set it for Caching
142+
HTMLRequests.SEARCH_API_KEY = api_key_result
143+
else:
144+
return None
145+
# Fetch the other data
111146
game_title = HTMLRequests.get_game_title(game_id)
112147
if game_title is not None:
113148
html_result = HTMLRequests.send_web_request(game_title)

howlongtobeatpy/setup.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
long_description = fh.read()
55

66
setup(name='howlongtobeatpy',
7-
version='1.0.6',
7+
version='1.0.7',
88
packages=find_packages(exclude=['tests']),
99
description='A Python API for How Long to Beat',
1010
long_description=long_description,
@@ -14,9 +14,10 @@
1414
license='MIT',
1515
keywords='howlongtobeat gaming steam uplay origin time length how long to beat',
1616
install_requires=[
17-
'aiohttp>=3.8.3',
18-
'requests>=2.28.1',
17+
'aiohttp>=3.10.1',
18+
'requests>=2.32.3',
1919
'aiounittest>=1.4.2',
20-
'fake_useragent>=1.1.0'
20+
'fake_useragent>=1.5.1',
21+
'beautifulsoup4>=4.12.3'
2122
],
2223
zip_safe=False)

sonar-project.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ sonar.organization=scrappycocco-github
22
sonar.projectKey=ScrappyCocco_HowLongToBeat-PythonAPI
33

44
sonar.projectName=HowLongToBeat-PythonAPI
5-
sonar.projectVersion=1.0.6
5+
sonar.projectVersion=1.0.7
66
sonar.python.version=3.9
77

88
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.

0 commit comments

Comments
 (0)