Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds auto updater #31

Merged
merged 12 commits into from
Oct 20, 2023
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pypresence==4.2.1
semantic-version==2.10.0
pyinstaller==5.13.0
psutil==5.9.5
psutil==5.9.5
requests==2.31.0
43 changes: 31 additions & 12 deletions src/checkupdate/checkupdate.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
# COMPILE THIS USING --onefile
import semantic_version
import subprocess
from semantic_version import Version
import time
import urllib.request
import time
import json
import sys
import os

from downloadupdate import downloadUpdate

def checkUpdate():
try:

print("Checking for updates in hoi4 presence...")

# picking the current dir
version_path = ""
if getattr(sys, 'frozen', False):
version_path = os.path.dirname(sys.executable)
else:
version_path = os.path.dirname(os.path.abspath(__file__))

localVersion = open(version_path + "/version.json", "r") # use something like .resolve() or clean code
localVersion = json.load(localVersion)
with open(version_path + "/version.json", "r") as f:
localVersion = json.load(f)

print("\nLocal version: ")
print(localVersion)
Expand All @@ -30,13 +36,26 @@ def checkUpdate():
URL = urllib.request.urlopen("https://raw.githubusercontent.com/ThiaudioTT/hoi4-presence/main/version.json")
cloudVersion = json.loads(URL.read())

print("Checking for updates in hoi4 presence...")
if semantic_version.Version(localVersion["version"]) < semantic_version.Version(cloudVersion["version"]):
print("\n\n\nUpdate available!")
print("Please, download the latest version from:\nhttps://github.com/ThiaudioTT/hoi4-presence/releases")
time.sleep(120)
else:
print("Update not found.")
time.sleep(5)
isClientOutdated = Version(localVersion["version"]) < Version(cloudVersion["version"])

if localVersion['auto-update'] and isClientOutdated:

print("Update found!")

downloadPath = downloadUpdate()

if downloadPath is not None:

installerPath = os.path.join(downloadPath, "setup.exe")

print('Updating...\n\n')

# Starting setup.exe in -update mode so it will automatically install and start up the mod
subprocess.Popen([installerPath, "-update"], start_new_session=True, cwd=downloadPath) # passing cwd to the script knows where he is

print('Closing checkUpdate.exe...')

# Close checkUpdate.exe (setup.exe will still run and in the new window)
sys.exit(0)

checkUpdate()
checkUpdate()
76 changes: 76 additions & 0 deletions src/checkupdate/downloadupdate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import os
import shutil

import requests

def downloadUpdate() -> str | None:
'''
Downloads and installs the newest hoi4 update.

Returns download path if successful, else None
'''

try:

downloadTemp: str = None
extractedTemp: str = None

# Get latest release data
latestRelease = requests.get("https://api.github.com/repos/ThiaudioTT/hoi4-presence/releases/latest")

latestReleaseData: dict = latestRelease.json()

# Find asset data api link
assetUrl: str = latestReleaseData["assets_url"]

# Get asset data
assetsData: dict = requests.get(assetUrl , headers={"accept":"application/vnd.github+json"}).json()

# Incase there are muiltiple assets create a for loop
downloadLink: str = None
fileName = f"hoi4-presence-{latestReleaseData['tag_name']}.zip"

for asset in assetsData:

if asset["name"] == fileName:

# Found the download link
downloadLink = asset["browser_download_url"]

break

if downloadLink is not None:

downloadTemp = os.path.join(os.environ["TEMP"], fileName)

# Creating a new file in "write in binary" mode
with open(downloadTemp, "wb") as f:

# Get data for download
request = requests.get(downloadLink, allow_redirects=True, stream=True)

chunksDownloaded = 0
totalChunks = len(request.content)

print("Starting Download")
# Write it to fileName in chunks
for chunk in request.iter_content(1024**2):
print(f"{chunksDownloaded / totalChunks * 100:.0f}%")
f.write(chunk)
chunksDownloaded += len(chunk)

print("100%")
print("Download successful!")

extractedTemp = os.path.join(os.environ["TEMP"], f"hoi4-presence-{latestReleaseData['tag_name']}")

