# -*- coding: utf-8 -*- r"""中转站改造成「官网 + 管理页分家」(修正版)。 上一版脚本自己踩了 f-string 花括号没转义,在写文件前就崩了 —— 所以 relay.py 没被改动。这版全部改成普通字符串拼接。 用户要求: relay.xxmxxs.top/ -> 官网(简洁介绍 + 下载) relay.xxmxxs.top/zhingzhuanzhan -> 中转站管理(要登录) 管理账号 xmz7891 密码 @REVAedu120830 """ from __future__ import annotations import ast import sys from pathlib import Path RELAY = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\relay" r"\relay.py") ADMIN_PATH = "/zhingzhuanzhan" ADMIN_USER = "xmz7891" ADMIN_PASS = "@REVAedu120830" def site_page_source() -> str: """生成 _site_page() 的源码。用拼接,避免 f-string 花括号地狱。""" head = '''def _site_page() -> str: """官网首页:简洁介绍 + 下载。**不需要登录**。 用户要求把 relay.xxmxxs.top 当官网用, 管理后台挪到 ADMIN_PATH(见 _login_page / _admin_page)。 """ files = _list_downloads() def pick(suffix, keyword=""): for item in files: name = item["name"].lower() if name.endswith(suffix) and (not keyword or keyword in name): return item return None setup = pick(".exe") server = pick(".zip", "server") watch = pick(".apk") def card(title, desc, item, tag): if not item: return ('
' + title + '
' '
' + desc + '
' '
暂未上传
') mb = item["size"] / 1024 / 1024 size = ("%.1f MB" % mb) if mb >= 0.1 else ("%.0f KB" % (item["size"] / 1024)) href = "/download/" + quote(item["name"]) return ('
' + title + '
' '
' + desc + '
' '下载 ' + tag + '' '
' + item["name"] + ' · ' + size + '
') ver = "" for item in files: found = re.search(r"(\\d+\\.\\d+\\.\\d+)", item["name"]) if found: ver = found.group(1) break cards = (card("电脑端", "教室那台 Windows 电脑装这个", setup, "安装包") + card("服务器端", "要跨网络才需要,装在一台小机器上", server, "压缩包") + card("手表端", "安卓手表装这个 APK", watch, "APK")) badge = ("最新版 " + ver) if ver else "" return """ ykxmz · 教室电脑手表遥控

ykxmz

老师抬一下手腕,就能管教室里那台电脑。
""" + badge + """

放课件、放音频、投图到大屏、看看谁在打游戏、下课关机 —— 不用走回讲台去点鼠标。

