Skip to content

Commit 0dd595d

Browse files
committed
Update 1.01
The old method for checking for updates and downloading stopped working. Replaced with using cloudscraper
1 parent 09f58c2 commit 0dd595d

2 files changed

Lines changed: 49 additions & 40 deletions

File tree

Improvement Mod Launcher.pyw

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import sys
2222
from datetime import date
2323
import webbrowser
2424
import ctypes.wintypes
25+
import cloudscraper
2526

2627
def debug(message:str, log:str) -> None: # Needs string message and string log message, does not return anything
2728
if gDebugger: # Display logs when enabled
@@ -189,7 +190,9 @@ def download_update_thread(): # Download the new update as a separate thread
189190
if os.path.exists(zip_path):
190191
debug("download_update_thread", "Removing mod_file.zip")
191192
os.remove(zip_path)
192-
with requests.get(gModDownloadUrl, stream=True) as response:
193+
194+
scraper = cloudscraper.create_scraper(interpreter="nodejs", delay=5) # Create a Cloudscraper session that solves Cloudflare
195+
with scraper.get(gModDownloadUrl, stream=True, timeout=60) as response:
193196
response.raise_for_status() # Raise an error if the request fails
194197
total_size = int(response.headers.get("Content-Length", 0)) # Get file size
195198
block_size = 1024 # Define block size for downloading (1 KB)
@@ -300,13 +303,22 @@ def check_updates(url: str) -> str: # Function to check for mod updates by compa
300303
global gLast_updated # Global variable to store the 'Last-Modified' header of the latest update
301304
global gUpdateMod_button # Global variable to reference the update button in the UI
302305
debug("check_updates", "checking for updates") # Log the start of the update check
303-
304306
try: # Send a HEAD request to the URL to get metadata, but not the content
305-
response = requests.head(url, allow_redirects=True)
306-
response.raise_for_status() # Raise an exception if the request fails (non-2xx status code)
307-
gLast_updated = response.headers.get("ETag", "No Last-Modified header found") # Get the 'Last-Modified' header from the response or provide a default message if it's not found
308-
update_date = response.headers.get("Last-Modified", "No Last-Modified header found")
309-
debug("check_updates Last updated date", gLast_updated) # Log the 'Last-Modified' header
307+
scraper = cloudscraper.create_scraper(interpreter="nodejs", delay=5)
308+
headers = {
309+
"Referer": "https://www.moddb.com/mods/improvement-mod/downloads/",
310+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
311+
}
312+
# Use stream=True to avoid downloading the whole file
313+
response = scraper.get(url, headers=headers, stream=True, allow_redirects=True)
314+
315+
if response.ok:
316+
gLast_updated = response.headers.get("Last-Modified", "Not found")
317+
update_date = gLast_updated
318+
debug("check_updates Last updated date", gLast_updated) # Log the 'Last-Modified' header
319+
else:
320+
add_log("Update response not OK")
321+
310322
if gConfigUserInfo["lastupdate"] != gLast_updated: # Compare the stored 'Last-Modified' date with the value received in the response
311323
debug("check_updates", f"{gConfigUserInfo['lastupdate']} != {gLast_updated}") # Log the mismatch between the stored and received date
312324
gUpdate_label.configure(text=f"Improvement Mod New Update - {truncate_string(update_date, max_length=550, placeholder="...")}") # Update the UI to indicate that a new update is available
@@ -321,7 +333,7 @@ def check_updates(url: str) -> str: # Function to check for mod updates by compa
321333
add_log("Cannot check for updates") # Add the error message to the log
322334
gUpdateButton_label.configure(text="Reinstall Mod")
323335
return "" # Return an empty string to indicate an error has occurred
324-
336+
325337
def startGame_button_click() -> None:
326338
global gThreadStop_event
327339
debug("startGame_button_click","Starting game")
@@ -641,38 +653,34 @@ def is_msxml4_installed() -> bool:
641653
continue
642654
return False
643655