# Unzipping
shutil.unpack_archive(downloadTemp, extractedTemp)

return extractedTemp

except Exception as e:

print(f"An error has occured while updating:\n{e}\n\nStarting current version...")

return None
2 changes: 1 addition & 1 deletion src/checkupdate/version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"OBS:": "THIS IS A TEST VERSION ONLY FOR DELEVOPING PURPOSES",
"version": "0.1.0",
"auto-update": false,
"auto-update": true,
"date": "23-sep-2022"
}
14 changes: 7 additions & 7 deletions src/discordRPC/hoi4RPC.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
path = os.path.dirname(sys.executable)
else:
path = os.path.dirname(os.path.abspath(__file__))

path = os.path.abspath(path + "/../" + "/save games/*.hoi4")

# getting the last modified save file
Expand All @@ -48,7 +48,7 @@
now = int(time.time())
saveNew = (now - dateFile) <= 120 # calc to see if save is recently (2 min recently)
# saveNew = True # for testing

if(saveNew):
print("New save found!")
# putting this in a function might be good.
Expand All @@ -69,7 +69,7 @@
year = data[2][:4]
mode = data[3]


# hint: use discord developer portal
RPC.update(
state="Year: " + year,
Expand All @@ -80,17 +80,17 @@
small_text="In " + mode + " mode",
start=playTime
)

print(data) # debug
except Exception as e:
print(e)
time.sleep(5)
time.sleep(30) #Wait a wee bit

time.sleep(30) # Wait a wee bit
gameRunning = False
for proc in psutil.process_iter():
if proc.name() == "hoi4.exe":
gameRunning = True
break

sys.exit(0) # when game running is false, exit script
sys.exit(0) # when game running is false, exit script
41 changes: 39 additions & 2 deletions src/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,27 @@
import sys
import json

# Parsing arguments
IS_UPDATE = False

num_of_args = len(sys.argv)

if num_of_args >= 2:
IS_UPDATE = sys.argv[1] == "-update"

def customInput() -> str | None:
"""
Checks first if this has been started by the auto updater
so the auto installation doesn't freeze from `input()`
"""

if not IS_UPDATE:
return input()

print("This script will install the hoi4-presence in your game/save path\nPress enter to continue...")
input()
customInput()

# 0 - Stop any running instances of hoi4Presence.exe
# 1 - Move hoi4Presence to documents/paradox/hearts of iron/ WITH CURRENTLY version.json and uninstaller.py
# 1.1 - If can't move, exit.
# 1.2 - If can't search, ask the user where is the path
Expand Down Expand Up @@ -64,6 +82,18 @@
time.sleep(10)
sys.exit()

# 0 - Stop any running instances of hoi4Presence.exe
# TODO: probably theres a better way to do this and this should be executed always
if IS_UPDATE:
print("Stopping any running instances of hoi4Presence.exe...")
result = os.system("taskkill /f /im hoi4Presence.exe")

if result == 0:
print("Process terminated successfully.")
else:
print("Error occurred while terminating the process.")
sys.exit(1)

# 1
documents = os.environ['USERPROFILE'] + "\\Documents\\Paradox Interactive\\Hearts of Iron IV"
while True:
Expand Down Expand Up @@ -131,6 +161,7 @@

# 3
gameFolder = os.environ['PROGRAMFILES(X86)'] + "\\Steam\\steamapps\\common\\Hearts of Iron IV"

while True:
try:
if "hoi4.exe" not in os.listdir(gameFolder):
Expand Down Expand Up @@ -175,6 +206,12 @@
print("\n\nSuccess! The hoi4Presence is installed in your game folder.\n\n")
print("Execute the game via launcher to auto activate the presence.\n\nYou can delete this folder now.\n\n")
print("See https://github.com/ThiaudioTT/hoi4-presence for updates and more information.\n\n")
input()

customInput()

time.sleep(5)

if IS_UPDATE:
os.startfile(os.path.join(gameFolder, "runRPC.bat"))

sys.exit()
4 changes: 2 additions & 2 deletions version.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.1.0",
"auto-update": false,
"version": "1.2.0",
"auto-update": true,
"date": "19-august-2023"
}