Skip to content

Commit

Permalink
Implemented automatic update system. From this version Sku Updater wi…
Browse files Browse the repository at this point in the history
…ll check for self updates and download them automatically
  • Loading branch information
Kirill Belousov committed Sep 8, 2023
1 parent 0c8c2cc commit 94b3f34
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 8 deletions.
2 changes: 1 addition & 1 deletion build.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ if "%CI%" == "true" (
)
)

python prepare_build_info.py
python prepare_build_info.py %curver%
python -m nuitka --standalone --onefile --prefer-source-code --assume-yes-for-downloads --remove-output --lto=yes --company-name=Cyrmax --product-name=Sku_Updater --file-version=%curver% --product-version=%curver% --file-description="A console program to update your installation of Sku for WoW Classic" --copyright="Made by Cyrmax in 2022. MIT license" sku-updater.py
6 changes: 4 additions & 2 deletions build_info.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# This file contains all necessary debug information about the build process.
# This file should be regenerated directly before build process for to contain actual info about build environment.
sku_updater_version = "noversion"
sku_updater_version = "34.26.2"
build_platform = "Windows-10-10.0.22621-SP0"
build_python_version = "3.11.1 (tags/v3.11.1:a7a450f, Dec 6 2022, 19:58:39) [MSC v.1934 64 bit (AMD64)]"
build_python_version = (
"3.11.1 (tags/v3.11.1:a7a450f, Dec 6 2022, 19:58:39) [MSC v.1934 64 bit (AMD64)]"
)
pip_freeze_output = """
beautifulsoup4==4.12.2
black==22.10.0
Expand Down
2 changes: 1 addition & 1 deletion prepare_build_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"# This file should be regenerated directly before build process for to contain actual info about build environment.\n"
)
f.write(
f'sku_updater_version = "{os.environ.get("GITHUB_REF_NAME", "noversion")}"\n'
f'sku_updater_version = "{os.environ.get("GITHUB_REF_NAME", sys.argv[1])}"\n'
)
f.write(f'build_platform = "{platform.platform()}"\n')
f.write(f'build_python_version = "{sys.version}"\n')
Expand Down
94 changes: 90 additions & 4 deletions sku-updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import build_info

SKU_URL = "https://api.github.com/repos/Duugu/Sku/releases/latest"
SKU_UPDATER_URL = "https://api.github.com/repos/cyrmax/sku-updater/releases/latest"
TITLE_UPDATE_TIMESTAMP = time()


Expand All @@ -39,31 +40,48 @@ def handle_exception(exc_type, exc_value, tb):
class Version:
major: int
minor: int
subminor: int
patch: int

def __init__(self, version_string: str):
if not version_string:
raise ValueError("Empty version string")
components = version_string.split(".")
self.major = int(components[0])
self.minor = int(components[1]) if len(components) > 1 else 0
self.subminor = int(components[2]) if len(components) > 2 else 0
self.patch = int(components[3]) if len(components) > 3 else 0

def __eq__(self, other) -> bool:
return self.major == other.major and self.minor == other.minor
return (
self.major == other.major
and self.minor == other.minor
and self.subminor == other.subminor
and self.patch == other.patch
)

def __lt__(self, other) -> bool:
if self.major != other.major:
return self.major < other.major
else:
elif self.minor != other.minor:
return self.minor < other.minor
elif self.subminor != other.subminor:
return self.subminor < other.subminor
else:
return self.patch < other.patch

def __gt__(self, other) -> bool:
if self.major != other.major:
return self.major > other.major
else:
elif self.minor != other.minor:
return self.minor > other.minor
elif self.subminor != other.subminor:
return self.subminor > other.subminor
else:
return self.patch > other.patch

def __str__(self) -> str:
return f"{self.major}.{self.minor}"
return f"{self.major}.{self.minor}.{self.subminor}.{self.patch}"

def __repr__(self):
return str(self)
Expand All @@ -75,6 +93,59 @@ def confirmed_exit(code: int):
sys.exit(code)


def self_update() -> bool:
logging.info("Checking for Sku Updater updates")
current_version = Version(build_info.sku_updater_version)
r = requests.get(SKU_UPDATER_URL)
if r.status_code != 200:
print("Unable to fetch latest Sku Updater version")
logging.error("Unable to fetch latest Sku Updater version")
confirmed_exit(1)
data = json.loads(r.text)
latest_version = Version(data["tag_name"])
if current_version >= latest_version:
return False
else:
print(f"New version of Sku Updater is available: {latest_version}")
print("Downloading latest Sku Updater")
logging.info(f"Downloading latest Sku Updater {latest_version}")
url = None
for asset in data["assets"]:
if asset["name"] == "sku-updater.zip":
url = asset["browser_download_url"]
break
if url is None:
print("Unable to download latest Sku Updater")
logging.error("Unable to download latest Sku Updater")
confirmed_exit(1)
local_filename = url.split("/")[-1]
with requests.get(url, stream=True) as r:
r.raise_for_status()
downloaded_size = 0
total_size = int(r.headers["Content-Length"])
print(f"{total_size / (1024 * 1024):.2f} MB will be downloaded")
with open(local_filename, "wb") as f:
for chunk in r.iter_content(16384):
f.write(chunk)
downloaded_size += len(chunk)
update_title(downloaded_size, total_size)
print("Unpacking Sku Updater")
logging.info("Unpacking Sku Updater")
os.makedirs("tmp", exist_ok=True)
with zipfile.ZipFile(local_filename, "r") as zip_ref:
zip_ref.extractall("tmp")
os.remove(local_filename)
print("Restarting")
logging.info("Creating temporary bat file")
with open("sku-updater-restart.bat", "w") as f:
f.write("@echo off\r\n")
f.write("ping -n 5 localhost > nul\r\n")
f.write("del sku-updater.exe\r\n")
f.write("copy tmp\\sku-updater.exe sku-updater.exe\r\n")
f.write("start sku-updater.exe\r\n")
return True


def find_wowc() -> str:
key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE,
Expand Down Expand Up @@ -172,6 +243,9 @@ def main():
help="Just save diagnostic information to log file and exit without updating.",
action="store_true",
)
parser.add_argument(
"-s", "--skip-update", help="Skip Sku Updater update", action="store_true"
)
args = parser.parse_args()
logging.info(f"Sku Updater started at {dt.now()}")
logging.info(f"Running on {platform.platform()}")
Expand All @@ -191,6 +265,18 @@ def main():
"Diagnostic info saved to sku-updater.log file. If necessary, send it to the developer."
)
confirmed_exit(0)
try:
os.remove("sku-updater-restart.bat")
os.remove("tmp\\sku-updater.exe")
os.removedirs("tmp")
except FileNotFoundError:
pass
if args.skip_update:
print("Skipping Sku Updater update")
else:
if self_update():
os.startfile("sku-updater-restart.bat")
sys.exit(0)
print("Searching World of Warcraft Classic installation...")
logging.debug("Searching World of Warcraft Classic installation...")
try:
Expand Down

0 comments on commit 94b3f34

Please sign in to comment.