""" 启动小狸就启动原神防止用户没原神玩会无聊死插件 (全自动版) ====================================================== 加载即运行,无需任何命令。 启动小狸 → 检测原神 → 有游戏就启动 / 有启动器就打开 / 什么都没有就安装启动器。 真正的防无聊守护神。 """ import os import sys import subprocess import tempfile import time import threading import requests from pathlib import Path from colorama import Fore, Style class Plugin: """原神自动守护插件""" # 官方启动器下载链接(定期更新) LAUNCHER_DOWNLOAD_URL = ( "https://download.cg.qq.com/launcher/hoyoplay/HoYoPlay_installer_202503121746.exe" ) BACKUP_LAUNCHER_URL = ( "https://autopatchcn.yuanshen.com/client_app/download/launcher/202503121746_1.0.0.0.exe" ) # 常见游戏路径 GENSHIN_PATHS = [ r"C:\Program Files\Genshin Impact\Genshin Impact Game\YuanShen.exe", r"C:\Program Files\Genshin Impact\Genshin Impact Game\GenshinImpact.exe", r"C:\Program Files (x86)\Genshin Impact\Genshin Impact Game\YuanShen.exe", r"D:\Genshin Impact\Genshin Impact Game\YuanShen.exe", r"E:\Genshin Impact\Genshin Impact Game\YuanShen.exe", ] LAUNCHER_DIR = r"C:\Program Files\miHoYo Launcher" LAUNCHER_EXE = os.path.join(LAUNCHER_DIR, "launcher.exe") def __init__(self): # 插件加载时自动触发,为避免阻塞主线程,新开线程执行 print(f"{Fore.MAGENTA}🧸 原神守护插件已激活!正在尝试启动原神...{Style.RESET_ALL}") t = threading.Thread(target=self._auto_launch, daemon=True) t.start() def set_cli(self, cli): """保存CLI引用(本插件不需要命令注册)""" self.cli = cli def get_tool_info(self): """提供工具信息(虽然不会主动调用,但会让AI知道这个插件存在)""" return { "name": "auto_genshin_launcher", "description": "启动小狸即自动检测并启动原神/安装米哈游启动器,无需手动操作。", "keywords": ["原神", "启动", "自动", "米哈游"], "usage": "本插件无需手动调用,加载即生效。" } def handle(self, args): """防呆接口,如果有笨笨的AI非要调用,就返回状态""" return "✨ 原神守护已就绪,它在后台默默守护着你~" # ---------- 核心自动逻辑 ---------- def _auto_launch(self): """自动检测并启动原神/启动器""" if os.name != 'nt': print(f"{Fore.RED}🛑 原神守护仅支持Windows系统~{Style.RESET_ALL}") return # 1. 已安装游戏 → 直接启动 game_path = self._find_genshin_game() if game_path: print(f"{Fore.GREEN}🎮 检测到原神!启动游戏...{Style.RESET_ALL}") self._launch_genshin(game_path) return # 2. 已安装启动器 → 打开启动器 if self._launcher_exists(): print(f"{Fore.GREEN}✅ 米哈游启动器已安装,正在打开...{Style.RESET_ALL}") self._launch_launcher() return # 3. 什么都没有 → 下载安装启动器 print(f"{Fore.YELLOW}📦 未检测到原神和启动器,正在自动安装米哈游启动器(需要管理员权限)...{Style.RESET_ALL}") if self._download_and_install_launcher(): print(f"{Fore.GREEN}🎉 启动器安装完成!正在打开...{Style.RESET_ALL}") self._launch_launcher() else: print(f"{Fore.RED}😭 安装失败,请手动从官网下载:https://ys.mihoyo.com{Style.RESET_ALL}") def _find_genshin_game(self): for path in self.GENSHIN_PATHS: if os.path.exists(path): return path return None def _launcher_exists(self): return os.path.exists(self.LAUNCHER_EXE) def _launch_genshin(self, exe_path): try: subprocess.Popen([exe_path], cwd=os.path.dirname(exe_path)) print(f"{Fore.CYAN}✨ 原神正在启动,旅行者,提瓦特见!{Style.RESET_ALL}") except Exception as e: print(f"{Fore.RED}启动原神失败: {e}{Style.RESET_ALL}") def _launch_launcher(self): try: subprocess.Popen([self.LAUNCHER_EXE], cwd=self.LAUNCHER_DIR) print(f"{Fore.CYAN}✅ 启动器已打开,请手动下载原神~{Style.RESET_ALL}") except Exception as e: print(f"{Fore.RED}打开启动器失败: {e}{Style.RESET_ALL}") def _download_and_install_launcher(self): tmp_dir = tempfile.gettempdir() installer_path = os.path.join(tmp_dir, "HoYoPlay_installer.exe") if os.path.exists(installer_path): os.remove(installer_path) url = self.LAUNCHER_DOWNLOAD_URL if not self._download_file(url, installer_path): print(f"{Fore.YELLOW}⚠️ 主链接失败,尝试备用链接...{Style.RESET_ALL}") if not self._download_file(self.BACKUP_LAUNCHER_URL, installer_path): return False print(f"{Fore.YELLOW}⚙️ 正在静默安装(等待约30秒)...{Style.RESET_ALL}") try: # 静默安装,/S 适用于NSIS安装包 subprocess.run([installer_path, "/S"], shell=True, capture_output=True) time.sleep(15) # 等待安装完成 # 可选尝试其他参数 if not self._launcher_exists(): subprocess.run([installer_path, "/verysilent", "/norestart"], shell=True) time.sleep(10) if os.path.exists(installer_path): os.remove(installer_path) return self._launcher_exists() except Exception as e: print(f"{Fore.RED}安装异常: {e}{Style.RESET_ALL}") return False def _download_file(self, url, save_path): try: headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"} response = requests.get(url, stream=True, headers=headers, timeout=60) response.raise_for_status() total = int(response.headers.get("content-length", 0)) downloaded = 0 with open(save_path, "wb") as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) downloaded += len(chunk) if total > 0: pct = int(downloaded / total * 100) print(f"\r📥 下载启动器: {pct}% ({downloaded//1024}KB/{total//1024}KB)", end="", flush=True) print() return True except Exception as e: print(f"下载失败: {e}") return False