# -*- coding: utf-8 -*- r"""修两个问题: 1. 「设备已关闭新设备连接」—— 手表重装后永远连不上 现在 _do_pair 第一句就是 if not self.pairing_enabled: 拒绝。 而 run_silent 里有"首台设备配对成功后自动关闭配对"的逻辑 (close_pair_after_first)。于是: 手表重装 / 换新表 / 清了 App 数据 -> 令牌没了 -> 重新配对 -> 被拒 用户只能去管理页手动开——但管理页那个开关是给"临时加设备"用的, 正常用户根本不该被迫走这条路。 改法:**配对码本身就是密钥**。拿着正确的 6 位码就允许配对, 不管配对窗口开没开。码不对才回"已关闭配对"(这样也保住了 防暴力枚举的门槛,见下面的限速)。 2. 应用名改成 ykxmz Windows 上显示的是 "ykxmz 教室电脑手表遥控", 用户要求直接叫 ykxmz(教室里那个名字放副标题就行)。 """ from __future__ import annotations import ast import sys from pathlib import Path ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") SERVER = ROOT / "windows" / "lanremote" / "server.py" # ---------- 1. 配对:知道码就放行 ---------- OLD_PAIR = ''' def _do_pair(self, session: Session, msg: dict) -> dict: if not self.pairing_enabled: return {"ok": False, "error": "被控端已关闭新设备配对"} code = str(msg.get("code") or "").strip() expected = self.store.pairing_code() if not expected: return {"ok": False, "error": "被控端尚未生成配对码"}''' NEW_PAIR = ''' def _do_pair(self, session: Session, msg: dict) -> dict: code = str(msg.get("code") or "").strip() expected = self.store.pairing_code() if not expected: return {"ok": False, "error": "被控端尚未生成配对码"} # 配对窗口关着、但对方报的码是对的 —— 照样放行。 # # 为什么:配对码本身就是密钥。老逻辑是"首台设备配对成功后 # 自动关闭配对窗口"(close_pair_after_first),结果手表重装、 # 换新表、或清掉 App 数据之后令牌没了,重新配对会被拒, # 用户看到"被控端已关闭新设备配对"就彻底连不上了 —— # 而这时候他能做的只有跑去管理页手动开窗口,完全不合理。 # # 码不对时才用"已关闭配对"这个说法挡回去, # 防暴力枚举的按 IP 限速(下面那段)仍然生效。 if not self.pairing_enabled and code != expected: return {"ok": False, "error": "被控端已关闭新设备配对" + "(配对码不对;要在管理页临时开启的话," "打开中转站管理页找「允许新设备配对」)"}''' # ---------- 2. 应用名 ---------- NAME_OLD = 'APP_NAME = "ykxmz 教室电脑手表遥控"' NAME_NEW = 'APP_NAME = "ykxmz"' def main() -> int: ok = True text = SERVER.read_text(encoding="utf-8") if "配对码本身就是密钥" in text: print(" server.py: 配对逻辑已经改过") elif OLD_PAIR in text: text = text.replace(OLD_PAIR, NEW_PAIR, 1) SERVER.write_text(text, encoding="utf-8", newline="\n") print(" server.py: 拿着正确配对码就放行") else: print(" [失败] server.py 的 _do_pair 锚点没找到") ok = False # 应用名 for rel in ("windows/lanremote/__init__.py",): path = ROOT / rel if not path.is_file(): continue t = path.read_text(encoding="utf-8") if NAME_OLD in t: path.write_text(t.replace(NAME_OLD, NAME_NEW), encoding="utf-8", newline="\n") print(f" {path.name}: 应用名 -> ykxmz") # 全局找一遍还叫旧名的 for path in (ROOT / "windows").rglob("*.py"): t = path.read_text(encoding="utf-8") if 'APP_NAME = "ykxmz 教室电脑手表遥控"' in t: path.write_text(t.replace('APP_NAME = "ykxmz 教室电脑手表遥控"', 'APP_NAME = "ykxmz"'), encoding="utf-8", newline="\n") print(f" {path.relative_to(ROOT)}: 应用名 -> ykxmz") for path, label in ((SERVER, "server.py"), (ROOT / "windows" / "lanremote" / "__init__.py", "__init__.py")): try: ast.parse(path.read_text(encoding="utf-8")) print(f" {label} 语法 OK") except SyntaxError as exc: print(f" [失败] {label} 语法错误: 行 {exc.lineno}: {exc.msg}") ok = False return 0 if ok else 1 if __name__ == "__main__": sys.exit(main())