"""Chromium/Edge 检测与 Playwright:仅打开浏览器(不写库、不做登录态 DOM 检测)。""" import json import os import subprocess import sys import tempfile from db.accounts_repo import get_account_by_id from util.logging_config import ( get_skill_logger, subprocess_env_with_trace, ) from util.platforms import PLATFORM_URLS # 子进程入口脚本与本模块同目录(独立解释器执行,非 import) _SERVICE_DIR = os.path.dirname(os.path.abspath(__file__)) # PyArmor 在模块首行注入对 pyarmor_runtime_* 的 import;若以「脚本路径」启动子进程, # sys.path[0] 仅为 service/,找不到 scripts/ 下的运行时包。必须用 -m 且 cwd=scripts/(标准做法)。 _SCRIPTS_ROOT = os.path.dirname(_SERVICE_DIR) def _win_find_exe(candidates): for p in candidates: if p and os.path.isfile(p): return p return None def resolve_chromium_channel(): """ Playwright channel: 'chrome' | 'msedge' | None Windows 优先 Chrome,其次 Edge;其它系统默认 chrome(由 Playwright 解析 PATH)。 """ if sys.platform != "win32": return "chrome" pf = os.environ.get("ProgramFiles", r"C:\Program Files") pfx86 = os.environ.get("ProgramFiles(x86)", r"C:\Program Files (x86)") local = os.environ.get("LocalAppData", "") chrome = _win_find_exe( [ os.path.join(pf, "Google", "Chrome", "Application", "chrome.exe"), os.path.join(pfx86, "Google", "Chrome", "Application", "chrome.exe"), os.path.join(local, "Google", "Chrome", "Application", "chrome.exe") if local else "", ] ) if chrome: return "chrome" edge = _win_find_exe( [ os.path.join(pfx86, "Microsoft", "Edge", "Application", "msedge.exe"), os.path.join(pf, "Microsoft", "Edge", "Application", "msedge.exe"), os.path.join(local, "Microsoft", "Edge", "Application", "msedge.exe") if local else "", ] ) if edge: return "msedge" return None def _print_browser_install_hint(): print("❌ 未检测到 Google Chrome 或 Microsoft Edge,请先安装:") print(" • Chrome: https://www.google.com/chrome/") print(" • Edge: https://www.microsoft.com/zh-cn/edge") def cmd_open(account_id): """打开该账号的持久化浏览器,仅用于肉眼核对;不写数据库、不判定是否已登录。""" get_skill_logger().info("open account_id=%r", account_id) target = get_account_by_id(account_id) if not target: get_skill_logger().warning("open_not_found account_id=%r", account_id) print("ERROR:ACCOUNT_NOT_FOUND") return channel = resolve_chromium_channel() if not channel: _print_browser_install_hint() return try: import playwright # noqa: F401 except ImportError: print( "ERROR:需要 playwright Python 包:请在匠厂共享环境中已含 playwright;" "本机需安装 Google Chrome 或 Microsoft Edge(channel 模式,无需 playwright install chromium)" ) return profile_dir = (target.get("profile_dir") or "").strip() if not profile_dir: print("ERROR:PROFILE_DIR_MISSING 库中 profile_dir 为空。") return os.makedirs(profile_dir, exist_ok=True) url = (target.get("url") or "").strip() or PLATFORM_URLS.get( target["platform"], "https://www.google.com" ) browser_name = "Google Chrome" if channel == "chrome" else "Microsoft Edge" print(f"正在打开 [{target['name']}] 的 {browser_name}(仅查看,不写入数据库)") print(f"地址:{url}") print("是否已登录由业务侧(如大模型网页引擎)在使用账号时自行处理;本命令不做登录检测。") cfg = {"channel": channel, "profile_dir": profile_dir, "url": url} with tempfile.NamedTemporaryFile( mode="w", suffix=".json", delete=False, encoding="utf-8" ) as jf: json.dump(cfg, jf, ensure_ascii=False) cfg_path = jf.name try: subprocess.run( [sys.executable, "-m", "service.open_child_runner", cfg_path], cwd=_SCRIPTS_ROOT, env=subprocess_env_with_trace(), ) finally: try: os.unlink(cfg_path) except OSError: pass