Skip to content

Commit 0fc50e2

Browse files
committed
1.03
Improved update check
1 parent 9897f62 commit 0fc50e2

2 files changed

Lines changed: 76 additions & 46 deletions

File tree

Improvement Mod Launcher.pyw

Lines changed: 72 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import os
88
from pathlib import Path
99
from PIL import Image, ImageTk
1010
from psutil import process_iter
11-
import requests
11+
import requests, urllib.parse
1212
from shutil import copyfileobj, rmtree
1313
from subprocess import run, CalledProcessError, STARTUPINFO, STARTF_USESHOWWINDOW
1414
from tempfile import mkdtemp
@@ -23,6 +23,8 @@ from datetime import date
2323
import webbrowser
2424
import ctypes.wintypes
2525
import cloudscraper
26+
from datetime import datetime, timedelta
27+
from email.utils import parsedate_to_datetime
2628

2729
def debug(message:str, log:str) -> None: # Needs string message and string log message, does not return anything
2830
if gDebugger: # Display logs when enabled
@@ -177,6 +179,7 @@ def download_update_thread(): # Download the new update as a separate thread
177179
global gStartGame_button
178180
global gStartGameButton_label
179181
global gAiDropDown
182+
global gUpdateSize
180183
process_names = ["age3m.exe", "age3x.exe", "age3.exe", "age3y.exe"]
181184
for process_name in process_names:
182185
if is_process_running(process_name):
@@ -289,7 +292,7 @@ def download_update_thread(): # Download the new update as a separate thread
289292
else: # If download was Cancelled, show the update button again
290293
enable_all_widgets()
291294
gThreadStop_event.set()
292-
check_updates(gModDownloadUrl) # Check for future updates
295+
check_updates("https://www.moddb.com/mods/improvement-mod/downloads/improvement-mod-manual-install-new") # Check for future updates
293296
install_check()
294297
except Exception as e: # Handle errors while deleting ZIP file
295298
debug("download_update_thread", "Error deleting zip file:" + str(e))
@@ -306,33 +309,36 @@ def download_update() -> None:
306309
gDownloadThread = Thread(target=download_update_thread, daemon=True)
307310
gApp.after(1, gDownloadThread.start())
308311

312+
309313
def check_updates(url: str) -> str: # Function to check for mod updates by comparing the 'Last-Modified' header from the server
310314
global gLast_updated # Global variable to store the 'Last-Modified' header of the latest update
311315
global gUpdateMod_button # Global variable to reference the update button in the UI
316+
global gUpdateSize # Stores the size of the zip
317+
312318
debug("check_updates", "checking for updates") # Log the start of the update check
313319
try: # Send a HEAD request to the URL to get metadata, but not the content
314-
scraper = cloudscraper.create_scraper(interpreter="nodejs", delay=5)
315-
headers = {
316-
"Referer": "https://www.moddb.com/mods/improvement-mod/downloads/",
317-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
318-
}
319-
# Use stream=True to avoid downloading the whole file
320-
response = scraper.get(url, headers=headers, stream=True, allow_redirects=True)
321-
322-
if response.ok:
323-
gLast_updated = response.headers.get("Last-Modified", "Not found")
324-
update_date = gLast_updated
325-
debug("check_updates Last updated date", gLast_updated) # Log the 'Last-Modified' header
326-
else:
327-
add_log("Update response not OK")
328-
329-
if gConfigUserInfo["lastupdate"] != gLast_updated: # Compare the stored 'Last-Modified' date with the value received in the response
320+
321+
# Use a proxy that fetches the HTML for us
322+
proxy_url = "https://api.allorigins.win/get?url=" + urllib.parse.quote(url, safe="")
323+
response = requests.get(proxy_url, timeout=15)
324+
response.raise_for_status()
325+
html = response.json()["contents"]
326+
327+
soup = BeautifulSoup(html, "html.parser")
328+
updated_tag = soup.find("h5", string="Updated")
329+
if updated_tag:
330+
time_tag = updated_tag.find_next("time")
331+
if time_tag:
332+
gLast_updated = time_tag.text.strip()
333+
334+
debug("check_updates - webcheck update",gLast_updated)
335+
if gLast_updated != gConfigUserInfo["lastupdate"] :
330336
debug("check_updates", f"{gConfigUserInfo['lastupdate']} != {gLast_updated}") # Log the mismatch between the stored and received date
331-
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
337+
gUpdate_label.configure(text=f"Improvement Mod New Update - {truncate_string(gLast_updated, max_length=550, placeholder="...")}") # Update the UI to indicate that a new update is available
332338
gUpdateMod_button.configure(text="Update Now") # Enable the update button for the user to click
333339
else: # If the dates match, the mod is up-to-date
334340
debug("check_updates", "UpToDate") # Log that the mod is up-to-date
335-
gUpdate_label.configure(text=f"Improvement Mod Up-to-date - {update_date}") # Update the UI to indicate that the mod is up-to-date
341+
gUpdate_label.configure(text=f"Improvement Mod Up-to-date - {gLast_updated}") # Update the UI to indicate that the mod is up-to-date
336342
gUpdateButton_label.configure(text="Reinstall Mod")
337343

