import json import mimetypes from pathlib import Path from shutil import rmtree from subprocess import PIPE, STDOUT, Popen import requests import webview from log import logger from python.Lib import shutil, os, subprocess 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窗口 subprocess.Popen([script_path], creationflags=subprocess.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)