fix: исправление подвисания Telegram бота и ошибок AI Watchdog
- telegram.uc: добавлены таймауты --max-time 35 и --connect-timeout 10 для всех запросов curl, ограничение длины сообщений до 3900 символов (предотвращение 400 Bad Request от Telegram API), безопасная обработка callback_query в try...catch с гарантированным вызовом answerCallbackQuery, защита основного цикла worker от падений при сбоях сети - api.uc: добавлены таймауты --max-time и --connect-timeout для всех curl вызовов, устраняющие зависание подпроцессов при опросе Clash API и проверках соединения через прокси - watchdog.uc: добавлена функция safe_reload_firewall, устранившая ошибки 'left-hand side is not a function' в процессах ai_heal_nftables и ai_heal_qos
This commit is contained in:
@@ -53,7 +53,7 @@ function process_running_by_pidfile(pidfile) {
|
||||
}
|
||||
|
||||
function get_clash_proxies_data() {
|
||||
let args = [ "curl", "-s", get_clash_url("proxies") ];
|
||||
let args = [ "curl", "-s", "-m", "5", "--connect-timeout", "3", get_clash_url("proxies") ];
|
||||
let res = command_capture(command_from_args(args));
|
||||
if (res && res.status == 0 && res.output != "") {
|
||||
try {
|
||||
@@ -154,7 +154,7 @@ function clash_request(method, endpoint, payload) {
|
||||
let payload_path = "/tmp/clash_payload_" + method + "_" + time() + "_" + sprintf("%04x", int(Math.random() * 65536)) + ".json";
|
||||
let res = null;
|
||||
try {
|
||||
let args = [ "curl", "-s", "-X", method ];
|
||||
let args = [ "curl", "-s", "-m", "5", "--connect-timeout", "3", "-X", method ];
|
||||
if (payload) {
|
||||
fs.writefile(payload_path, sprintf("%J", payload));
|
||||
push(args, "-H", "Content-Type: application/json", "-d", "@" + payload_path);
|
||||
@@ -186,7 +186,7 @@ function clash_request(method, endpoint, payload) {
|
||||
}
|
||||
|
||||
function get_clash_connections() {
|
||||
let args = [ "curl", "-s", get_clash_url("connections") ];
|
||||
let args = [ "curl", "-s", "-m", "5", "--connect-timeout", "3", get_clash_url("connections") ];
|
||||
let res = command_capture(command_from_args(args));
|
||||
if (res && res.status == 0 && res.output != "") {
|
||||
try {
|
||||
@@ -197,24 +197,24 @@ function get_clash_connections() {
|
||||
}
|
||||
|
||||
function check_connection() {
|
||||
let res_direct = command_capture("curl -I -s --connect-timeout 5 https://www.google.com");
|
||||
let direct_ok = (res_direct.status == 0) ? true : false;
|
||||
let res_direct = command_capture("curl -I -s -m 8 --connect-timeout 4 https://www.google.com");
|
||||
let direct_ok = (res_direct && res_direct.status == 0) ? true : false;
|
||||
|
||||
let res_proxy = command_capture("curl -I -s --connect-timeout 5 --proxy http://127.0.0.1:4534 https://www.google.com");
|
||||
let proxy_ok = (res_proxy.status == 0) ? true : false;
|
||||
let res_proxy = command_capture("curl -I -s -m 8 --connect-timeout 4 --proxy http://127.0.0.1:4534 https://www.google.com");
|
||||
let proxy_ok = (res_proxy && res_proxy.status == 0) ? true : false;
|
||||
|
||||
return { direct: direct_ok, proxy: proxy_ok };
|
||||
}
|
||||
|
||||
function run_speedtest() {
|
||||
// Direct speedtest
|
||||
let res_direct = command_capture("curl -s -w '%{speed_download}' -o /dev/null --connect-timeout 8 https://speed.cloudflare.com/__down?bytes=5242880");
|
||||
let direct_speed = double(res_direct.output || 0);
|
||||
let res_direct = command_capture("curl -s -m 15 --connect-timeout 6 -w '%{speed_download}' -o /dev/null https://speed.cloudflare.com/__down?bytes=5242880");
|
||||
let direct_speed = double(res_direct ? res_direct.output || 0 : 0);
|
||||
let direct_mbps = (direct_speed * 8) / 1000000;
|
||||
|
||||
// Proxy speedtest
|
||||
let res_proxy = command_capture("curl -s -w '%{speed_download}' -o /dev/null --connect-timeout 8 --proxy http://127.0.0.1:4534 https://speed.cloudflare.com/__down?bytes=5242880");
|
||||
let proxy_speed = double(res_proxy.output || 0);
|
||||
let res_proxy = command_capture("curl -s -m 15 --connect-timeout 6 --proxy http://127.0.0.1:4534 -w '%{speed_download}' -o /dev/null https://speed.cloudflare.com/__down?bytes=5242880");
|
||||
let proxy_speed = double(res_proxy ? res_proxy.output || 0 : 0);
|
||||
let proxy_mbps = (proxy_speed * 8) / 1000000;
|
||||
|
||||
return { direct_mbps: direct_mbps, proxy_mbps: proxy_mbps };
|
||||
|
||||
@@ -48,7 +48,7 @@ function tg_request(token, method, payload) {
|
||||
let res = null;
|
||||
try {
|
||||
fs.writefile(payload_path, sprintf("%J", payload));
|
||||
let args = [ "curl", "-s", "-X", "POST", "-H", "Content-Type: application/json", "-d", "@" + payload_path ];
|
||||
let args = [ "curl", "-s", "-m", "35", "--connect-timeout", "10", "-X", "POST", "-H", "Content-Type: application/json", "-d", "@" + payload_path ];
|
||||
let proxy = get_proxy_args();
|
||||
for (let p in proxy) push(args, p);
|
||||
push(args, url);
|
||||
@@ -64,6 +64,8 @@ function tg_request(token, method, payload) {
|
||||
}
|
||||
|
||||
function send_message(token, chat_id, text, parse_mode, keyboard) {
|
||||
text = as_string(text);
|
||||
if (length(text) > 3900) text = substr(text, 0, 3900) + "\n... (сообщение сокращено)";
|
||||
let payload = { chat_id: int(chat_id), text: text };
|
||||
if (parse_mode) payload.parse_mode = parse_mode;
|
||||
if (keyboard) payload.reply_markup = { inline_keyboard: keyboard };
|
||||
@@ -71,6 +73,8 @@ function send_message(token, chat_id, text, parse_mode, keyboard) {
|
||||
}
|
||||
|
||||
function edit_message(token, chat_id, message_id, text, parse_mode, keyboard) {
|
||||
text = as_string(text);
|
||||
if (length(text) > 3900) text = substr(text, 0, 3900) + "\n... (сообщение сокращено)";
|
||||
let payload = { chat_id: int(chat_id), message_id: int(message_id), text: text };
|
||||
if (parse_mode) payload.parse_mode = parse_mode;
|
||||
if (keyboard) payload.reply_markup = { inline_keyboard: keyboard };
|
||||
@@ -80,7 +84,7 @@ function edit_message(token, chat_id, message_id, text, parse_mode, keyboard) {
|
||||
function send_document(token, chat_id, file_path) {
|
||||
if (!token) return null;
|
||||
let url = "https://api.telegram.org/bot" + token + "/sendDocument";
|
||||
let args = [ "curl", "-s", "-X", "POST", "-F", "chat_id=" + chat_id, "-F", "document=@" + file_path ];
|
||||
let args = [ "curl", "-s", "-m", "60", "--connect-timeout", "10", "-X", "POST", "-F", "chat_id=" + chat_id, "-F", "document=@" + file_path ];
|
||||
let proxy = get_proxy_args();
|
||||
for (let p in proxy) push(args, p);
|
||||
push(args, url);
|
||||
@@ -913,8 +917,9 @@ function handle_sec_clear(token, chat_id, msg_id, sec_name, list_type) {
|
||||
|
||||
function exec_doctor(token, chat_id) {
|
||||
send_message(token, chat_id, "⏳ <b>Запуск диагностики и авто-исправления...</b>", "HTML");
|
||||
let res = command_capture("/usr/bin/tachyon doctor");
|
||||
let report = res.output || "Нет вывода диагностики.";
|
||||
let res = command_capture(command_from_args([ "/usr/bin/tachyon", "doctor" ]));
|
||||
let report = res ? (res.output || "Нет вывода диагностики.") : "Ошибка запуска диагностики.";
|
||||
if (length(report) > 3500) report = substr(report, 0, 3500) + "\n... (отчёт сокращён)";
|
||||
send_message(token, chat_id, "🩺 <b>Результаты Tachyon Doctor:</b>\n\n<pre>" + escape_html(report) + "</pre>", "HTML", [[{text:"⬅️ Назад", callback_data:"/menu"}]]);
|
||||
}
|
||||
|
||||
@@ -1655,8 +1660,9 @@ function exec_ai_heal(token, chat_id, msg_id) {
|
||||
|
||||
function exec_ai_status_full(token, chat_id, msg_id) {
|
||||
send_message(token, chat_id, "🔍 <b>Сбор полного AI Watchdog статуса...</b>", "HTML");
|
||||
let res = command_capture("/usr/bin/tachyon ai_status_full");
|
||||
let data = res.output || "Нет данных.";
|
||||
let res = command_capture(command_from_args([ "/usr/bin/tachyon", "ai_status_full" ]));
|
||||
let data = res ? (res.output || "Нет данных.") : "Ошибка получения статуса.";
|
||||
if (length(data) > 3500) data = substr(data, 0, 3500) + "\n... (данные сокращены)";
|
||||
let text = "🤖 <b>AI Watchdog — Полный статус:</b>\n\n<pre>" + escape_html(data) + "</pre>";
|
||||
let keyboard = [[{ text: "⬅️ Назад", callback_data: "/watchdog" }]];
|
||||
if (msg_id) edit_message(token, chat_id, msg_id, text, "HTML", keyboard);
|
||||
@@ -2059,7 +2065,11 @@ function process_updates(token, admin_ids) {
|
||||
tg_request(token, "answerCallbackQuery", { callback_query_id: cb.id, text: "Access Denied" });
|
||||
continue;
|
||||
}
|
||||
dispatch_command(token, chat_id, cb.data, cb.message ? cb.message.message_id : null);
|
||||
try {
|
||||
dispatch_command(token, chat_id, cb.data, cb.message ? cb.message.message_id : null);
|
||||
} catch (e) {
|
||||
send_message(token, chat_id, "❌ Ошибка выполнения команды: " + escape_html(as_string(e)), "HTML");
|
||||
}
|
||||
tg_request(token, "answerCallbackQuery", { callback_query_id: cb.id });
|
||||
continue;
|
||||
}
|
||||
@@ -2321,22 +2331,26 @@ function worker() {
|
||||
let last_update_check = 0;
|
||||
|
||||
while (true) {
|
||||
cfg = settings();
|
||||
if (cfg.enabled != "1") break;
|
||||
process_updates(cfg.bot_token, cfg.admin_ids);
|
||||
|
||||
let now = time();
|
||||
let tm = clock(now); // [year, mon, day, hour, min, sec]
|
||||
let daily_hour = int(cfg.daily_report_hour || "8");
|
||||
|
||||
if (cfg.daily_report_enabled == "1" && tm[3] == daily_hour && tm[2] != last_report_day) {
|
||||
last_report_day = tm[2];
|
||||
send_daily_digest(cfg.bot_token, cfg.admin_ids);
|
||||
}
|
||||
|
||||
if (now - last_update_check > 3600) { // check every hour
|
||||
check_notified_updates(cfg.bot_token, cfg.admin_ids);
|
||||
last_update_check = now;
|
||||
try {
|
||||
cfg = settings();
|
||||
if (cfg.enabled != "1") break;
|
||||
process_updates(cfg.bot_token, cfg.admin_ids);
|
||||
|
||||
let now = time();
|
||||
let tm = clock(now); // [year, mon, day, hour, min, sec]
|
||||
let daily_hour = int(cfg.daily_report_hour || "8");
|
||||
|
||||
if (cfg.daily_report_enabled == "1" && tm[3] == daily_hour && tm[2] != last_report_day) {
|
||||
last_report_day = tm[2];
|
||||
send_daily_digest(cfg.bot_token, cfg.admin_ids);
|
||||
}
|
||||
|
||||
if (now - last_update_check > 3600) { // check every hour
|
||||
check_notified_updates(cfg.bot_token, cfg.admin_ids);
|
||||
last_update_check = now;
|
||||
}
|
||||
} catch (e) {
|
||||
command_success_from_args(["logger", "-t", "tachyon-telegram", "[err] Worker loop error: " + as_string(e)]);
|
||||
}
|
||||
|
||||
sleep(poll_interval * 1000);
|
||||
|
||||
@@ -473,6 +473,10 @@ function safe_proxy_restart(reason) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function safe_reload_firewall() {
|
||||
bg_system("/usr/bin/tachyon reload_firewall </dev/null >/dev/null 2>&1 &");
|
||||
}
|
||||
|
||||
function ai_heal_nftables() {
|
||||
let cfg = settings();
|
||||
let routing_mode = cfg.routing_mode || "nftables";
|
||||
|
||||
Reference in New Issue
Block a user