From 5e40ed426bf5418ad38f613bc38e1997cc7cf162 Mon Sep 17 00:00:00 2001 From: hotyue <52734432+hotyue@users.noreply.github.com> Date: Fri, 17 Apr 2026 02:24:07 +0000 Subject: [PATCH] chore: revert failed v3.6.0 attempts, rollback to safe state --- core/agent_daemon.sh | 79 -------------------- core/install.sh | 77 ++++++-------------- master/install_master.sh | 21 ------ master/tg_master.sh | 153 ++------------------------------------- 4 files changed, 27 insertions(+), 303 deletions(-) diff --git a/core/agent_daemon.sh b/core/agent_daemon.sh index 6a0c076..65f7804 100755 --- a/core/agent_daemon.sh +++ b/core/agent_daemon.sh @@ -292,86 +292,7 @@ class AgentHandler(http.server.BaseHTTPRequestHandler): self.send_response(400) self.end_headers() self.wfile.write(b"400 Bad Request: Invalid Characters\n") - - # ================== [v3.6.0 新增: 远程 OTA 升级接口] ================== - elif req_path == '/trigger_upgrade': - try: - allow_ota = "false" - if os.path.exists('/opt/ip_sentinel/config.conf'): - with open('/opt/ip_sentinel/config.conf', 'r') as f: - for line in f: - if line.startswith('ALLOW_OTA='): - allow_ota = line.strip().split('=', 1)[1].strip('"\'') - break - - if allow_ota.lower() != "true": - self.send_response(403) - self.end_headers() - self.wfile.write(b"403 Forbidden: OTA Disabled\n") - return - - # 1. 精确斩断 HTTP:声明内容长度并强制 Close,让 Master 瞬间拿到回执并断开 TCP 连接 - resp_msg = b"Action Accepted: trigger_upgrade\n" - self.send_response(200) - self.send_header("Content-type", "text/plain") - self.send_header("Content-Length", str(len(resp_msg))) - self.send_header("Connection", "close") - self.end_headers() - self.wfile.write(resp_msg) - self.wfile.flush() - - # 2. 终极无状态执行脱壳: - # stdin=subprocess.DEVNULL: 彻底切断标准输入,防止 curl|bash 误读环境吞噬管道 - # close_fds=True & start_new_session=True: 剥夺所有网络 Socket 和进程树的血缘关系 - cmd = "sleep 2 && export SILENT_OTA=true && curl -sL https://raw.githubusercontent.com/hotyue/IP-Sentinel/main/core/install.sh | bash" - subprocess.Popen(cmd, shell=True, start_new_session=True, close_fds=True, - stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - - except Exception as e: - self.send_response(500) - self.end_headers() - - # ================== [v3.6.0 新增: 模块动态启停接口] ================== - elif req_path == '/trigger_toggle': - mod_name = query.get('mod', [''])[0] - target_state = query.get('state', [''])[0].lower() - if mod_name not in ['google', 'trust'] or target_state not in ['true', 'false']: - self.send_response(400) - self.end_headers() - self.wfile.write(b"400 Bad Request: Invalid parameters\n") - return - - config_key = f"ENABLE_{mod_name.upper()}=" - - try: - config_path = '/opt/ip_sentinel/config.conf' - with open(config_path, 'r', encoding='utf-8', errors='ignore') as f: - lines = f.readlines() - - found = False - for i, line in enumerate(lines): - if line.startswith(config_key): - lines[i] = f'{config_key}"{target_state}"\n' - found = True - break - - if not found: - lines.append(f'{config_key}"{target_state}"\n') - - with open(config_path, 'w', encoding='utf-8') as f: - f.writelines(lines) - - self.send_response(200) - self.send_header("Content-type", "text/plain") - self.end_headers() - self.wfile.write(b"Action Accepted: trigger_toggle\n") - - except Exception as e: - self.send_response(500) - self.end_headers() - self.wfile.write(f"500 Internal Error: {str(e)}\n".encode('utf-8')) - else: self.send_response(404) self.end_headers() diff --git a/core/install.sh b/core/install.sh index c486dff..d29ac3c 100755 --- a/core/install.sh +++ b/core/install.sh @@ -49,20 +49,12 @@ if [ ! -s "/tmp/map.json" ]; then fi echo -e "\n请选择操作:" -# [v3.6.0 新增: 无人值守静默 OTA 升级拦截] -if [ "$SILENT_OTA" == "true" ] && [ -f "$CONFIG_FILE" ]; then - echo -e "\n📡 [系统] 接收到远端静默 OTA 指令,直接切入平滑升级模式..." - ACTION_CHOICE="1" - # 模拟用户输入,直接跳过提示 - UPGRADE_CHOICE="y" - LOG_CHOICE="y" -else - echo -e "\n请选择操作:" - echo " 1) 🚀 部署边缘节点 (进入全球节点配置)" - echo " 2) 🗑️ 一键卸载 IP-Sentinel" - read -p "请输入选择 [1-2] (默认1): " ACTION_CHOICE - ACTION_CHOICE=${ACTION_CHOICE:-1} -fi +echo " 1) 🚀 部署边缘节点 (进入全球节点配置)" +echo " 2) 🗑️ 一键卸载 IP-Sentinel" +read -p "请输入选择 [1-2] (默认1): " ACTION_CHOICE + +# [v3.5.2 修复] 防止用户直接回车导致变量为空,从而漏过下方的平滑升级判定 +ACTION_CHOICE=${ACTION_CHOICE:-1} if [ "$ACTION_CHOICE" == "2" ]; then echo -e "\n⏳ 正在拉取卸载程序..." @@ -79,20 +71,10 @@ KEEP_LOGS="true" if [ "$ACTION_CHOICE" == "1" ] && [ -f "$CONFIG_FILE" ]; then echo -e "\n\033[33m💡 哨兵雷达提示:检测到本机已部署过 IP-Sentinel。\033[0m" - - # [v3.6.0 终极修复: 拦截静默模式下的交互,防止 read 吞噬管道脚本指令] - if [ "$SILENT_OTA" == "true" ]; then - UPGRADE_CHOICE="y" - LOG_CHOICE="y" - else - read -p "👉 是否按原配置直接进行平滑升级?(y/n, 默认y): " UPGRADE_CHOICE - fi - + read -p "👉 是否按原配置直接进行平滑升级?(y/n, 默认y): " UPGRADE_CHOICE if [[ -z "$UPGRADE_CHOICE" || "$UPGRADE_CHOICE" =~ ^[Yy]$ ]]; then UPGRADE_MODE="true" - if [ "$SILENT_OTA" != "true" ]; then - read -p "👉 是否保留历史运行日志?(y/n, 默认y): " LOG_CHOICE - fi + read -p "👉 是否保留历史运行日志?(y/n, 默认y): " LOG_CHOICE if [[ "$LOG_CHOICE" =~ ^[Nn]$ ]]; then KEEP_LOGS="false" fi @@ -224,10 +206,20 @@ if [ "$UPGRADE_MODE" == "false" ]; then mkdir -p "${INSTALL_DIR}/data/regions/${COUNTRY_ID}/${STATE_ID}" mkdir -p "${INSTALL_DIR}/logs" - # 3. 功能模块前置开关 (v3.6.0 默认全量加载,后续经由 TG 动态启停) - echo -e "\n[3/7] 正在初始化养护模块 (默认全量部署,支持 TG 远程启停)..." + # 3. 功能模块前置开关 (按需加载) + echo -e "\n[3/7] 请选择需要开启的养护模块 (按需开启,节省资源):" + echo " 1) 📍 仅开启 [Google 区域纠偏] (默认,适合流媒体解锁机位漂移)" + echo " 2) 🛡️ 仅开启 [IP 信用净化] (适合高风险机房 IP 降低 Scamalytics 分数)" + echo " 3) 🔥 双管齐下 (同时开启以上两项)" + read -p "请输入选择 [1-3] (默认1): " MODULE_CHOICE + ENABLE_GOOGLE="true" - ENABLE_TRUST="true" + ENABLE_TRUST="false" + case ${MODULE_CHOICE:-1} in + 2) ENABLE_GOOGLE="false"; ENABLE_TRUST="true" ;; + 3) ENABLE_GOOGLE="true"; ENABLE_TRUST="true" ;; + *) ENABLE_GOOGLE="true"; ENABLE_TRUST="false" ;; + esac # 4. 接入 Master 中枢配置 echo -e "\n[4/7] 是否接入 Master 司令部?(需要配置与主控相同的 TG 机器人) (y/n)" @@ -244,25 +236,12 @@ if [ "$UPGRADE_MODE" == "false" ]; then if [ -z "$USER_TOKEN" ]; then TG_TOKEN="OFFICIAL_GATEWAY_MODE" TG_API_URL="https://omni-gateway.samanthaestime296.workers.dev" - ALLOW_OTA="false" echo -e "\033[32m✅ 已自动连接官方安全网关 (@OmniBeacon_bot)。\033[0m" echo -e "\033[33m👉 请确保您已关注官方机器人并发送过 /start,否则将无法接收消息。\033[0m" - echo -e "\033[31m⛔ [安全协议] 为保障节点安全,接入官方网关时,远程 OTA 升级功能已被永久禁用!若需该功能请自建 Master。\033[0m" else TG_TOKEN="$USER_TOKEN" TG_API_URL="https://api.telegram.org/bot${TG_TOKEN}/sendMessage" echo -e "\033[32m✅ 已记录您的私有机器人 Token。\033[0m" - - # [v3.6.0 新增: 私有节点 OTA 授权] - echo -e "\n\033[36m[OTA 授权] 是否允许 Master 司令部向本节点下发 OTA 远程升级指令?\033[0m" - read -p "请输入选择 [y/n] (默认n, 拒绝则只能登录 SSH 手动升级): " OTA_CHOICE - if [[ "$OTA_CHOICE" =~ ^[Yy]$ ]]; then - ALLOW_OTA="true" - echo -e "\033[32m✅ 远程 OTA 升级接口已开启,随时听候司令部调遣。\033[0m" - else - ALLOW_OTA="false" - echo -e "\033[33m🛡️ 远程 OTA 升级接口已关闭,拒绝一切远端升级指令。\033[0m" - fi fi echo -e "\033[33m💡 提示:如果您不知道自己的 Chat ID,可以关注 @userinfobot 获取。\033[0m" @@ -452,9 +431,6 @@ BIND_IP="$BIND_IP" # [v3.5.2新增: 双轨身份系统] NODE_NAME="$NODE_NAME" NODE_ALIAS="$NODE_ALIAS" - -# [v3.6.0新增: 远程控制权限] -ALLOW_OTA="$ALLOW_OTA" EOF # ================== [v3.0.3 变更: 敏感配置文件权限收敛] ================== @@ -516,17 +492,6 @@ if [ "$UPGRADE_MODE" == "true" ]; then echo "NODE_ALIAS=\"$NODE_ALIAS\"" >> "$CONFIG_FILE" fi fi - - # [v3.6.0 升级兼容] 补齐缺失的远程控制开关,尊重原有开关状态 - if ! grep -q "^ALLOW_OTA=" "$CONFIG_FILE"; then - echo 'ALLOW_OTA="false"' >> "$CONFIG_FILE" - fi - if ! grep -q "^ENABLE_GOOGLE=" "$CONFIG_FILE"; then - echo 'ENABLE_GOOGLE="true"' >> "$CONFIG_FILE" - fi - if ! grep -q "^ENABLE_TRUST=" "$CONFIG_FILE"; then - echo 'ENABLE_TRUST="true"' >> "$CONFIG_FILE" - fi fi # ======================================================================== diff --git a/master/install_master.sh b/master/install_master.sh index d6a3b14..a91522d 100755 --- a/master/install_master.sh +++ b/master/install_master.sh @@ -113,17 +113,6 @@ if [ "$UPGRADE_MODE" == "false" ]; then # 2. 交互配置机器人 echo -e "\n[2/4] 配置控制中枢机器人:" read -p "请输入 Telegram Bot Token: " TG_TOKEN - - # [v3.6.0 新增: 控制中枢 OTA 下发权限配置] - echo -e "\n\033[36m[OTA 权限] 是否允许本中枢向受控节点下发远程 OTA 升级指令?\033[0m" - read -p "请输入选择 [y/n] (默认n, 建议仅在完全信任节点环境时开启): " MASTER_OTA_CHOICE - if [[ "$MASTER_OTA_CHOICE" =~ ^[Yy]$ ]]; then - ENABLE_MASTER_OTA="true" - echo -e "\033[32m✅ 中枢 OTA 升级下发权限已开启。\033[0m" - else - ENABLE_MASTER_OTA="false" - echo -e "\033[33m🛡️ 中枢 OTA 升级下发权限已关闭。\033[0m" - fi cat > "${MASTER_DIR}/master.conf" << EOF # IP-Sentinel Master 本地固化配置 (v${TARGET_VERSION}) @@ -131,18 +120,10 @@ MASTER_VERSION="$TARGET_VERSION" TG_TOKEN="$TG_TOKEN" DB_FILE="$DB_FILE" MASTER_DIR="$MASTER_DIR" -ENABLE_MASTER_OTA="$ENABLE_MASTER_OTA" EOF fi # 🛑 拦截块结束 -# [v3.6.0 升级兼容] 补齐老版本缺失的 OTA 下发权限开关 (默认对自建用户开启,保障丝滑体验) -if [ "$UPGRADE_MODE" == "true" ]; then - if ! grep -q "^ENABLE_MASTER_OTA=" "${MASTER_DIR}/master.conf"; then - echo 'ENABLE_MASTER_OTA="true"' >> "${MASTER_DIR}/master.conf" - fi -fi - # 3. 初始化 SQLite 数据库 (幂等操作,升级模式下由 tg_master.sh 负责热修补) echo -e "\n[3/4] 正在初始化 SQLite 数据库表结构..." sqlite3 "$DB_FILE" < /dev/null } -# [v3.6.0 新增: 支持内联键盘的原位 UI 重绘函数] -edit_ui() { - curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/editMessageText" \ - -H "Content-Type: application/json" \ - -d "{\"chat_id\":\"$1\",\"message_id\":\"$2\",\"text\":\"$3\",\"parse_mode\":\"Markdown\",\"reply_markup\":{\"inline_keyboard\":$4}}" > /dev/null -} - # 数据库执行函数 db_exec() { sqlite3 "$DB_FILE" "$1" @@ -67,12 +60,10 @@ generate_signed_url() { } # ======================================================================== -# ================== [v3.1.3/v3.6.0 核心: 数据库结构无损热升级] ================== -# 自动探测并增加缺失字段,屏蔽已存在的报错,保护老节点数据 +# ================== [v3.1.3/v3.5.2 核心: 数据库结构无损热升级] ================== +# 自动探测并增加 region 与 node_alias 字段,屏蔽已存在的报错,保护老节点数据 db_exec "ALTER TABLE nodes ADD COLUMN region TEXT DEFAULT 'UNKNOWN';" 2>/dev/null db_exec "ALTER TABLE nodes ADD COLUMN node_alias TEXT;" 2>/dev/null -db_exec "ALTER TABLE nodes ADD COLUMN enable_google TEXT DEFAULT 'true';" 2>/dev/null -db_exec "ALTER TABLE nodes ADD COLUMN enable_trust TEXT DEFAULT 'true';" 2>/dev/null # ======================================================================== # --- 核心轮询循环 --- @@ -193,38 +184,10 @@ while true; do VER_INFO="${VER_INFO}\n✨ **发现新版本**: \`v${REMOTE_VER}\` (请尽快更新主控)" fi - # [v3.6.0] 动态判定渲染 OTA 升级按钮 - BTNS="[[{\"text\":\"🖥️ 我的节点列表\",\"callback_data\":\"list_nodes\"}], [{\"text\":\"🚀 全节点日报汇总\",\"callback_data\":\"all_reports\"}], [{\"text\":\"🛠️ 全节点一键维护\",\"callback_data\":\"all_run\"}]" - if [ "$ENABLE_MASTER_OTA" == "true" ]; then - BTNS="$BTNS, [{\"text\":\"🔄 全网一键升级 (OTA)\",\"callback_data\":\"all_upgrade_confirm\"}]" - fi - BTNS="$BTNS]" - + BTNS="[[{\"text\":\"🖥️ 我的节点列表\",\"callback_data\":\"list_nodes\"}], [{\"text\":\"🚀 全节点日报汇总\",\"callback_data\":\"all_reports\"}], [{\"text\":\"🛠️ 全节点一键维护\",\"callback_data\":\"all_run\"}]]" send_ui "$CHAT_ID" "🛡️ **IP-Sentinel 司令部**\n${VER_INFO}\n\n欢迎回来,长官。请下达指令:" "$BTNS" ;; - "all_upgrade_confirm") - BTNS="[[{\"text\":\"⚠️ 确认下发全网升级\",\"callback_data\":\"all_upgrade_do\"}], [{\"text\":\"❌ 取消操作\",\"callback_data\":\"list_nodes\"}]]" - send_ui "$CHAT_ID" "⚠️ **高危操作警告**:\n全网下发 OTA 升级指令将导致所有节点进入静默重载,可能出现短暂失联。\n*(仅有授权了 OTA 权限的节点会真正执行)*" "$BTNS" - ;; - - "all_upgrade_do") - if [ "$ENABLE_MASTER_OTA" != "true" ]; then - send_msg "$CHAT_ID" "⛔ 中枢 OTA 下发权限未开启,指令已拦截。" - continue - fi - NODE_DATA=$(db_exec "SELECT node_name, agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID';") - if [ -z "$NODE_DATA" ]; then - send_msg "$CHAT_ID" "⚠️ 您名下暂无在线节点。" - else - send_msg "$CHAT_ID" "📢 **司令部指令下达:正在向全网哨兵广播 OTA 升级指令...**" - echo "$NODE_DATA" | while IFS='|' read -r NNAME AIP APORT; do - TARGET_URL=$(generate_signed_url "$AIP" "$APORT" "/trigger_upgrade") - curl -s -m 5 "$TARGET_URL" > /dev/null & - done - fi - ;; - "all_reports") NODE_DATA=$(db_exec "SELECT node_name, agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID';") if [ -z "$NODE_DATA" ]; then @@ -320,113 +283,9 @@ while true; do TARGET_ALIAS=$(db_exec "SELECT IFNULL(node_alias, node_name) FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;") [ -z "$TARGET_ALIAS" ] && TARGET_ALIAS="$TARGET_NODE" - # [v3.6.0] 收纳改名和升级功能至 L5 高级控制面板,L4 保持清爽 - BTNS="[[{\"text\":\"📍 Google 纠偏\",\"callback_data\":\"google:$TARGET_NODE\"}, {\"text\":\"🛡️ 信用净化\",\"callback_data\":\"trust:$TARGET_NODE\"}], [{\"text\":\"📜 实时日志\",\"callback_data\":\"log:$TARGET_NODE\"}, {\"text\":\"📊 统计战报\",\"callback_data\":\"report:$TARGET_NODE\"}], [{\"text\":\"⚙️ 高级控制功能\",\"callback_data\":\"adv:$TARGET_NODE\"}, {\"text\":\"🗑️ 剔除失联节点\",\"callback_data\":\"del:$TARGET_NODE\"}], [{\"text\":\"⬅️ 返回大区目录\",\"callback_data\":\"list_nodes\"}]]" - - if [ -n "$MSG_ID" ]; then - edit_ui "$CHAT_ID" "$MSG_ID" "⚙️ **目标锁定**: \`$TARGET_ALIAS\`\n*(身份标识: $TARGET_NODE)*\n请选择战术动作:" "$BTNS" - else - send_ui "$CHAT_ID" "⚙️ **目标锁定**: \`$TARGET_ALIAS\`\n*(身份标识: $TARGET_NODE)*\n请选择战术动作:" "$BTNS" - fi - ;; - - adv:*) - # [L5 高级控制面板渲染] - TARGET_NODE=$(echo "${TEXT#*:}" | tr -cd 'a-zA-Z0-9_.-') - TARGET_ALIAS=$(db_exec "SELECT IFNULL(node_alias, node_name) FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;") - [ -z "$TARGET_ALIAS" ] && TARGET_ALIAS="$TARGET_NODE" - - # 从数据库抓取当前节点的开关状态 - TOGGLE_INFO=$(db_exec "SELECT enable_google, enable_trust FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;") - ST_GOOGLE=$(echo "$TOGGLE_INFO" | cut -d'|' -f1) - ST_TRUST=$(echo "$TOGGLE_INFO" | cut -d'|' -f2) - - # 动态渲染状态机红绿灯 UI - [ "$ST_GOOGLE" == "true" ] && BTN_G="🔴 停用 Google 纠偏" && ACT_G="false" || { BTN_G="🟢 启用 Google 纠偏"; ACT_G="true"; } - [ "$ST_TRUST" == "true" ] && BTN_T="🔴 停用信用净化" && ACT_T="false" || { BTN_T="🟢 启用信用净化"; ACT_T="true"; } - - BTNS="[[{\"text\":\"$BTN_G\",\"callback_data\":\"toggle:google:$TARGET_NODE:$ACT_G\"}], [{\"text\":\"$BTN_T\",\"callback_data\":\"toggle:trust:$TARGET_NODE:$ACT_T\"}], [{\"text\":\"✏️ 修改节点备注\",\"callback_data\":\"rename:$TARGET_NODE\"}]" - - if [ "$ENABLE_MASTER_OTA" == "true" ]; then - BTNS="$BTNS, [{\"text\":\"🔄 远程升级该节点\",\"callback_data\":\"upgrade_confirm:$TARGET_NODE\"}]" - fi - BTNS="$BTNS, [{\"text\":\"⬅️ 返回节点面板\",\"callback_data\":\"manage:$TARGET_NODE\"}]]" - - if [ -n "$MSG_ID" ]; then - edit_ui "$CHAT_ID" "$MSG_ID" "⚙️ **高级控制** | \`$TARGET_ALIAS\`\n请谨慎操作节点底层逻辑:" "$BTNS" - else - send_ui "$CHAT_ID" "⚙️ **高级控制** | \`$TARGET_ALIAS\`\n请谨慎操作节点底层逻辑:" "$BTNS" - fi - ;; - - toggle:*) - # [动态启停通信闭环] - IFS=':' read -r CMD MOD_NAME TARGET_NODE TARGET_STATE <<< "$TEXT" - CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-') - - AGENT_INFO=$(db_exec "SELECT agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;") - AGENT_IP=$(echo "$AGENT_INFO" | cut -d'|' -f1) - AGENT_PORT=$(echo "$AGENT_INFO" | cut -d'|' -f2) - - if [ -n "$AGENT_IP" ] && [ -n "$AGENT_PORT" ]; then - TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_toggle") - TARGET_URL="${TARGET_URL}&mod=${MOD_NAME}&state=${TARGET_STATE}" - - RESPONSE=$(curl -s -m 5 "$TARGET_URL" || echo "FAILED") - if [[ "$RESPONSE" == *"Action Accepted"* ]]; then - # 下发成功,更新中枢 DB,为接下来的无缝重绘准备数据 - db_exec "UPDATE nodes SET enable_${MOD_NAME}='$TARGET_STATE' WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE';" - - # [神级交互: 原位丝滑重绘红绿灯面板] - TOGGLE_INFO=$(db_exec "SELECT enable_google, enable_trust FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;") - ST_GOOGLE=$(echo "$TOGGLE_INFO" | cut -d'|' -f1) - ST_TRUST=$(echo "$TOGGLE_INFO" | cut -d'|' -f2) - [ "$ST_GOOGLE" == "true" ] && BTN_G="🔴 停用 Google 纠偏" && ACT_G="false" || { BTN_G="🟢 启用 Google 纠偏"; ACT_G="true"; } - [ "$ST_TRUST" == "true" ] && BTN_T="🔴 停用信用净化" && ACT_T="false" || { BTN_T="🟢 启用信用净化"; ACT_T="true"; } - - BTNS="[[{\"text\":\"$BTN_G\",\"callback_data\":\"toggle:google:$TARGET_NODE:$ACT_G\"}], [{\"text\":\"$BTN_T\",\"callback_data\":\"toggle:trust:$TARGET_NODE:$ACT_T\"}], [{\"text\":\"✏️ 修改节点备注\",\"callback_data\":\"rename:$TARGET_NODE\"}]" - if [ "$ENABLE_MASTER_OTA" == "true" ]; then - BTNS="$BTNS, [{\"text\":\"🔄 远程升级该节点\",\"callback_data\":\"upgrade_confirm:$TARGET_NODE\"}]" - fi - BTNS="$BTNS, [{\"text\":\"⬅️ 返回节点面板\",\"callback_data\":\"manage:$TARGET_NODE\"}]]" - TARGET_ALIAS=$(db_exec "SELECT IFNULL(node_alias, node_name) FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;") - - edit_ui "$CHAT_ID" "$MSG_ID" "⚙️ **高级控制** | \`$TARGET_ALIAS\`\n✅ 操作成功:模块 [$MOD_NAME] 状态已切换为 $TARGET_STATE!" "$BTNS" - else - send_msg "$CHAT_ID" "❌ 指令下发失败,节点可能离线或拒绝请求。" - fi - fi - ;; - - upgrade_confirm:*) - # [单节点升级二次确认] - TARGET_NODE=$(echo "${TEXT#*:}" | tr -cd 'a-zA-Z0-9_.-') - BTNS="[[{\"text\":\"⚠️ 确认下发 OTA 升级\",\"callback_data\":\"do_upgrade:$TARGET_NODE\"}], [{\"text\":\"❌ 取消操作\",\"callback_data\":\"adv:$TARGET_NODE\"}]]" - edit_ui "$CHAT_ID" "$MSG_ID" "⚠️ **高危操作警告**:\n确定向 \`$TARGET_NODE\` 下发 OTA 升级指令吗?节点将执行平滑重启。" "$BTNS" - ;; - - do_upgrade:*) - # [单节点执行升级] - TARGET_NODE=$(echo "${TEXT#*:}" | tr -cd 'a-zA-Z0-9_.-') - CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-') - - AGENT_INFO=$(db_exec "SELECT agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;") - AGENT_IP=$(echo "$AGENT_INFO" | cut -d'|' -f1) - AGENT_PORT=$(echo "$AGENT_INFO" | cut -d'|' -f2) - - if [ -n "$AGENT_IP" ] && [ -n "$AGENT_PORT" ]; then - edit_msg "$CHAT_ID" "$MSG_ID" "⏳ 正在建立加密隧道,推送 OTA 升级指令..." - TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_upgrade") - RESPONSE=$(curl -s -m 5 "$TARGET_URL" || echo "FAILED") - - if [[ "$RESPONSE" == *"Action Accepted"* ]]; then - edit_msg "$CHAT_ID" "$MSG_ID" "✅ OTA 升级指令下发成功!节点 \`$TARGET_NODE\` 正在后台无状态重载..." - elif [[ "$RESPONSE" == *"403"* ]]; then - edit_msg "$CHAT_ID" "$MSG_ID" "⛔ **安全拦截**:该节点已物理切断 OTA 升级通道 (ALLOW_OTA=false)。" - else - edit_msg "$CHAT_ID" "$MSG_ID" "❌ 通讯超时或节点离线。" - fi - fi + # 【核心升级】排版为 4 行 2 列,加入“修改备注”按钮 + BTNS="[[{\"text\":\"📍 Google 纠偏\",\"callback_data\":\"google:$TARGET_NODE\"}, {\"text\":\"🛡️ 信用净化\",\"callback_data\":\"trust:$TARGET_NODE\"}], [{\"text\":\"📜 实时日志\",\"callback_data\":\"log:$TARGET_NODE\"}, {\"text\":\"📊 统计战报\",\"callback_data\":\"report:$TARGET_NODE\"}], [{\"text\":\"✏️ 修改节点备注\",\"callback_data\":\"rename:$TARGET_NODE\"}, {\"text\":\"🗑️ 剔除失联节点\",\"callback_data\":\"del:$TARGET_NODE\"}], [{\"text\":\"⬅️ 返回大区目录\",\"callback_data\":\"list_nodes\"}]]" + send_ui "$CHAT_ID" "⚙️ **目标锁定**: \`$TARGET_ALIAS\`\n*(身份标识: $TARGET_NODE)*\n请选择战术动作:" "$BTNS" ;; del:*)