""" + cards + """
源码在 Gitee · 历史版本在 发行版 · 管理入口
""" ''' return head def main() -> int: text = RELAY.read_text(encoding="utf-8") if "_site_page" in text: print(" 已经改造过") return 0 ok = True # ---- 1. 补导入 ---- if "\nimport re" not in text: text = text.replace("import os\n", "import os\nimport re\n", 1) print(" 补 import re") if "from urllib.parse import quote" not in text: text = text.replace("import urllib.parse\n", "import urllib.parse\n" "from urllib.parse import quote\n", 1) print(" 补 from urllib.parse import quote") # ---- 2. 密码 + 账号 ---- old_pw = 'ADMIN_PASSWORD_DEFAULT = "120830"' new_pw = ('ADMIN_PASSWORD_DEFAULT = "' + ADMIN_PASS + '"\n' '# 管理页账号(原来只有密码,用户要求加上账号)\n' 'ADMIN_USER_DEFAULT = "' + ADMIN_USER + '"\n' 'ADMIN_USER = (os.environ.get("RELAY_ADMIN_USER") or\n' ' ADMIN_USER_DEFAULT)') if old_pw in text: text = text.replace(old_pw, new_pw, 1) print(" 默认管理密码 -> " + ADMIN_PASS + ",账号 " + ADMIN_USER) else: print(" [提示] 默认密码锚点没找到") # ---- 3. admin_login 加账号参数 ---- if "def admin_login(password: str) -> str:" in text: text = text.replace("def admin_login(password: str) -> str:", "def admin_login(username: str, password: str) -> str:", 1) print(" admin_login 签名加了账号") old_body = (' if not password or not secrets.compare_digest(password, admin_password()):\n' ' return ""') new_body = (' # 账号也要对(用户要求用账号+密码登录)\n' ' if username and username.strip() != ADMIN_USER:\n' ' return ""\n' ' if not password or not secrets.compare_digest(password, admin_password()):\n' ' return ""') if old_body in text: text = text.replace(old_body, new_body, 1) print(" admin_login 加密码校验") else: print(" [提示] admin_login 函数体锚点没找到") # ---- 4. 路由 ---- old_route = (' if path in ("/", "/admin"):\n' ' # 管理页要登录 —— 上面会显示配对码,不能谁都能看\n' ' if not self._admin_gate():\n' ' self._send(200, _login_page(\n' ' "密码不对,再试一次" if _query(self.path, "bad") else ""\n' ' ), "text/html; charset=utf-8")\n' ' return\n' ' self._admin_page()\n' ' return') new_route = (' # ---- 官网首页(公开,不用登录)----\n' ' if path == "/":\n' ' self._send(200, _site_page(), "text/html; charset=utf-8")\n' ' return\n\n' ' # ---- 管理后台 ----\n' ' # 挪到 ' + ADMIN_PATH + '(用户要求)。\n' ' # /admin 保留成跳转,免得存过书签的人打不开。\n' ' if path == "/admin":\n' ' self._redirect("' + ADMIN_PATH + '")\n' ' return\n\n' ' if path == "' + ADMIN_PATH + '":\n' ' # 管理页要登录 —— 上面会显示配对码,不能谁都能看\n' ' if not self._admin_gate():\n' ' self._send(200, _login_page(\n' ' "账号或密码不对,再试一次"\n' ' if _query(self.path, "bad") else ""\n' ' ), "text/html; charset=utf-8")\n' ' return\n' ' self._admin_page()\n' ' return') if old_route in text: text = text.replace(old_route, new_route, 1) print(" 路由:/ 官网," + ADMIN_PATH + " 管理页") else: print(" [失败] 路由锚点没找到") ok = False # ---- 5. 登录接口 ---- old_login = (' if path == "/admin/login":\n' ' form = self._body().decode("utf-8", "replace")\n' ' password = ""\n' ' for piece in form.split("&"):\n' ' name, _, value = piece.partition("=")\n' ' if name == "password":\n' ' from urllib.parse import unquote_plus\n' ' password = unquote_plus(value)\n' ' token = admin_login(password)\n' ' if not token:\n' ' log(f"管理页登录失败,来自 {self._client_ip()}")\n' ' self._redirect("/?bad=1")\n' ' return\n' ' log(f"管理页登录成功,来自 {self._client_ip()}")\n' ' self.send_response(302)\n' ' self.send_header("Location", "/")') new_login = (' if path == "/admin/login":\n' ' form = self._body().decode("utf-8", "replace")\n' ' username = ""\n' ' password = ""\n' ' from urllib.parse import unquote_plus\n' ' for piece in form.split("&"):\n' ' name, _, value = piece.partition("=")\n' ' if name == "password":\n' ' password = unquote_plus(value)\n' ' elif name == "username":\n' ' username = unquote_plus(value)\n' ' token = admin_login(username, password)\n' ' if not token:\n' ' log("管理页登录失败(%s),来自 %s"\n' ' % (username or "未填账号", self._client_ip()))\n' ' self._redirect("' + ADMIN_PATH + '?bad=1")\n' ' return\n' ' log("管理页登录成功(%s),来自 %s"\n' ' % (username, self._client_ip()))\n' ' self.send_response(302)\n' ' self.send_header("Location", "' + ADMIN_PATH + '")') if old_login in text: text = text.replace(old_login, new_login, 1) print(" 登录接口:接受账号 + 密码") else: print(" [失败] 登录接口锚点没找到") ok = False # ---- 6. 登录表单加账号框 ---- old_form = '
' if old_form in text: text = text.replace( old_form, old_form + '', 1) print(" 登录表单加了账号框") # ---- 7. 插入官网函数 ---- anchor = "def _login_page(" if anchor in text: text = text.replace(anchor, site_page_source() + anchor, 1) print(" 插入 _site_page()") else: print(" [失败] 找不到 _login_page") ok = False RELAY.write_text(text, encoding="utf-8", newline="\n") try: ast.parse(text) print(" relay.py 语法 OK") except SyntaxError as exc: print(" [失败] 语法错误: 行 %s: %s" % (exc.lineno, exc.msg)) lines = text.splitlines() for i in range(max(0, (exc.lineno or 1) - 3), min(len(lines), (exc.lineno or 1) + 2)): print(" %d: %s" % (i + 1, lines[i][:90])) return 1 return 0 if ok else 1 if __name__ == "__main__": sys.exit(main())