644-
def find_download_mirror() -> None: # Find the download link from moddb
656+
def find_download_mirror() -> None:
645657
global gModDownloadUrl
646-
start_url = "https://www.moddb.com/downloads/start/286602?referer=https%3A%2F%2Fwww.moddb.com%2Fmods%2Fimprovement-mod%2Fdownloads" # Find the download page from moddb
647-
headers = { # Headers to mimic a real browser to get the mirror link
648-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
658+
url = "https://www.moddb.com/downloads/start/286602?referer=https%3A%2F%2Fwww.moddb.com%2Fmods%2Fimprovement-mod%2Fdownloads%2F"
659+
headers = {
649660
"Referer": "https://www.moddb.com/mods/improvement-mod/downloads/improvement-mod-manual-install-new"
650661
}
651-
# Fetch the HTML content
652-
session = requests.Session()
662+
663+
scraper = cloudscraper.create_scraper(
664+
browser={"browser": "chrome", "platform": "windows", "mobile": False},
665+
interpreter="js2py",
666+
delay=5, # allow JS challenge time
667+
debug=True # log details if challenge fails
668+
)
669+
653670
try:
654-
response = session.get(start_url, headers=headers, timeout=5)
655-
except requests.exceptions.ConnectionError:
656-
add_log("No internet connection available")
657-
return
658-
except requests.exceptions.Timeout:
659-
add_log("Update check failed")
660-
return
661-
except requests.exceptions.RequestException as e:
662-
print(f"An error has occurred: {e}")
663-
add_log("Update check failed")
671+
response = scraper.get(url, headers=headers, timeout=15)
672+
response.raise_for_status()
673+
except Exception as e:
674+
add_log(f"Failed to fetch: {e}")
664675
return
665676

666-
soup = BeautifulSoup(response.text, "html.parser") # Parse the HTML using BeautifulSoup
667-
# Look for the mirror link inside the page
668-
mirror_link = None
669-
for a in soup.find_all("a", href=True):
670-
if "/downloads/mirror/" in a["href"]:
671-
mirror_link = "https://www.moddb.com" + a["href"]
672-
break
673-
if mirror_link:
674-
gModDownloadUrl = mirror_link
675-
debug("find_download_mirror Mirror Link Found:",mirror_link)
677+
soup = BeautifulSoup(response.text, "html.parser")
678+
mirror = next((a["href"] for a in soup.find_all("a", href=True)
679+
if "/downloads/mirror/" in a["href"]), None)
680+
681+
if mirror:
682+
gModDownloadUrl = "https://www.moddb.com" + mirror
683+
debug("Mirror Link Found:", gModDownloadUrl)
676684
else:
677685
add_log("Mirror Link not Found")
678686

@@ -1051,8 +1059,8 @@ if __name__ == '__main__':
10511059
else: # Running as a script
10521060
gApp.iconbitmap(r"icon\icon.ico") # Set the path to the icon file for script
10531061

1054-
gVersion:str = "1.00" # App version
1055-
gGitHubVersion:str = "version1.00"
1062+
gVersion:str = "1.01" # App version
1063+
gGitHubVersion:str = "version1.01"
10561064

10571065
gModDownloadUrl:str = "" # Hold the URL for the mirror download
10581066
gLast_updated:str = "" # Stores the last date the file was installed
@@ -1099,4 +1107,5 @@ if __name__ == '__main__':
10991107
gLog_font:ctk.CTkFont = None
11001108
gAi_font:ctk.CTkFont = None
11011109
gLogTextBox:ctk.CTkTextbox = None
1110+
11021111
main()

version/version_info.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ VSVersionInfo(
66
ffi=FixedFileInfo(
77
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
88
# Set not needed items to zero 0.
9-
filevers=(1, 0, 0, 0),
10-
prodvers=(1, 0, 0, 0),
9+
filevers=(1, 0, 1, 0),
10+
prodvers=(1, 0, 1, 0),
1111
# Contains a bitmask that specifies the valid bits 'flags'r
1212
mask=0x3f,
1313
# Contains a bitmask that specifies the Boolean attributes of the file.
@@ -31,12 +31,12 @@ VSVersionInfo(
3131
u'040904B0',
3232
[StringStruct(u'CompanyName', u'ageekhere'),
3333
StringStruct(u'FileDescription', u'Improvement Mod Launcher'),
34-
StringStruct(u'FileVersion', u'1.000'),
34+
StringStruct(u'FileVersion', u'1.010'),
3535
StringStruct(u'InternalName', u'Improvement Mod Launcher'),
3636
StringStruct(u'LegalCopyright', u'ageekhere'),
3737
StringStruct(u'OriginalFilename', u'Improvement Mod Launcher'),
3838
StringStruct(u'ProductName', u'Improvement Mod Launcher'),
39-
StringStruct(u'ProductVersion', u'1.0.0.0')])
39+
StringStruct(u'ProductVersion', u'1.0.1.0')])
4040
]),
4141
VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
4242
]

0 commit comments

Comments
 (0)