@@ -36,41 +36,27 @@ def __init__(self, script_content: str):
3636
3737 def __extract_search_url_script (self , script_content : str ):
3838 """
39- Function that finds the 'fetch' call using 'method: "POST"',
40- extracts the base endpoint path, and returns the full '/api/path'
41- string (e.g., "/api/search" or "/api/finder").
42-
43- This avoids relying on the exact string by confirming
39+ Function that finds the 'fetch' call using 'method: "POST"',
40+ extracts the endpoint path, and returns the full '/api/...'
41+ string (e.g., "/api/search/site " or "/api/finder/v2 ").
42+
43+ This avoids relying on the exact string by confirming
4444 the use of the POST method, which identifies the actual search endpoint.
45-
46- @return: The full API endpoint string (e.g., "/api/search") or None.
45+
46+ @return: The full API endpoint string (e.g., "/api/search/site ") or None.
4747 """
48- # Pattern explanation:
49- # 1. Capture Group 1: Matches the path suffix (e.g., "search", "find", "finder").
50- # 2. Ensures the request options contain 'method: "POST"' to filter out the GET init call.
5148 pattern = re .compile (
52- # Capture Group 1: The path suffix after /api/ (e.g., "search", "find", "finder")
5349 r'fetch\s*\(\s*["\']/api/([a-zA-Z0-9_/]+)[^"\']*["\']\s*,\s*{[^}]*method:\s*["\']POST["\'][^}]*}' ,
5450 re .DOTALL | re .IGNORECASE
5551 )
56-
52+
5753 match = pattern .search (script_content )
58-
54+
5955 if match :
60- # Example captured string: "search", "find", "finder", or "find/v2"
61- path_suffix = match .group (1 )
62-
63- # Determine the root path (e.g., "search" from "search/v2")
64- # This ensures we get the base endpoint name even if sub-paths are used.
65- if '/' in path_suffix :
66- base_path = path_suffix .split ('/' )[0 ]
67- else :
68- base_path = path_suffix
69-
70- # Accept any endpoint variant (search, find, finder, etc.)
71- full_endpoint = f"/api/{ base_path } "
72- return full_endpoint
73-
56+ # e.g. "search/site", "find", "finder/v2"
57+ path_suffix = match .group (1 ).rstrip ('/' )
58+ return f"/api/{ path_suffix } "
59+
7460 return None
7561
7662
@@ -199,9 +185,7 @@ def send_web_request(game_name: str, search_modifiers: SearchModifiers = SearchM
199185 ua = UserAgent ()
200186 request_user_agent = ua .random .strip ()
201187 # Retrieve the updated URL
202- search_info_data = HTMLRequests .send_website_request_getcode (False , request_user_agent )
203- if search_info_data is None or search_info_data .search_url is None :
204- search_info_data = HTMLRequests .send_website_request_getcode (True , request_user_agent )
188+ search_info_data = HTMLRequests .send_website_request_getcode (request_user_agent )
205189 # Retrieve the request auth token
206190 auth_struct = None
207191 if search_info_data is not None and search_info_data .search_url is not None :
@@ -232,9 +216,7 @@ async def send_async_web_request(game_name: str, search_modifiers: SearchModifie
232216 ua = UserAgent ()
233217 request_user_agent = ua .random .strip ()
234218 # Retrieve the updated URL
235- search_info_data = await HTMLRequests .async_send_website_request_getcode (False , request_user_agent )
236- if search_info_data is None or search_info_data .search_url is None :
237- search_info_data = await HTMLRequests .async_send_website_request_getcode (True , request_user_agent )
219+ search_info_data = await HTMLRequests .async_send_website_request_getcode (request_user_agent )
238220 # Retrieve the request auth token
239221 auth_struct = None
240222 if search_info_data is not None and search_info_data .search_url is not None :
@@ -343,7 +325,7 @@ async def async_get_game_title(game_id: int):
343325 return None
344326
345327 @staticmethod
346- def send_website_request_getcode (parse_all_scripts : bool , user_agent ):
328+ def send_website_request_getcode (user_agent ):
347329 """
348330 Function that send a request to howlongtobeat to scrape the correct search url
349331 @return: The search informations to use in the request
@@ -356,10 +338,10 @@ def send_website_request_getcode(parse_all_scripts: bool, user_agent):
356338 soup = BeautifulSoup (resp .text , HTMLRequests .HTML_PARSER )
357339 # Find all <script> tags with a src attribute containing the substring
358340 scripts = soup .find_all ('script' , src = True )
359- if parse_all_scripts :
360- matching_scripts = [ script ['src' ] for script in scripts ]
361- else :
362- matching_scripts = [ script [ 'src' ] for script in scripts if '_app-' in script [ 'src' ] ]
341+ matching_scripts = [
342+ script ['src' ] for script in scripts
343+ if '/_next/static/chunks/' in script [ 'src' ]
344+ ]
363345 for script_url in matching_scripts :
364346 script_url = HTMLRequests .BASE_URL + script_url
365347 script_resp = requests .get (script_url , headers = headers , timeout = 60 )
@@ -370,7 +352,7 @@ def send_website_request_getcode(parse_all_scripts: bool, user_agent):
370352 return None
371353
372354 @staticmethod
373- async def async_send_website_request_getcode (parse_all_scripts : bool , user_agent ):
355+ async def async_send_website_request_getcode (user_agent ):
374356 """
375357 Function that send a request to howlongtobeat to scrape the correct search url
376358 @return: The search informations to use in the request
@@ -386,10 +368,10 @@ async def async_send_website_request_getcode(parse_all_scripts: bool, user_agent
386368 soup = BeautifulSoup (resp_text , HTMLRequests .HTML_PARSER )
387369 # Find all <script> tags with a src attribute containing the substring
388370 scripts = soup .find_all ('script' , src = True )
389- if parse_all_scripts :
390- matching_scripts = [ script ['src' ] for script in scripts ]
391- else :
392- matching_scripts = [ script [ 'src' ] for script in scripts if '_app-' in script [ 'src' ] ]
371+ matching_scripts = [
372+ script ['src' ] for script in scripts
373+ if '/_next/static/chunks/' in script [ 'src' ]
374+ ]
393375 for script_url in matching_scripts :
394376 script_url = HTMLRequests .BASE_URL + script_url
395377 async with aiohttp .ClientSession () as session :
0 commit comments