# -*- coding: utf-8 -*-
r"""中转站改造成「官网 + 管理页分家」。
用户要求:
relay.xxmxxs.top/ -> 官网(简洁介绍 + 下载)
relay.xxmxxs.top/zhingzhuanzhan -> 中转站管理(要登录)
管理账号 xmz7891 密码 @REVAedu120830
改动点:
1. 默认管理密码改掉,并加"账号"这个维度(原来只有密码)
2. admin_login(username, password)
3. GET / -> 官网(公开,不用登录)
4. GET /zhingzhuanzhan -> 管理页(要登录)
/admin 保留成 302 跳过去,免得老书签失效
5. 登录表单加账号输入框
6. 登录后的跳转、退出链接都指到 /zhingzhuanzhan
"""
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"
# 官网首页(公开)。做得简洁:一句话说清是什么、三个下载按钮。
SITE_PAGE = '''def _site_page() -> str:
"""官网首页:简洁介绍 + 下载。**不需要登录**。
用户要求把 relay.xxmxxs.top 当官网用,
管理后台挪到 /zhingzhuanzhan(见 _login_page / _admin_page)。
"""
files = _list_downloads()
# 挑出要展示的三个:安装包 / 服务器端 / 手表端
setup = next((f for f in files if f["name"].endswith(".exe")), None)
server = next((f for f in files
if f["name"].endswith(".zip") and "server" in f["name"]), None)
watch = next((f for f in files if f["name"].endswith(".apk")), None)
def card(title, desc, item, tag):
if not item:
return (f'
{title}
'
f'
{desc}
'
f'
暂未上传
')
mb = item["size"] / 1024 / 1024
size = f"{mb:.1f} MB" if mb >= 0.1 else f"{item['size'] / 1024:.0f} KB"
href = "/download/" + quote(item["name"])
return (f'{title}
'
f'
{desc}
'
f'
下载 {tag}'
f'
{item["name"]} · {size}
')
ver = ""
for f in files:
m = re.search(r"(\\d+\\.\\d+\\.\\d+)", f["name"])
if m:
ver = m.group(1)
break
return f"""
ykxmz · 教室电脑手表遥控
ykxmz
老师抬一下手腕,就能管教室里那台电脑。
{("最新版 " + ver) if ver else ""}
放课件、放音频、投图到大屏、看看谁在打游戏、下课关机 ——
不用走回讲台去点鼠标。
- 手表和电脑在同一个 WiFi:直连,几十毫秒
- 不在同一个网络:自动走中转,办公室也能管教室
- 屏幕被看时电脑上一定有提示条,关不掉
{card("电脑端", "教室那台 Windows 电脑装这个", setup, "安装包")}
{card("服务器端", "要跨网络才需要,装在一台小机器上", server, "压缩包")}
{card("手表端", "安卓手表装这个 APK", watch, "APK")}
"""
'''
def main() -> int:
text = RELAY.read_text(encoding="utf-8")
ok = True
if "_site_page" in text:
print(" 已经改造过")
return 0
# ---- 1. 导入 quote / re ----
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\nfrom urllib.parse import quote\n", 1)
print(" 补 from urllib.parse import quote")
# ---- 2. 密码 / 账号 ----
text = text.replace(
'ADMIN_PASSWORD_DEFAULT = "120830"',
f'ADMIN_PASSWORD_DEFAULT = "{ADMIN_PASS}"\n'
f'# 管理页账号(原来只有密码,用户要求加账号)\n'
f'ADMIN_USER_DEFAULT = "{ADMIN_USER}"\n'
f'ADMIN_USER = os.environ.get("RELAY_ADMIN_USER", "") or ADMIN_USER_DEFAULT',
1)
text = text.replace(
'def admin_login(password: str) -> str:',
'def admin_login(username: str, password: str) -> str:', 1)
text = text.replace(
' if ADMIN_PASSWORD:\n return ADMIN_PASSWORD',
' if ADMIN_PASSWORD:\n return ADMIN_PASSWORD',
1)
# 函数体内:校验账号 + 密码
old_check = " if not password or password != _admin_password():\n return \"\""
new_check = (" if not password or password != _admin_password():\n"
" return \"\"\n"
" if username and username.strip() != ADMIN_USER:\n"
" return \"\"")
if old_check in text:
text = text.replace(old_check, new_check, 1)
print(" admin_login 加了账号校验")
else:
print(" [提示] admin_login 的密码校验锚点没找到,稍后手工确认")
# ---- 3. 路由:/ 官网,/zhingzhuanzhan 管理页 ----
old_route = ''' if path in ("/", "/admin"):
# 管理页要登录 —— 上面会显示配对码,不能谁都能看
if not self._admin_gate():
self._send(200, _login_page(
"密码不对,再试一次" if _query(self.path, "bad") else ""
), "text/html; charset=utf-8")
return
self._admin_page()
return'''
new_route = f''' # ---- 官网首页(公开,不用登录)----
if path == "/":
self._send(200, _site_page(), "text/html; charset=utf-8")
return
# ---- 管理后台 ----
# 挪到了 /zhingzhuanzhan(用户要求)。/admin 保留成跳转,
# 免得存过书签的人打不开。
if path == "/admin":
self._redirect("{ADMIN_PATH}")
return
if path == "{ADMIN_PATH}":
# 管理页要登录 —— 上面会显示配对码,不能谁都能看
if not self._admin_gate():
self._send(200, _login_page(
"账号或密码不对,再试一次"
if _query(self.path, "bad") else ""
), "text/html; charset=utf-8")
return
self._admin_page()
return'''
if old_route in text:
text = text.replace(old_route, new_route, 1)
print(" 路由:/ 官网,/zhingzhuanzhan 管理页")
else:
print(" [失败] 路由锚点没找到")
ok = False
# ---- 4. 登录 POST:读账号 + 密码 ----
old_login = ''' if path == "/admin/login":
form = self._body().decode("utf-8", "replace")
password = ""
for piece in form.split("&"):
name, _, value = piece.partition("=")
if name == "password":
from urllib.parse import unquote_plus
password = unquote_plus(value)
token = admin_login(password)
if not token:
log(f"管理页登录失败,来自 {self._client_ip()}")
self._redirect("/?bad=1")
return
log(f"管理页登录成功,来自 {self._client_ip()}")
self.send_response(302)
self.send_header("Location", "/")'''
new_login = f''' if path == "/admin/login":
form = self._body().decode("utf-8", "replace")
username = password = ""
for piece in form.split("&"):
name, _, value = piece.partition("=")
if name == "password":
from urllib.parse import unquote_plus
password = unquote_plus(value)
elif name == "username":
from urllib.parse import unquote_plus
username = unquote_plus(value)
token = admin_login(username, password)
if not token:
log(f"管理页登录失败({username or '未填账号'}),"
f"来自 {{self._client_ip()}}")
self._redirect("{ADMIN_PATH}?bad=1")
return
log(f"管理页登录成功({{username}}),来自 {{self._client_ip()}}")
self.send_response(302)
self.send_header("Location", "{ADMIN_PATH}")'''
if old_login in text:
text = text.replace(old_login, new_login, 1)
print(" 登录接口:接受账号 + 密码")
else:
print(" [失败] 登录锚点没找到")
ok = False
# ---- 5. 登录表单加账号框 ----
old_form = '