338344
except requests.RequestException as e: # Catch network-related errors during the HTTP request
@@ -341,6 +347,7 @@ def check_updates(url: str) -> str: # Function to check for mod updates by compa
341347
gUpdateButton_label.configure(text="Reinstall Mod")
342348
return "" # Return an empty string to indicate an error has occurred
343349

350+
344351
def startGame_button_click() -> None:
345352
global gThreadStop_event
346353
debug("startGame_button_click","Starting game")
@@ -693,38 +700,60 @@ def find_download_mirror() -> None:
693700
else:
694701
add_log("Mirror Link not Found")
695702

696-
def make_config() -> None: # Make a user config file to save preferences
703+
def make_config() -> None: # Make a user config file to save preferences
697704
debug("make_config Creating", "config")
698705
global gConfigPath
699706
global gConfigUserData
700707
global gConfigUserInfo
701708
global gGamePath
702-
gConfigUserData = ConfigParser()
703-
gConfigPath = Path("ImprovementModLauncher.ini") # Relative path to INI file
709+
710+
gConfigUserData = ConfigParser()
711+
gConfigPath = Path("ImprovementModLauncher.ini")
712+
713+
# Define defaults
714+
defaults = {
715+
"gamepath": str(os.getcwd()),
716+
"lastupdate": "na",
717+
"showlogs": "0",
718+
"updatelastcheck": ""
719+
}
720+
704721
try:
705-
if gConfigPath.is_file(): # Check if the INI file exists
706-
read_write_config("r") # Read the config file
707-
else: # Set the defaults of the INI file if the file does not exists and create it
708-
gConfigUserData["USERINFO"] = {
709-
"gamepath": str(os.getcwd()),
710-
"lastupdate": "na",
711-
"showlogs": "0",
712-
"updatelastcheck": ""
713-
}
714-
read_write_config("w") # Wright to the config
715-
read_write_config("r") # Read the new config
716-
gConfigUserInfo = gConfigUserData["USERINFO"] # Store the INI settings information
717-
gGamePath = gConfigUserInfo["gamepath"] # Get the saved game path dir
722+
if gConfigPath.is_file():
723+
# Read existing config
724+
read_write_config("r")
725+
else:
726+
# Create section if file doesn’t exist
727+
gConfigUserData["USERINFO"] = {}
728+
729+
# Ensure section exists
730+
if "USERINFO" not in gConfigUserData:
731+
gConfigUserData["USERINFO"] = {}
732+
733+
# Fill in any missing keys with defaults
734+
for key, value in defaults.items():
735+
if key not in gConfigUserData["USERINFO"]:
736+
gConfigUserData["USERINFO"][key] = value
737+
738+
# Save changes
739+
read_write_config("w")
740+
read_write_config("r")
741+
742+
gConfigUserInfo = gConfigUserData["USERINFO"]
743+
gGamePath = gConfigUserInfo.get("gamepath", str(os.getcwd()))
718744
if gGamePath == "":
719745
gGamePath = str(os.getcwd())
746+
720747
debug("make_config Config created ", "successfully")
721-
except PermissionError: # File Permission Error
748+
749+
except PermissionError: # File Permission Error
722750
debug("make_config Permission denied", "PermissionError")
723-
except OSError as e: # OSError
751+
except OSError as e: # OSError
724752
debug(f"make_config OS error has occurred: {e}", "OSError")
725-
except Exception as e: # Exception
753+
except Exception as e: # Exception
726754
debug(f"make_config An unexpected error has occurred: {e}", "Exception")
727755

756+
728757
def select_folder() -> None:
729758
global gGamePath
730759
try:
@@ -1005,7 +1034,7 @@ def main():
10051034
make_config()
10061035
interface()
10071036
find_download_mirror()
1008-
check_updates(gModDownloadUrl)
1037+
check_updates("https://www.moddb.com/mods/improvement-mod/downloads/improvement-mod-manual-install-new")
10091038
read_ai_zip()
10101039
install_check()
10111040

@@ -1068,8 +1097,8 @@ if __name__ == '__main__':
10681097
else: # Running as a script
10691098
gApp.iconbitmap(r"icon\icon.ico") # Set the path to the icon file for script
10701099

1071-
gVersion:str = "1.02" # App version
1072-
gGitHubVersion:str = "version1.02"
1100+
gVersion:str = "1.03" # App version
1101+
gGitHubVersion:str = "version1.03"
10731102

10741103
gModDownloadUrl:str = "" # Hold the URL for the mirror download
10751104
gLast_updated:str = "" # Stores the last date the file was installed
@@ -1116,5 +1145,6 @@ if __name__ == '__main__':
11161145
gLog_font:ctk.CTkFont = None
11171146
gAi_font:ctk.CTkFont = None
11181147
gLogTextBox:ctk.CTkTextbox = None
1148+
gUpdateSize = None
11191149

11201150
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, 2, 0),
10-
prodvers=(1, 0, 2, 0),
9+
filevers=(1, 0, 3, 0),
10+
prodvers=(1, 0, 3, 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.020'),
34+
StringStruct(u'FileVersion', u'1.030'),
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.2.0')])
39+
StringStruct(u'ProductVersion', u'1.0.3.0')])
4040
]),
4141
VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
4242
]

0 commit comments

Comments
 (0)