ykxmz 1.5.0锛氫慨澶嶆墜琛ㄧ TLS 璇佷功鏍¢獙 + MTU 淇缃戠粶绋冲畾鎬?

琚帶绔?- 淇 MTU 闂锛氬す MSS + 璺緞 MTU 鎺㈡祴锛堝叕缃戝彲鐢ㄧ巼 48% -> 100%锛?- 澶嶇敤 HTTP 杩炴帴锛堝厤鎺夋瘡娆℃柊寤?TLS 鐨?30% 鎻℃墜澶辫触锛?- 姣忓垎閽熷洖澶存壘灞€鍩熺綉锛岃嚜鍔ㄥ垏鍥炲揩 400 鍊嶇殑璺緞
- 鐢婚潰蹇冭烦甯э細闈欐鏃剁渷娴侀噺锛屽鎴风浠嶇煡閬撴祦鏄椿鐨?- 閿佸睆鏃剁粰鍑哄彲鎿嶄綔鐨勬彁绀?
鎵嬭〃绔?- 鍐呯疆 GTS Root R4 / GlobalSign Root CA锛屼慨 SSLHandshakeException
- 杩炴帴閿欒缈昏瘧鎴愪汉璇濓紙璇佷功/鏃堕棿/瑙f瀽/瓒呮椂鍒嗗埆鎻愮ず锛?- 缁忎腑杞繛涓婂悗鐢ㄦ湇鍔″櫒鎶ョ殑鍦板潃鍒锋柊宸查厤瀵硅褰?- 鏂板灞€鍩熺綉杩炴帴椤甸潰銆佹湇鍔″櫒寤惰繜妫€娴?
鏈嶅姟鍣ㄧ
- 鏀寔 chunked 璇锋眰浣擄紙淇瘡 16 绉掍竴娆$殑杩炴帴閿欎贡涓庡ぇ闈㈢Н 502锛?- 缃戠粶璋冧紭鑴氭湰 net-tune.sh锛堝紑鏈鸿嚜鍔ㄥ簲鐢級
- 绠$悊椤碉細鎵归噺鍒犻櫎銆佺綉缁滀綋妫€銆佷笅杞藉尯
- 闅ч亾鏀?HTTP/2 + 鍙岃繛鎺?
鏂囨。
- 璁稿彲鍗忚 / 瀹夎鍓嶅繀璇?/ 瀹夎鍚庨』鐭ワ紙浣滆€咃細灏忛害瀛愶級
This commit is contained in:
xmz7891
2026-10-06 19:01:05 +08:00
commit b705216e4a
3195 changed files with 203292 additions and 0 deletions
+697
View File
@@ -0,0 +1,697 @@
# -*- coding: utf-8 -*-
"""再加 39 个功能(总数到 78)。
重点:
教学类(全屏大字 / 倒计时 / 随机点名 / 白板 / 投影设置)—— 老师的刚需
系统类(睡眠/休眠/注销/显示桌面/任务视图/重启显卡/时钟秒数/隐藏文件)
网络类(WiFi 密码 / 公网 IP / ping / 局域网设备 / 网卡列表)
文件类(复制/移动/压缩/解压/详情/回收站/文件夹大小/按类型统计)
工具类(随机密码 / 秒表 / 世界时钟 / 硬件信息 / 启动项 / 计划任务)
媒体类(定时停止 / 音量淡出 / 显卡信息)
"""
from __future__ import annotations
import sys
from pathlib import Path
FEATURES = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\windows"
r"\lanremote\features.py")
# ---------------------------------------------------------------- defs 追加
DEFS_OLD = ''' # ---- 文件(限定自己的目录)----'''
DEFS_NEW = ''' # ---- 教学(老师的刚需)----
add("big_text", "全屏大字", "input", "教学",
hint="要显示的文字", key="text")
add("big_text_clear", "关掉全屏大字", "action", "教学")
add("countdown_screen", "全屏倒计时", "input", "教学",
hint="几分钟", key="minutes")
add("roll_call", "随机点名", "action", "教学")
add("roll_call_set", "设置点名名单", "input", "教学",
hint="名字用逗号隔开", key="names")
add("whiteboard", "全屏白板", "action", "教学")
add("display_mode", "投影 / 显示设置", "action", "教学")
add("big_text_fixed", "全屏显示「安静」", "action", "教学")
# ---- 系统控制 ----
add("minimize_all", "显示桌面", "action", "系统")
add("task_view", "任务视图", "action", "系统")
add("close_windows", "关闭所有窗口", "action", "系统")
add("clock_seconds", "任务栏时钟显示秒", "toggle", "系统",
on=self._clock_seconds())
add("hidden_files", "显示隐藏文件", "toggle", "系统",
on=self._hidden_files())
add("sleep", "睡眠", "action", "系统")
add("hibernate", "休眠", "action", "系统")
add("lock_only", "只锁屏", "action", "系统")
add("sign_out", "注销当前用户", "action", "系统")
add("restart_graphics", "重启显卡驱动", "action", "系统")
# ---- 网络 ----
add("wifi_password", "查看 WiFi 密码", "action", "网络")
add("public_ip", "查公网 IP", "action", "网络")
add("ping_host", "Ping 一个地址", "input", "网络",
hint="如 192.168.2.1", key="host")
add("arp_devices", "局域网设备列表", "action", "网络")
add("net_adapters", "网卡列表", "action", "网络")
# ---- 文件(限定自己的目录)----'''
DEFS_TAIL_OLD = ''' add("open_file", "用默认程序打开", "action", "文件")
return items'''
DEFS_TAIL_NEW = ''' add("open_file", "用默认程序打开", "input", "文件",
hint="文件路径", key="path")
add("copy_file", "复制文件", "input", "文件",
hint="源路径", key="path", hint2="目标路径", key2="to")
add("move_file", "移动文件", "input", "文件",
hint="源路径", key="path", hint2="目标路径", key2="to")
add("zip_dir", "压缩为 zip", "input", "文件",
hint="文件夹路径", key="path")
add("unzip", "解压 zip", "input", "文件",
hint="zip 文件路径", key="path")
add("file_info", "文件详情", "input", "文件",
hint="文件路径", key="path")
add("folder_size", "文件夹大小", "input", "文件",
hint="文件夹路径", key="path")
add("open_recycle", "打开回收站", "action", "文件")
add("disk_by_type", "按类型统计磁盘", "action", "文件")
# ---- 工具 ----
add("password_gen", "生成随机密码", "action", "工具")
add("stopwatch", "秒表(电脑上显示)", "action", "工具")
add("world_clock", "世界时钟", "action", "工具")
add("hardware_info", "硬件信息", "action", "工具")
add("startup_items", "开机启动项", "action", "工具")
add("scheduled_tasks", "计划任务", "action", "工具")
add("system_detail", "系统详细信息", "action", "工具")
# ---- 媒体 ----
add("stop_after", "定时停止播放", "input", "媒体",
hint="几分钟后停", key="minutes")
add("fade_volume", "音量淡出到静音", "action", "媒体")
add("gpu_info", "显卡信息", "action", "媒体")
return items'''
# ---------------------------------------------------------------- 实现追加
IMPL_ANCHOR = ''' # ---------------- 持久化 ----------------'''
IMPL_NEW = ''' # ==================================================================
# 教学
# ==================================================================
def _fullscreen_window(self, builder, seconds: float = 0.0):
"""在电脑上开一个全屏窗口。builder(win) 负责往里放内容。"""
def build():
import tkinter as tk
root = getattr(self.actions.ui, "root", None)
if root is None:
return
win = tk.Toplevel(root)
win.attributes("-fullscreen", True)
win.attributes("-topmost", True)
def close(_event=None):
try:
win.destroy()
except Exception: # noqa: BLE001
pass
builder(win, close)
win.bind("<Escape>", close)
win.bind("<Button-1>", close)
win.protocol("WM_DELETE_WINDOW", close)
if seconds > 0:
win.after(int(seconds * 1000), close)
self.actions.ui.ui_call(build)
def _do_big_text(self, params) -> str:
text = str(params.get("text") or "").strip()
if not text:
raise ValueError("文字为空")
size = 96 if len(text) <= 8 else (64 if len(text) <= 20 else 40)
def builder(win, close):
import tkinter as tk
win.configure(bg="#0B1020")
tk.Label(win, text=text, bg="#0B1020", fg="#FFFFFF",
font=("Microsoft YaHei UI", size, "bold"),
wraplength=win.winfo_screenwidth() - 80,
justify="center").pack(expand=True, fill="both")
tk.Label(win, text="按 Esc 或点一下关闭", bg="#0B1020", fg="#55607A",
font=("Microsoft YaHei UI", 12)).place(
relx=0.5, rely=0.97, anchor="center")
self._fullscreen_window(builder)
return f"已全屏显示「{text[:20]}」"
def _do_big_text_fixed(self, params) -> str:
return self._do_big_text({"text": "安静"})
def _do_big_text_clear(self, params) -> str:
self.actions.close_image()
return "已关闭全屏内容"
def _do_countdown_screen(self, params) -> str:
try:
minutes = max(1, min(180, int(params.get("minutes") or 5)))
except (TypeError, ValueError):
minutes = 5
total = minutes * 60
def builder(win, close):
import tkinter as tk
win.configure(bg="#0B1020")
label = tk.Label(win, text="", bg="#0B1020", fg="#FFFFFF",
font=("Consolas", 160, "bold"))
label.pack(expand=True, fill="both")
hint = tk.Label(win, text=f"倒计时 {minutes} 分钟 · 按 Esc 结束",
bg="#0B1020", fg="#55607A",
font=("Microsoft YaHei UI", 14))
hint.place(relx=0.5, rely=0.95, anchor="center")
state = {"left": total}
def tick():
if state["left"] < 0:
return
mins, secs = divmod(max(0, state["left"]), 60)
label.configure(text=f"{mins:02d}:{secs:02d}",
fg="#FF6B6B" if state["left"] <= 10 else "#FFFFFF")
if state["left"] == 0:
try:
win.bell()
except Exception: # noqa: BLE001
pass
state["left"] -= 1
win.after(1000, tick)
tick()
self._fullscreen_window(builder)
return f"已开始 {minutes} 分钟倒计时"
def _do_whiteboard(self, params) -> str:
def builder(win, close):
import tkinter as tk
win.configure(bg="#FFFFFF")
canvas = tk.Canvas(win, bg="#FFFFFF", highlightthickness=0)
canvas.pack(fill="both", expand=True)
state = {"x": None, "y": None, "color": "#1F2328", "size": 4}
def press(event):
state["x"], state["y"] = event.x, event.y
def drag(event):
if state["x"] is None:
return
canvas.create_line(state["x"], state["y"], event.x, event.y,
fill=state["color"], width=state["size"],
capstyle="round")
state["x"], state["y"] = event.x, event.y
def release(_event):
state["x"] = state["y"] = None
canvas.bind("<Button-1>", press)
canvas.bind("<B1-Motion>", drag)
canvas.bind("<ButtonRelease-1>", release)
bar = tk.Frame(win, bg="#F5F7FA")
bar.place(relx=1.0, rely=0.0, anchor="ne")
def clear():
canvas.delete("all")
for text, color in (("黑", "#1F2328"), ("红", "#CF222E"),
("蓝", "#185CE8"), ("绿", "#1A7F37")):
tk.Button(bar, text=text, bg="#FFFFFF", fg=color, relief="flat",
font=("Microsoft YaHei UI", 11, "bold"), width=3,
command=lambda c=color: state.update(color=c)).pack(
side="left", padx=2, pady=4)
tk.Button(bar, text="清空", bg="#EAEEF2", relief="flat",
font=("Microsoft YaHei UI", 10),
command=clear).pack(side="left", padx=6, pady=4)
self._fullscreen_window(builder)
return "白板已打开(鼠标画,Esc 关闭)"
def _do_display_mode(self, params) -> str:
_run(["cmd", "/c", "start", "ms-settings:display"], shell=False)
return "已打开显示设置(投影模式在这里切)"
def _do_roll_call_set(self, params) -> str:
raw = str(params.get("names") or "").strip()
if not raw:
raise ValueError("名单为空")
parts = [p.strip() for p in raw.replace(",", ",").replace("、", ",")
.replace(" ", ",").split(",") if p.strip()]
if not parts:
raise ValueError("没解析出名字")
self.store.set("roll_call_names", parts)
return f"名单已存,共 {len(parts)} 人"
def _do_roll_call(self, params) -> str:
import random
names = self.store.get("roll_call_names") or []
if not names:
raise ValueError("还没有名单,先点「设置点名名单」")
picked = random.choice(names)
# 在电脑上全屏显示,让全班看到
self._do_big_text({"text": picked})
return f"点到:{picked}(共 {len(names)} 人)"
# ==================================================================
# 系统控制
# ==================================================================
def _do_minimize_all(self, params) -> str:
ctypes.windll.user32.keybd_event(0x5B, 0, 0, 0) # Win
ctypes.windll.user32.keybd_event(0x44, 0, 0, 0) # D
ctypes.windll.user32.keybd_event(0x44, 0, 2, 0)
ctypes.windll.user32.keybd_event(0x5B, 0, 2, 0)
return "已显示桌面"
def _do_task_view(self, params) -> str:
ctypes.windll.user32.keybd_event(0x5B, 0, 0, 0) # Win
ctypes.windll.user32.keybd_event(0x09, 0, 0, 0) # Tab
ctypes.windll.user32.keybd_event(0x09, 0, 2, 0)
ctypes.windll.user32.keybd_event(0x5B, 0, 2, 0)
return "已打开任务视图"
def _do_close_windows(self, params) -> str:
"""给所有可见的顶层窗口发关闭消息(相当于 Alt+F4 一轮)。"""
WM_CLOSE = 0x0010
closed = 0
user32 = ctypes.windll.user32
EnumProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_void_p,
ctypes.c_void_p)
own_pid = os.getpid()
def callback(hwnd, _lparam):
nonlocal closed
if not user32.IsWindowVisible(hwnd):
return True
length = user32.GetWindowTextLengthW(hwnd)
if length == 0:
return True
pid = ctypes.c_ulong()
user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid))
if pid.value == own_pid:
return True
cls = ctypes.create_unicode_buffer(256)
user32.GetClassNameW(hwnd, cls, 256)
if cls.value in ("Progman", "Shell_TrayWnd", "WorkerW"):
return True
user32.PostMessageW(hwnd, WM_CLOSE, 0, 0)
closed += 1
return True
user32.EnumWindows(EnumProc(callback), 0)
return f"已向 {closed} 个窗口发出关闭"
def _clock_seconds(self) -> bool:
code, out = _run(["reg", "query",
r"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced",
"/v", "ShowSecondsInSystemClock"])
return code == 0 and "0x1" in out
def _do_clock_seconds(self, params) -> str:
want = 1 if params.get("on") else 0
_run(["reg", "add",
r"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced",
"/v", "ShowSecondsInSystemClock", "/t", "REG_DWORD", "/d", str(want),
"/f"])
self._restart_explorer_quiet()
return "任务栏时钟已显示秒" if want else "任务栏时钟已恢复"
def _hidden_files(self) -> bool:
code, out = _run(["reg", "query",
r"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced",
"/v", "Hidden"])
return code == 0 and ("0x1" in out.split("REG_DWORD")[-1]
if "REG_DWORD" in out else False)
def _do_hidden_files(self, params) -> str:
want = 1 if params.get("on") else 2
_run(["reg", "add",
r"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced",
"/v", "Hidden", "/t", "REG_DWORD", "/d", str(want), "/f"])
self._restart_explorer_quiet()
return "已显示隐藏文件" if want == 1 else "已恢复不显示隐藏文件"
def _restart_explorer_quiet(self) -> None:
_run(["taskkill", "/F", "/IM", "explorer.exe"])
time.sleep(0.8)
subprocess.Popen("explorer.exe", shell=True, creationflags=_NO_WINDOW)
def _do_sleep(self, params) -> str:
_run(["rundll32.exe", "powrprof.dll,SetSuspendState", "0,1,0"])
return "已进入睡眠"
def _do_hibernate(self, params) -> str:
_run(["shutdown", "/h"])
return "已进入休眠(如果启用了休眠)"
def _do_lock_only(self, params) -> str:
ctypes.windll.user32.LockWorkStation()
return "已锁屏"
def _do_sign_out(self, params) -> str:
_run(["shutdown", "/l"])
return "已注销"
def _do_restart_graphics(self, params) -> str:
# Win + Ctrl + Shift + B
for vk in (0x5B, 0x11, 0x10, 0x42):
ctypes.windll.user32.keybd_event(vk, 0, 0, 0)
for vk in (0x42, 0x10, 0x11, 0x5B):
ctypes.windll.user32.keybd_event(vk, 0, 2, 0)
time.sleep(0.5)
return "已重启显卡驱动"
# ==================================================================
# 网络
# ==================================================================
def _do_wifi_password(self, params) -> str:
code, out = _run(["netsh", "wlan", "show", "profiles"])
if code != 0:
return "读不到 WiFi 配置"
names = []
for raw in out.splitlines():
text = raw.strip()
if text.startswith("All User Profile") or "所有用户配置文件" in text:
names.append(text.split(":", 1)[-1].strip())
if not names:
return "没有保存过 WiFi"
lines = []
for name in names[:6]:
code2, detail = _run(["netsh", "wlan", "show", "profile",
f"name={name}", "key=clear"])
pwd = ""
for raw in detail.splitlines():
text = raw.strip()
if text.startswith("Key Content") or "关键内容" in text:
pwd = text.split(":", 1)[-1].strip()
lines.append(f"{name}:{pwd or '(读不到,可能需要管理员)'}")
return "\\n".join(lines)
def _do_public_ip(self, params) -> str:
import urllib.request
for url in ("https://api.ipify.org", "https://ifconfig.me/ip"):
try:
with urllib.request.urlopen(url, timeout=6) as resp:
text = resp.read().decode("utf-8", errors="replace").strip()
if text:
return f"公网 IP:{text}"
except Exception: # noqa: BLE001
continue
return "查不到(可能没联网)"
def _do_ping_host(self, params) -> str:
host = str(params.get("host") or "").strip()
if not host:
raise ValueError("地址为空")
if not re.match(r"^[A-Za-z0-9_.:\\-]+$", host):
raise ValueError("地址含有不合法字符")
code, out = _run(["ping", "-n", "3", host], timeout=25)
lines = [l for l in out.splitlines() if l.strip()]
return "\\n".join(lines[-8:]) or "没有输出"
def _do_arp_devices(self, params) -> str:
code, out = _run(["arp", "-a"])
lines = [l.strip() for l in out.splitlines()
if l.strip() and "---" not in l and "Interface" not in l
and "接口" not in l]
return f"局域网设备 {len(lines)} 条:\\n" + "\\n".join(lines[:40])
def _do_net_adapters(self, params) -> str:
code, out = _run(["powershell", "-NoProfile", "-Command",
"Get-NetAdapter | ForEach-Object { "
"\\"$($_.Name) $($_.Status) $($_.LinkSpeed)\\" }"])
lines = [l for l in out.splitlines() if l.strip()]
return "\\n".join(lines) or "读不到网卡"
# ==================================================================
# 文件(继续限定在自己的目录内)
# ==================================================================
def _do_copy_file(self, params) -> str:
source = self.resolve_in_roots(str(params.get("path") or ""))
target = self.resolve_in_roots(str(params.get("to") or ""))
if not source.exists():
raise ValueError("源文件不存在")
import shutil as _shutil
if source.is_dir():
_shutil.copytree(source, target, dirs_exist_ok=True)
else:
target.parent.mkdir(parents=True, exist_ok=True)
_shutil.copy2(source, target)
return f"已复制到 {target}"
def _do_move_file(self, params) -> str:
source = self.resolve_in_roots(str(params.get("path") or ""))
target = self.resolve_in_roots(str(params.get("to") or ""))
if not source.exists():
raise ValueError("源文件不存在")
import shutil as _shutil
target.parent.mkdir(parents=True, exist_ok=True)
_shutil.move(str(source), str(target))
return f"已移动到 {target}"
def _do_zip_dir(self, params) -> str:
import zipfile
source = self.resolve_in_roots(str(params.get("path") or ""))
if not source.is_dir():
raise ValueError("不是文件夹")
out = source.parent / f"{source.name}.zip"
with zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED) as zf:
for item in source.rglob("*"):
if item.is_file():
zf.write(item, item.relative_to(source.parent))
return f"已压缩为 {out.name}({out.stat().st_size // 1024} KB)"
def _do_unzip(self, params) -> str:
import zipfile
source = self.resolve_in_roots(str(params.get("path") or ""))
if not source.is_file() or source.suffix.lower() != ".zip":
raise ValueError("不是 zip 文件")
target = source.parent / source.stem
target.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(source) as zf:
zf.extractall(target)
return f"已解压到 {target.name}"
def _do_file_info(self, params) -> str:
target = self.resolve_in_roots(str(params.get("path") or ""))
if not target.exists():
raise ValueError("文件不存在")
stat = target.stat()
kind = "文件夹" if target.is_dir() else "文件"
size = stat.st_size
readable = (f"{size / 1048576:.2f} MB" if size > 1048576
else f"{size // 1024} KB")
return (f"{kind}:{target.name}\\n"
f"大小:{readable}\\n"
f"修改:{time.strftime('%Y-%m-%d %H:%M', time.localtime(stat.st_mtime))}\\n"
f"位置:{target.parent}")
def _do_folder_size(self, params) -> str:
target = self.resolve_in_roots(str(params.get("path") or ""))
if not target.is_dir():
raise ValueError("不是文件夹")
total = 0
count = 0
for item in target.rglob("*"):
try:
if item.is_file():
total += item.stat().st_size
count += 1
except OSError:
continue
return (f"{target.name}:{count} 个文件,"
f"共 {total / 1048576:.1f} MB")
def _do_open_recycle(self, params) -> str:
os.startfile("shell:RecycleBinFolder") # noqa: S606
return "已打开回收站"
def _do_disk_by_type(self, params) -> str:
buckets = {"图片": 0, "视频": 0, "音频": 0, "文档": 0, "压缩包": 0, "其他": 0}
exts = {
"图片": {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"},
"视频": {".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv"},
"音频": {".mp3", ".wav", ".flac", ".m4a", ".aac"},
"文档": {".doc", ".docx", ".pdf", ".ppt", ".pptx", ".xls",
".xlsx", ".txt", ".md"},
"压缩包": {".zip", ".rar", ".7z", ".tar", ".gz"},
}
for root in self.allowed_roots():
try:
for item in root.rglob("*"):
if not item.is_file():
continue
suffix = item.suffix.lower()
for name, group in exts.items():
if suffix in group:
buckets[name] += item.stat().st_size
break
else:
buckets["其他"] += item.stat().st_size
except OSError:
continue
parts = [f"{k} {v / 1048576:.0f}MB" for k, v in buckets.items() if v]
return " | ".join(parts) or "统计不到"
# ==================================================================
# 工具
# ==================================================================
def _do_password_gen(self, params) -> str:
import secrets
import string
alphabet = string.ascii_letters + string.digits + "!@#$%^&*-_"
pwd = "".join(secrets.choice(alphabet) for _ in range(16))
self.actions.clip_set(pwd)
return f"已生成并复制到剪贴板:\\n{pwd}"
def _do_stopwatch(self, params) -> str:
def builder(win, close):
import tkinter as tk
win.configure(bg="#0B1020")
label = tk.Label(win, text="00:00.0", bg="#0B1020", fg="#FFFFFF",
font=("Consolas", 140, "bold"))
label.pack(expand=True, fill="both")
win.configure(bg="#0B1020")
state = {"start": time.time()}
def tick():
elapsed = time.time() - state["start"]
mins, secs = divmod(int(elapsed), 60)
label.configure(text=f"{mins:02d}:{secs:02d}.{int(elapsed * 10) % 10}")
win.after(100, tick)
tick()
self._fullscreen_window(builder)
return "秒表已打开(Esc 关闭)"
def _do_world_clock(self, params) -> str:
now = time.time()
zones = [("北京", 8), ("伦敦", 0), ("纽约", -5), ("洛杉矶", -8),
("东京", 9), ("悉尼", 10)]
lines = []
for name, offset in zones:
local = time.gmtime(now + offset * 3600)
lines.append(f"{name} {time.strftime('%H:%M', local)}")
return "\\n".join(lines)
def _do_hardware_info(self, params) -> str:
script = (
"$c=Get-CimInstance Win32_Processor|Select-Object -First 1;"
"$m=(Get-CimInstance Win32_PhysicalMemory|Measure-Object -Property "
"Capacity -Sum).Sum/1GB;"
"$g=Get-CimInstance Win32_VideoController|Select-Object -First 1;"
"$b=Get-CimInstance Win32_BaseBoard|Select-Object -First 1;"
"\\"CPU: $($c.Name)\\";\\"核心: $($c.NumberOfCores) 核 "
"$($c.NumberOfLogicalProcessors) 线程\\";"
"\\"内存: $([math]::Round($m,1)) GB\\";"
"\\"显卡: $($g.Name)\\";\\"主板: $($b.Manufacturer) $($b.Product)\\"")
code, out = _run(["powershell", "-NoProfile", "-Command", script], timeout=30)
lines = [l for l in out.splitlines() if l.strip()]
return "\\n".join(lines) or "读不到硬件信息"
def _do_startup_items(self, params) -> str:
script = ("Get-CimInstance Win32_StartupCommand | "
"ForEach-Object { \\"$($_.Name) -> $($_.Command)\\" }")
code, out = _run(["powershell", "-NoProfile", "-Command", script], timeout=30)
lines = [l for l in out.splitlines() if l.strip()]
return f"启动项 {len(lines)} 个:\\n" + "\\n".join(
l[:100] for l in lines[:30]) if lines else "没有启动项"
def _do_scheduled_tasks(self, params) -> str:
script = ("Get-ScheduledTask | Where-Object {$_.State -ne 'Disabled'} | "
"Select-Object -First 30 -ExpandProperty TaskName")
code, out = _run(["powershell", "-NoProfile", "-Command", script], timeout=30)
lines = [l for l in out.splitlines() if l.strip()]
return f"计划任务 {len(lines)} 个:\\n" + "\\n".join(lines)
def _do_system_detail(self, params) -> str:
import platform
code, out = _run(["wmic", "os", "get", "Caption,Version,BuildNumber,"
"InstallDate,OSArchitecture", "/format:list"])
lines = [l.strip() for l in out.splitlines() if l.strip()]
return (f"{platform.system()} {platform.release()} "
f"{platform.machine()}\\n" + "\\n".join(lines))
# ==================================================================
# 媒体
# ==================================================================
def _do_stop_after(self, params) -> str:
try:
minutes = max(1, min(180, int(params.get("minutes") or 10)))
except (TypeError, ValueError):
minutes = 10
import threading
def fire():
self.actions.stop_audio()
timer = threading.Timer(minutes * 60, fire)
timer.daemon = True
timer.start()
self._timers.append(timer)
return f"{minutes} 分钟后停止播放"
def _do_fade_volume(self, params) -> str:
for _ in range(20):
self._volume_key(0xAE, 1)
time.sleep(0.05)
return "音量已淡出到最低"
def _do_gpu_info(self, params) -> str:
script = ("Get-CimInstance Win32_VideoController | ForEach-Object { "
"\\"$($_.Name) 驱动 $($_.DriverVersion) "
"显存 $([math]::Round($_.AdapterRAM/1GB,1))GB\\" }")
code, out = _run(["powershell", "-NoProfile", "-Command", script], timeout=25)
lines = [l for l in out.splitlines() if l.strip()]
return "\\n".join(lines) or "读不到显卡信息"
''' + IMPL_ANCHOR
def main() -> int:
ok = True
text = FEATURES.read_text(encoding="utf-8")
for old, new, tag in ((DEFS_OLD, DEFS_NEW, "defs 前半"),
(DEFS_TAIL_OLD, DEFS_TAIL_NEW, "defs 后半"),
(IMPL_ANCHOR, IMPL_NEW, "实现")):
if old not in text:
print(f" [失败] {tag} 锚点未匹配")
ok = False
else:
text = text.replace(old, new, 1)
print(f" features.py / {tag}: OK")
if ok:
FEATURES.write_text(text, encoding="utf-8")
print("\n语法检查:")
import ast
try:
ast.parse(FEATURES.read_text(encoding="utf-8"))
print(" features.py: OK")
except SyntaxError as exc:
print(f" features.py: 语法错误 {exc}")
ok = False
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())