mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 20:40:43 +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 + 双连接 文档 - 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
211 lines
8.3 KiB
Python
211 lines
8.3 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""首次运行设置窗口。
|
||
|
||
流程:
|
||
装完第一次启动 → 弹一个窗口,让你自己定一个配对码
|
||
(顺便可以勾"以后开机静默运行")
|
||
→ 之后**再也不会有任何窗口**,手表输这个码就能连
|
||
|
||
为什么是"你自己定"而不是"程序里写死":
|
||
写死意味着每台装这软件的被控端都是同一个码,而且会打进手表 APK。
|
||
自己定的话,这个码只存在你这台机器的 data\\settings.json 里。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\windows"
|
||
r"\lanremote")
|
||
UI = ROOT / "ui.py"
|
||
RUN = ROOT.parent / "run_agent.py"
|
||
|
||
# ---------------- ui.py:设置窗口 ----------------
|
||
|
||
ANCHOR = ''' def run(self) -> None:
|
||
from .actions import Actions
|
||
'''
|
||
|
||
NEW = ''' # ------------------------------------------------------------------
|
||
# 首次运行:设置配对码
|
||
# ------------------------------------------------------------------
|
||
|
||
def setup_needed(self) -> bool:
|
||
"""是不是还没设置过配对码。"""
|
||
return not bool(self.store.get("setup_done", False))
|
||
|
||
def open_first_run_setup(self) -> bool:
|
||
"""第一次使用时的设置窗口。返回是否设置成功。
|
||
|
||
这个窗口**只出现一次** —— 设完之后程序再也不弹任何窗口,
|
||
手表用这个码连上就完事了。
|
||
"""
|
||
win = tk.Toplevel(self.root)
|
||
win.title("第一次使用 · 设置配对码")
|
||
win.configure(bg=BG)
|
||
win.resizable(False, False)
|
||
|
||
result = {"ok": False}
|
||
|
||
def refuse_close():
|
||
# 必须设一个码才能继续,否则手表连不上
|
||
self.show_message("请先设置一个配对码") if hasattr(self, "show_message") else None
|
||
|
||
win.protocol("WM_DELETE_WINDOW", refuse_close)
|
||
|
||
header = tk.Frame(win, bg=ACCENT, height=6)
|
||
header.pack(fill="x")
|
||
|
||
tk.Label(win, text="设置你的配对码", bg=BG, fg=FG,
|
||
font=("Microsoft YaHei UI", 15, "bold")).pack(
|
||
anchor="w", padx=18, pady=(16, 4))
|
||
|
||
tk.Label(win,
|
||
text="设一个只有你知道的码,手表上输这个就能连。\\n"
|
||
"设完之后程序就不会再弹任何窗口了。",
|
||
bg=BG, fg=DIM, font=FONT_SMALL, justify="left").pack(
|
||
anchor="w", padx=18, pady=(0, 12))
|
||
|
||
code_row = tk.Frame(win, bg=BG)
|
||
code_row.pack(fill="x", padx=18)
|
||
tk.Label(code_row, text="配对码", bg=BG, fg=FG,
|
||
font=FONT_SMALL).pack(side="left")
|
||
ent = tk.Entry(code_row, bg=CARD, fg=FG, relief="flat",
|
||
font=("Consolas", 16, "bold"), width=12,
|
||
justify="center", highlightthickness=1,
|
||
highlightbackground=BORDER)
|
||
ent.insert(0, self.store.pairing_code() or self.store.new_pairing_code())
|
||
ent.pack(side="left", padx=(10, 0), ipady=6)
|
||
|
||
hint = tk.Label(win, text="6-16 位,数字或字母",
|
||
bg=BG, fg=DIM, font=FONT_SMALL)
|
||
hint.pack(anchor="w", padx=18, pady=(6, 0))
|
||
|
||
var_auto = tk.BooleanVar(value=True)
|
||
tk.Checkbutton(win, text="以后开机自动静默运行(不再显示窗口)",
|
||
variable=var_auto, bg=BG, fg=FG,
|
||
activebackground=BG, selectcolor=CARD,
|
||
font=FONT_SMALL, bd=0, highlightthickness=0).pack(
|
||
anchor="w", padx=14, pady=(12, 0))
|
||
|
||
status = tk.Label(win, text="", bg=BG, fg=DANGER, font=FONT_SMALL)
|
||
status.pack(anchor="w", padx=18, pady=(6, 0))
|
||
|
||
def confirm():
|
||
typed = ent.get().strip()
|
||
try:
|
||
saved = self.store.set_pairing_code(typed)
|
||
except ValueError as exc:
|
||
status.configure(text=str(exc))
|
||
return
|
||
|
||
self.store.set("setup_done", True)
|
||
self.lbl_code.configure(text=saved)
|
||
|
||
note = ""
|
||
if var_auto.get():
|
||
try:
|
||
from .autostart import is_enabled, enable
|
||
if not is_enabled():
|
||
enable()
|
||
note = ";已设为开机静默运行"
|
||
except Exception as exc: # noqa: BLE001
|
||
note = f";开机自启没设上({exc})"
|
||
|
||
self.log(f"配对码已设为 {saved}{note}")
|
||
result["ok"] = True
|
||
win.grab_release()
|
||
win.destroy()
|
||
|
||
def reroll():
|
||
ent.delete(0, "end")
|
||
ent.insert(0, self.store.new_pairing_code())
|
||
|
||
buttons = tk.Frame(win, bg=BG)
|
||
buttons.pack(fill="x", padx=18, pady=(4, 18))
|
||
self._btn(buttons, "确定,开始使用", confirm, width=15)
|
||
self._btn(buttons, "换个随机的", reroll, width=11, last=True)
|
||
|
||
self.center_window(win)
|
||
win.grab_set()
|
||
ent.focus_set()
|
||
win.bind("<Return>", lambda _e: confirm())
|
||
self.root.wait_window(win)
|
||
return result["ok"]
|
||
|
||
def run(self) -> None:
|
||
from .actions import Actions
|
||
|
||
# 第一次使用:先让用户定一个自己的配对码。
|
||
# 这一个窗口是整个程序里唯一一次需要你动手的地方。
|
||
if self.force_setup or self.setup_needed():
|
||
if not self.open_first_run_setup():
|
||
self.log("没有设置配对码,退出")
|
||
return
|
||
'''
|
||
|
||
# AgentUI.__init__ 要接受 force_setup
|
||
INIT_ANCHOR = " def __init__(self, store: Store, start_minimized: bool = False):"
|
||
INIT_NEW = (" def __init__(self, store: Store, start_minimized: bool = False,\n"
|
||
" force_setup: bool = False):")
|
||
|
||
INIT_BODY_ANCHOR = " self.start_minimized = start_minimized"
|
||
INIT_BODY_NEW = (" self.start_minimized = start_minimized\n"
|
||
" self.force_setup = force_setup")
|
||
|
||
# ---------------- run_agent.py:--setup + 静默模式提示 ----------------
|
||
|
||
RUN_OLD = ''' parser.add_argument("--status", action="store_true", help="打印状态后退出")'''
|
||
RUN_NEW = ''' parser.add_argument("--status", action="store_true", help="打印状态后退出")
|
||
parser.add_argument("--setup", action="store_true",
|
||
help="强制打开首次设置窗口(重新设配对码)")'''
|
||
|
||
RUN_UI_OLD = ''' ui = AgentUI(store, start_minimized=args.minimized)'''
|
||
RUN_UI_NEW = ''' ui = AgentUI(store, start_minimized=args.minimized,
|
||
force_setup=args.setup)'''
|
||
|
||
RUN_SILENT_OLD = ''' ui = HeadlessUI(store, log_file=log_file)
|
||
ui.log(f"{APP_NAME} v{__version__} 静默启动")'''
|
||
RUN_SILENT_NEW = ''' ui = HeadlessUI(store, log_file=log_file)
|
||
ui.log(f"{APP_NAME} v{__version__} 静默启动")
|
||
|
||
# 还没设过配对码就静默启动的话,手表没法连(而且用户看不到码)。
|
||
# 记到日志里,并提醒怎么处理。
|
||
if not store.get("setup_done", False):
|
||
ui.log("注意:还没有设置过配对码。请先运行:"
|
||
"LanRemote-Agent.exe --setup")
|
||
ui.log(f"当前临时配对码是 {store.pairing_code()}")'''
|
||
|
||
|
||
def main() -> int:
|
||
ok = True
|
||
for path, old, new, tag in (
|
||
(UI, ANCHOR, NEW, "ui: 首次设置窗口"),
|
||
(UI, INIT_ANCHOR, INIT_NEW, "ui: __init__ 签名"),
|
||
(UI, INIT_BODY_ANCHOR, INIT_BODY_NEW, "ui: force_setup 字段"),
|
||
(RUN, RUN_OLD, RUN_NEW, "run_agent: --setup"),
|
||
(RUN, RUN_UI_OLD, RUN_UI_NEW, "run_agent: 传 force_setup"),
|
||
(RUN, RUN_SILENT_OLD, RUN_SILENT_NEW, "run_agent: 静默模式提示"),
|
||
):
|
||
text = path.read_text(encoding="utf-8")
|
||
if old not in text:
|
||
print(f" [跳过] {tag} —— 锚点没找到")
|
||
ok = False
|
||
continue
|
||
path.write_text(text.replace(old, new, 1), encoding="utf-8")
|
||
print(f" {tag}: OK")
|
||
|
||
import ast
|
||
for label, path in (("ui.py", UI), ("run_agent.py", RUN)):
|
||
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())
|