import json import mimetypes from pathlib import Path from shutil import rmtree from subprocess import CREATE_NO_WINDOW, PIPE, STDOUT, Popen import requests import webview from log import logger import shutil import os mimetypes.add_type("text/html", ".html") mimetypes.add_type("text/css", ".css") mimetypes.add_type("application/javascript", ".js") version = "v0.2" config = { "page": "init", "branch": "slow", "mirror": "aliyun", } config_path = Path("launcher.json") get_new_version_url = ( "https://git.zhaozuohong.vip/api/v1/repos/mower-ng/launcher/releases/latest" ) upgrade_script_name = "upgrade.bat" try: with config_path.open("r") as f: user_config = json.load(f) config.update(user_config) except Exception: pass def custom_event(data): data = json.dumps({"log": data}) js = f"var event = new CustomEvent('log', {{detail: {data}}}); window.dispatchEvent(event);" window.evaluate_js(js) mirror_list = { "pypi": "https://pypi.org/simple", "aliyun": "https://mirrors.aliyun.com/pypi/simple/", "tuna": "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple", "sjtu": "https://mirror.sjtu.edu.cn/pypi/web/simple", } command_list = { "lfs": "git\\bin\\git lfs install", "ensurepip": "python\\python -m ensurepip --default-pip", "clone": "git\\bin\\git clone https://git.zhaozuohong.vip/mower-ng/mower-ng.git --branch slow", "fetch": lambda: f"..\\git\\bin\\git fetch origin {config['branch']}", "switch": lambda: f"..\\git\\bin\\git switch -f {config['branch']}", "reset": lambda: f"..\\git\\bin\\git reset --hard origin/{config['branch']}", "pip_install": lambda: f"..\\python\\Scripts\\pip install --no-cache-dir -i {mirror_list[config['mirror']]} -r requirements.txt --no-warn-script-location", "webview": "start ..\\python\\pythonw webview_ui.py", "manager": "start ..\\python\\pythonw manager.py", } class Api: def get_branch(self): return config["branch"] def set_branch(self, branch): config["branch"] = branch def get_page(self): return config["page"] def set_page(self, page): config["page"] = page def get_mirror(self): return config["mirror"] def set_mirror(self, mirror): config["mirror"] = mirror def get_version(self): return version def get_new_version(self): logger.info("获取最新版本号") response = requests.get(get_new_version_url) return response.json() # 更新启动器本身 def update_self(self, download_url): # 下载压缩包的全路径 download_path = os.path.join(os.getcwd(), os.path.basename(download_url)) logger.info(f"下载新版本: {download_url}到{download_path}") response = requests.get(download_url, stream=True) if response.status_code == 200: with open(download_path, "wb") as file: shutil.copyfileobj(response.raw, file) logger.info("下载完成") else: logger.error(f"下载新版本失败: {response.status_code}") return f"下载新版本失败: {response.status_code}" script_path = os.path.join(os.getcwd(), upgrade_script_name) folder_path = os.path.join(os.getcwd(), "_internal") exe_path = os.path.join(os.getcwd(), "launcher.exe") with open(script_path, "w") as b: TempList = f"@echo off\n" TempList += f"timeout /t 3 /nobreak\n" # 等待进程退出 TempList += f"rmdir {folder_path}\n" # 删除_internal TempList += f"del {exe_path}\n" # 删除exe TempList += f"tar -xf {download_path} -C ..\n" # 解压压缩包 TempList += f"timeout /t 1 /nobreak\n" # 等待解压 TempList += f"start {exe_path}\n" # 启动新程序 TempList += f"del {download_path}\n" # 删除压缩包 TempList += f"exit" b.write(TempList) # 不显示cmd窗口 Popen([script_path], creationflags=CREATE_NO_WINDOW) os._exit(0) def rm_site_packages(self): site_packages_path = Path("./python/Lib/site-packages") if site_packages_path.exists(): rmtree(site_packages_path) return "site-packages目录移除成功" return "python\\Lib\\site-packages目录不存在" def rm_python_scripts(self): python_scripts_path = Path("./python/Scripts") if python_scripts_path.exists(): rmtree(python_scripts_path) return "Scripts目录移除成功" return "python\\Scripts目录不存在" def run(self, command, cwd=None): command = command_list[command] if callable(command): command = command() custom_event(command + "\n") try: with Popen( command, stdout=PIPE, stderr=STDOUT, shell=True, cwd=cwd, bufsize=0 ) as p: for data in p.stdout: try: text = data.decode("utf-8") except Exception: text = data.decode("gbk") custom_event(text) if p.returncode == 0: return "success" except Exception as e: custom_event(str(e)) return "failed" # 如果当前路径存在更新脚本,则删除 if Path(upgrade_script_name).exists(): os.remove(upgrade_script_name) window = webview.create_window( f"mower-ng launcher {version}", "ui/dist/index.html", js_api=Api() ) # window = webview.create_window(f"mower-ng launcher {version}", "http://localhost:5173/", js_api=Api()) webview.start() with config_path.open("w") as f: json.dump(config, f)