From 52b12c7057bc7fc47349c2615e0c8d0347d080f3 Mon Sep 17 00:00:00 2001 From: hotyue <52734432+hotyue@users.noreply.github.com> Date: Fri, 17 Apr 2026 01:19:27 +0000 Subject: [PATCH] =?UTF-8?q?feat(master):=20[v3.6.0]=20=E6=B7=B1=E5=BA=A6?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=B8=AD=E6=9E=A2=E8=B0=83=E5=BA=A6=EF=BC=8C?= =?UTF-8?q?=E5=BC=95=E5=85=A5L5=E9=99=8D=E7=BB=B4=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E3=80=81=E7=BA=A2=E7=BB=BF=E7=81=AF=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=90=AF=E5=81=9C=E4=B8=8E=E5=85=A8=E7=BD=91=20OTA=20?= =?UTF-8?q?=E9=9D=99=E9=BB=98=E5=8D=87=E7=BA=A7=20(Resolves=20#17,=20Resol?= =?UTF-8?q?ves=20#19)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- master/tg_master.sh | 153 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 147 insertions(+), 6 deletions(-) diff --git a/master/tg_master.sh b/master/tg_master.sh index 154482e..e80ab8e 100755 --- a/master/tg_master.sh +++ b/master/tg_master.sh @@ -36,6 +36,13 @@ edit_msg() { -d "chat_id=$1" -d "message_id=$2" -d "text=$3" -d "parse_mode=Markdown" > /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" @@ -60,10 +67,12 @@ generate_signed_url() { } # ======================================================================== -# ================== [v3.1.3/v3.5.2 核心: 数据库结构无损热升级] ================== -# 自动探测并增加 region 与 node_alias 字段,屏蔽已存在的报错,保护老节点数据 +# ================== [v3.1.3/v3.6.0 核心: 数据库结构无损热升级] ================== +# 自动探测并增加缺失字段,屏蔽已存在的报错,保护老节点数据 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 # ======================================================================== # --- 核心轮询循环 --- @@ -184,10 +193,38 @@ while true; do VER_INFO="${VER_INFO}\n✨ **发现新版本**: \`v${REMOTE_VER}\` (请尽快更新主控)" fi - BTNS="[[{\"text\":\"🖥️ 我的节点列表\",\"callback_data\":\"list_nodes\"}], [{\"text\":\"🚀 全节点日报汇总\",\"callback_data\":\"all_reports\"}], [{\"text\":\"🛠️ 全节点一键维护\",\"callback_data\":\"all_run\"}]]" + # [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]" + 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 @@ -283,9 +320,113 @@ 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" - # 【核心升级】排版为 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" + # [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 ;; del:*)