mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 23:00:44 +00:00
被控端 - 修复 MTU 问题:夹 MSS + 路径 MTU 探测(公网可用率 48% -> 100%) - 复用 HTTP 连接(免掉每次新建 TLS 的 30% 握手失败) - 每分钟回头找局域网,自动切回快 400 倍的路径 - 画面心跳帧:静止时省流量,客户端仍知道流是活的 - 锁屏时给出可操作的提示 手表端 - 内置 GTS Root R4 / GlobalSign Root CA,修 SSLHandshakeException - 连接错误翻译成人话(证书/时间/解析/超时分别提示) - 经中转连上后用服务器报的地址刷新已配对记录 - 新增局域网连接页面、服务器延迟检测 服务器端 - 支持 chunked 请求体(修每 16 秒一次的连接错乱与大面积 502) - 网络调优脚本 net-tune.sh(开机自动应用) - 管理页:批量删除、网络体检、下载区 - 隧道改 HTTP/2 + 双连接 文档 - 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
208 lines
7.7 KiB
Python
208 lines
7.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""两件事:
|
|
|
|
【1】修「弹通知」在静默模式下不显示
|
|
HeadlessUI.notify 之前只写日志,什么都不弹,所以手表点「弹通知」
|
|
电脑上一点反应都没有。
|
|
静默模式的意思是"开机不弹控制窗口",不代表手表**明确要求显示**的
|
|
东西也不显示 —— 投图、全屏大字、通知都属于这一类。
|
|
|
|
【2】把网络自检 / 修防火墙做进 EXE
|
|
原来的 网络自检.bat 会去找 python,没装 Python 的电脑用不了。
|
|
现在改成调用 LanRemote-Agent.exe --netcheck。
|
|
因为是 --windowed 程序没有控制台,所以要先 AllocConsole 自己开一个。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\windows")
|
|
HEADLESS = ROOT / "lanremote" / "headless.py"
|
|
RUN = ROOT / "run_agent.py"
|
|
|
|
# ---------------- 1. notify 真的弹窗 ----------------
|
|
|
|
NOTIFY_OLD = ''' def notify(self, title: str, text: str) -> None:
|
|
"""静默模式下不弹气泡,只记日志。
|
|
|
|
真正的"提醒"由功能自己用 actions.notify 决定要不要显示窗口。
|
|
"""
|
|
self.log(f"[通知] {title}: {text}")'''
|
|
|
|
NOTIFY_NEW = ''' def notify(self, title: str, text: str) -> None:
|
|
"""弹一个小通知窗(屏幕右下角,几秒后自动消失)。
|
|
|
|
之前这里只写日志,所以手表点「弹通知」电脑上毫无反应。
|
|
静默模式的意思是"开机不弹控制窗口",而不是
|
|
"手表明确要求显示的东西也不显示" —— 投图、全屏大字、通知
|
|
都属于"明确要求",照常显示。
|
|
"""
|
|
self.log(f"[通知] {title}: {text}")
|
|
root = self._ensure_root()
|
|
if root is None:
|
|
return
|
|
|
|
def build():
|
|
try:
|
|
win = tk.Toplevel(root)
|
|
win.title(f"通知 - {title}")
|
|
win.overrideredirect(True)
|
|
win.attributes("-topmost", True)
|
|
win.configure(bg="#ffffff")
|
|
|
|
box = tk.Frame(win, bg="#ffffff", highlightthickness=1,
|
|
highlightbackground="#d0d7de")
|
|
box.pack(fill="both", expand=True)
|
|
tk.Frame(box, bg="#185ce8", height=4).pack(fill="x")
|
|
tk.Label(box, text=title or "通知", bg="#ffffff",
|
|
fg="#1f2328", font=("Microsoft YaHei UI", 11, "bold"),
|
|
anchor="w").pack(fill="x", padx=14, pady=(10, 2))
|
|
tk.Label(box, text=text or "", bg="#ffffff", fg="#656d76",
|
|
font=("Microsoft YaHei UI", 10), anchor="w",
|
|
justify="left", wraplength=260).pack(
|
|
fill="x", padx=14, pady=(0, 12))
|
|
win.update_idletasks()
|
|
|
|
screen_w, screen_h = self.screen_size()
|
|
width = max(240, win.winfo_reqwidth())
|
|
height = win.winfo_reqheight()
|
|
win.geometry(f"+{screen_w - width - 24}+{screen_h - height - 72}")
|
|
|
|
def close(_event=None):
|
|
try:
|
|
win.destroy()
|
|
except Exception: # noqa: BLE001
|
|
pass
|
|
|
|
win.bind("<Button-1>", close)
|
|
win.after(6000, close)
|
|
except Exception as exc: # noqa: BLE001
|
|
self.log(f"通知显示失败: {exc}")
|
|
|
|
try:
|
|
self._queue.put(build)
|
|
except Exception: # noqa: BLE001
|
|
pass'''
|
|
|
|
# ---------------- 2. run_agent 加 --netcheck / --fix-firewall ----------------
|
|
|
|
ARGS_OLD = ''' parser.add_argument("--setup", action="store_true",
|
|
help="重新打开设置窗口")'''
|
|
ARGS_NEW = ''' parser.add_argument("--setup", action="store_true",
|
|
help="重新打开设置窗口")
|
|
parser.add_argument("--netcheck", nargs="?", type=int, const=90,
|
|
default=None, metavar="秒",
|
|
help="网络自检(自开控制台,不需要装 Python)")
|
|
parser.add_argument("--fix-firewall", action="store_true",
|
|
help="提权修复防火墙")'''
|
|
|
|
MAIN_OLD = ''' if args.autostart:
|
|
return cli_autostart(args.autostart)
|
|
if args.status:
|
|
return cli_status()'''
|
|
MAIN_NEW = ''' if args.autostart:
|
|
return cli_autostart(args.autostart)
|
|
if args.status:
|
|
return cli_status()
|
|
|
|
# 这两个是给 .bat 调的:EXE 自带功能,不需要系统装 Python
|
|
if args.netcheck is not None:
|
|
return cli_netcheck(args.netcheck)
|
|
if args.fix_firewall:
|
|
return cli_fix_firewall()'''
|
|
|
|
CLI_ANCHOR = '''def cli_status() -> int:'''
|
|
|
|
CLI_NEW = '''def attach_console() -> None:
|
|
"""给 --windowed 程序自己开一个控制台窗口。
|
|
|
|
打包成 --windowed 后进程没有控制台,直接 print 什么都看不到。
|
|
AllocConsole 可以临时开一个,并把 stdout/stderr 接过去。
|
|
"""
|
|
if os.name != "nt":
|
|
return
|
|
try:
|
|
import ctypes
|
|
ctypes.windll.kernel32.AllocConsole()
|
|
sys.stdout = open("CONOUT$", "w", encoding="utf-8", buffering=1)
|
|
sys.stderr = open("CONOUT$", "w", encoding="utf-8", buffering=1)
|
|
try:
|
|
sys.stdin = open("CONIN$", "r", encoding="utf-8")
|
|
except OSError:
|
|
pass
|
|
except Exception: # noqa: BLE001
|
|
pass
|
|
|
|
|
|
def wait_key() -> None:
|
|
try:
|
|
print()
|
|
input("按回车键关闭这个窗口…")
|
|
except Exception: # noqa: BLE001
|
|
pass
|
|
|
|
|
|
def cli_netcheck(seconds: int) -> int:
|
|
"""网络自检:监听端口,看手表的包到底有没有到这台电脑。"""
|
|
attach_console()
|
|
try:
|
|
from lanremote import netcheck
|
|
return netcheck.run_check(int(seconds or 90))
|
|
except Exception as exc: # noqa: BLE001
|
|
print(f"自检运行失败: {exc}")
|
|
return 1
|
|
finally:
|
|
wait_key()
|
|
|
|
|
|
def cli_fix_firewall() -> int:
|
|
"""提权修复防火墙(会弹一次 UAC,然后黑终端一闪)。"""
|
|
store = Store(data_dir())
|
|
ok, detail = fix_firewall_with_flash(store)
|
|
attach_console()
|
|
print(("已修复:" if ok else "未完成:") + str(detail))
|
|
wait_key()
|
|
return 0 if ok else 1
|
|
|
|
|
|
def cli_status() -> int:'''
|
|
|
|
|
|
def main() -> int:
|
|
# 1
|
|
text = HEADLESS.read_text(encoding="utf-8")
|
|
if NOTIFY_OLD not in text:
|
|
print(" [失败] headless notify 锚点没找到")
|
|
return 1
|
|
HEADLESS.write_text(text.replace(NOTIFY_OLD, NOTIFY_NEW, 1), encoding="utf-8")
|
|
print(" headless.notify: 已改成真的弹通知窗")
|
|
|
|
# 2
|
|
text = RUN.read_text(encoding="utf-8")
|
|
for old, new, tag in ((ARGS_OLD, ARGS_NEW, "--netcheck/--fix-firewall 参数"),
|
|
(MAIN_OLD, MAIN_NEW, "main 分发"),
|
|
(CLI_ANCHOR, CLI_NEW, "cli_netcheck/cli_fix_firewall")):
|
|
if old not in text:
|
|
print(f" [跳过] {tag} —— 锚点没找到")
|
|
continue
|
|
text = text.replace(old, new, 1)
|
|
print(f" {tag}: OK")
|
|
RUN.write_text(text, encoding="utf-8")
|
|
|
|
import ast
|
|
ok = True
|
|
for label, path in (("headless.py", HEADLESS), ("run_agent.py", RUN),
|
|
("netcheck.py", ROOT / "lanremote" / "netcheck.py")):
|
|
try:
|
|
ast.parse(path.read_text(encoding="utf-8"))
|
|
print(f" {label}: 语法 OK")
|
|
except SyntaxError as exc:
|
|
print(f" {label}: 语法错误 {exc}")
|
|
ok = False
|
|
return 0 if ok else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|