import os import json import shutil import tempfile import zipfile import urllib.request CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config.json") EXCLUDE_PATHS = { "data", "config.json", "logs.log", "updater" } def load_config(): with open(CONFIG_PATH, "r", encoding="utf-8") as f: return json.load(f) def get_latest_release(cfg): url = f"{cfg['host']}/api/v1/repos/{cfg['user']}/{cfg['repo']}/releases/latest" with urllib.request.urlopen(url) as r: return json.loads(r.read().decode("utf-8")) def download(url, path): urllib.request.urlretrieve(url, path) def should_exclude(relative_path: str) -> bool: parts = set(relative_path.split(os.sep)) return any(ex in parts for ex in EXCLUDE_PATHS) def apply_update(src_root, target_root): for root, dirs, files in os.walk(src_root): rel_dir = os.path.relpath(root, src_root) if rel_dir == ".": rel_dir = "" for file in files: rel_path = os.path.normpath(os.path.join(rel_dir, file)) if should_exclude(rel_path): continue src_file = os.path.join(root, file) dst_file = os.path.join(target_root, rel_path) os.makedirs(os.path.dirname(dst_file), exist_ok=True) shutil.copy2(src_file, dst_file) cfg = load_config() release = get_latest_release(cfg) zip_url = release["zipball_url"] tmp = tempfile.mkdtemp() zip_path = os.path.join(tmp, "release.zip") print("Downloading:", release["tag_name"]) download(zip_url, zip_path) with zipfile.ZipFile(zip_path, "r") as z: z.extractall(tmp) extracted_root = os.path.join(tmp, os.listdir(tmp)[0]) project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) apply_update(extracted_root, project_root) print("Update success!")