feat(telegram): выбор секции прокси для Telegram-бота + фикс краша при null cb.from

- get_proxy_args() теперь поддерживает опцию UCI bot_proxy_section:
  если sing-box запущен и секция указана, переключает GLOBAL outbound через REST API
- Исправлен краш 'left-hand side expression is null' при обработке
  callback_query без поля from (например channel_post callbacks)
- В LuCI settings.js добавлен ListValue 'bot_proxy_section' с выпадающим
  списком активных секций (паттерн аналогичен download_via_proxy_section)
- Локализация: ru/tachyon.po и templates/tachyon.pot синхронизированы
- Пересборка main.js через npm run build
This commit is contained in:
Dushnilin
2026-08-09 22:34:06 +03:00
parent 26d67506a4
commit 90980917e4
4 changed files with 73 additions and 1 deletions
@@ -1664,6 +1664,43 @@ function createTelegramContent(section) {
o.retain = true;
o.default = "1";
o.rmempty = false;
o = section.option(
form.ListValue,
"bot_proxy_section",
_("Proxy Section for Bot"),
_("Route bot API requests through this section. Leave empty to use the default mixed proxy."),
);
o.depends("enabled", "1");
o.retain = true;
o.default = "";
o.rmempty = true;
o.value("", _("Default (auto)"));
o.load = function (section_id) {
const sections = this.map?.data?.state?.values?.[UCI_PACKAGE] ?? {};
for (const secName in sections) {
const sec = sections[secName];
if (
sec[".type"] === "section" &&
sec.enabled !== "0" &&
isDownloadSectionAction(sec.action, null)
) {
this.value(secName, sec.label || secName);
}
}
return uci.get(UCI_PACKAGE, "telegram", "bot_proxy_section") || "";
};
o.write = function (_section_id, value) {
const normalized = value ? `${value}`.trim() : "";
if (normalized) {
uci.set(UCI_PACKAGE, "telegram", "bot_proxy_section", normalized);
} else {
uci.unset(UCI_PACKAGE, "telegram", "bot_proxy_section");
}
};
o.remove = function () {
uci.unset(UCI_PACKAGE, "telegram", "bot_proxy_section");
};
}
const EntryPoint = {
+9
View File
@@ -1928,6 +1928,15 @@ msgstr "Уведомлять о сбоях ядра"
msgid "Notify on DNS Leaks"
msgstr "Уведомлять об утечках DNS"
msgid "Default (auto)"
msgstr "По умолчанию (авто)"
msgid "Proxy Section for Bot"
msgstr "Секция прокси для бота"
msgid "Route bot API requests through this section. Leave empty to use the default mixed proxy."
msgstr "Направлять запросы бота к Telegram API через эту секцию. Оставьте пустым для использования стандартного прокси."
msgid "Notify on Server Switches"
msgstr "Уведомлять о переключениях серверов"
+12
View File
@@ -2769,6 +2769,18 @@ msgstr ""
msgid "Notify on DNS Leaks"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:1682
msgid "Default (auto)"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:1669
msgid "Proxy Section for Bot"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:1670
msgid "Route bot API requests through this section. Leave empty to use the default mixed proxy."
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:1621
msgid "Notify on Server Switches"
msgstr ""
+15 -1
View File
@@ -106,6 +106,19 @@ function settings() {
function get_proxy_args() {
let cfg = settings();
if (command_success_from_args(["pidof", "sing-box"])) {
// If a specific section is configured for the bot, force-select it
// through the Mihomo REST API so the mixed proxy routes bot traffic
// through the right outbound.
let bot_section = cfg.bot_proxy_section ? trim(cfg.bot_proxy_section) : "";
if (bot_section != "") {
let tag = bot_section + "-out";
command_capture(command_from_args([
"curl", "-s", "-X", "PUT",
"-H", "Content-Type: application/json",
"-d", sprintf("%J", { name: tag }),
"http://127.0.0.1:9090/proxies/GLOBAL"
]));
}
return [ "--proxy", "http://127.0.0.1:4534" ];
}
if (cfg.fallback_socks && trim(cfg.fallback_socks) != "") {
@@ -2316,7 +2329,8 @@ function process_updates(token, admin_ids) {
try {
let cb = upd.callback_query;
if (cb) {
let chat_id = cb.message ? cb.message.chat.id : cb.from.id;
let chat_id = cb.message ? cb.message.chat.id : (cb.from ? cb.from.id : null);
if (!chat_id) continue;
if (!is_admin(chat_id, admin_ids)) {
tg_request(token, "answerCallbackQuery", { callback_query_id: cb.id, text: "Access Denied" });
continue;