Files
aza/AzA march 2026/desktop_update_check.py

127 lines
3.5 KiB
Python
Raw Permalink Normal View History

2026-03-25 22:03:39 +01:00
import os
2026-04-16 13:32:32 +02:00
import sys
2026-03-25 22:03:39 +01:00
import tempfile
2026-04-16 13:32:32 +02:00
import webbrowser
2026-03-25 22:03:39 +01:00
import requests
from aza_version import APP_CHANNEL, APP_VERSION
2026-04-16 13:32:32 +02:00
UPDATE_MANIFEST_URL = "https://api.aza-medwork.ch/download/version.json"
_MIN_INSTALLER_BYTES = 1_000_000
2026-03-25 22:03:39 +01:00
def _is_newer_version(latest: str, current: str) -> bool:
def parse(v: str):
parts = []
for p in str(v).strip().split("."):
try:
parts.append(int(p))
except Exception:
parts.append(0)
while len(parts) < 3:
parts.append(0)
return tuple(parts[:3])
return parse(latest) > parse(current)
def check_for_updates():
try:
2026-04-16 13:32:32 +02:00
r = requests.get(UPDATE_MANIFEST_URL, timeout=4)
2026-03-25 22:03:39 +01:00
if r.status_code != 200:
return None
data = r.json()
latest = str(data.get("version") or "").strip()
channel = str(data.get("channel") or "stable").strip()
2026-04-16 13:32:32 +02:00
download_url = str(data.get("download_url") or "").strip()
2026-03-25 22:03:39 +01:00
2026-04-16 13:32:32 +02:00
if channel != APP_CHANNEL:
return None
2026-03-25 22:03:39 +01:00
2026-04-16 13:32:32 +02:00
if latest and _is_newer_version(latest, APP_VERSION):
2026-03-25 22:03:39 +01:00
return {
"update_available": True,
"latest_version": latest,
2026-04-16 13:32:32 +02:00
"download_url": download_url,
2026-03-25 22:03:39 +01:00
}
2026-04-16 13:32:32 +02:00
return None
2026-03-25 22:03:39 +01:00
except Exception:
return None
2026-04-16 13:32:32 +02:00
def _download_installer(download_url: str) -> str | None:
"""Downloads installer to TEMP. Returns path on success, None on failure."""
2026-03-25 22:03:39 +01:00
try:
2026-04-16 13:32:32 +02:00
target = os.path.join(tempfile.gettempdir(), "aza_desktop_setup_latest.exe")
with requests.get(download_url, stream=True, timeout=60) as r:
2026-03-25 22:03:39 +01:00
if r.status_code != 200:
return None
2026-04-16 13:32:32 +02:00
with open(target, "wb") as f:
for chunk in r.iter_content(chunk_size=512 * 1024):
2026-03-25 22:03:39 +01:00
if chunk:
f.write(chunk)
2026-04-16 13:32:32 +02:00
if os.path.isfile(target) and os.path.getsize(target) >= _MIN_INSTALLER_BYTES:
return target
return None
2026-03-25 22:03:39 +01:00
except Exception:
return None
2026-04-16 13:32:32 +02:00
def prompt_update_if_available():
"""Prueft auf Update, zeigt Dialog, laedt Installer herunter und startet ihn."""
info = check_for_updates()
if not info or not info.get("update_available"):
return
2026-03-25 22:03:39 +01:00
2026-04-16 13:32:32 +02:00
download_url = info.get("download_url", "")
latest_version = info.get("latest_version", "")
try:
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
root.withdraw()
answer = messagebox.askyesno(
"Update verfuegbar",
f"AZA {latest_version} ist verfuegbar.\n\n"
f"Ihre Version: {APP_VERSION}\n\n"
"Moechten Sie das Update jetzt installieren?",
parent=root,
)
if not answer:
root.destroy()
return
root.destroy()
installer_path = _download_installer(download_url)
if installer_path:
os.startfile(installer_path)
sys.exit(0)
_root2 = tk.Tk()
_root2.withdraw()
retry = messagebox.askyesno(
"Download fehlgeschlagen",
"Das Update konnte nicht heruntergeladen werden.\n\n"
"Moechten Sie die Download-Seite im Browser oeffnen?",
parent=_root2,
)
if retry and download_url:
webbrowser.open(download_url)
_root2.destroy()
2026-03-25 22:03:39 +01:00
except Exception:
2026-04-16 13:32:32 +02:00
pass
2026-03-25 22:03:39 +01:00
if __name__ == "__main__":
result = check_for_updates()
print(result)