P9(5): restore upstream Telegram bot (settings, backup, notifications)
Per user decision 2026-10-21 (reverses the 2026-10-20 drop-Telegram call): port the upstream 3x-ui v3.7.0-generation Telegram bot wholesale instead of rewriting a minimal set, adapted to this fork. - new internal/web/service/tgbot package (telego): bot lifecycle, commands, reports, callback router, send helpers; token validation via telego; custom API server URL passes the fork's SSRF sanitizer (loopback/private bases fall back to the default endpoint, logged) - settings: full upstream key set (tgBotEnable/Token/Proxy/APIServer/ ChatId, tgRunTime, tgBotBackup, tgCpu/tgMemory, tgLang, tgEnabledEvents) with getters/setters; settings page gains a Telegram tab + sidebar entry; token shown masked, clearTgBotToken honored - wiring (web.go): stats-notify cron registered from tgRunTime when the bot is enabled; CheckHashStorage job; CPU/memory alarm jobs gated on tgEnabledEvents + thresholds; login notifications via event bus; POST /panel/api/setting/testTgBot and /panel/api/backuptotgbot - lite adaptation: StatsNotifyJob no longer gates on a local Xray core (this panel never runs one) so the periodic report and the scheduled DB backup (sendDocument) can actually fire - translations: upstream TG keys restored across all locales End-to-end smoke (real binary + fake Telegram API over HTTPS at a public-looking address, browser form wire format): bot starts on settings change (getMe), testTgBot delivers, panel restart re-arms the bot, tgRunTime='@every 1m' cron really fires sendDocument carrying the panel SQLite DB (magic verified) plus the report sendMessage, login notification delivered, dead-endpoint failure is logged not silent. 13/13 PASS — see P9-REPORT.md.
This commit is contained in:
@@ -88,7 +88,8 @@
|
||||
"noExpiry": "Sem validade",
|
||||
"copyAllConfigs": "Copiar Todas as Configurações",
|
||||
"copyAllConfigsCopied": "Todas as configurações copiadas",
|
||||
"email": "Email"
|
||||
"email": "Email",
|
||||
"individualLinks": "Links individuais"
|
||||
},
|
||||
"menu": {
|
||||
"theme": "Tema",
|
||||
@@ -1168,7 +1169,44 @@
|
||||
"httpMethodDesc": "Método usado nas requisições de probe.",
|
||||
"note": "Balanceadores leastPing/leastLoad sempre carregam um burstObservatory. Esta opção personaliza seus parâmetros de probe — desligue-a para usar os padrões integrados. As alterações se aplicam após reiniciar o painel."
|
||||
}
|
||||
}
|
||||
},
|
||||
"TGBotSettings": "Bot do Telegram",
|
||||
"notifications": "Notificações",
|
||||
"notifyTime": {
|
||||
"custom": "Personalizado (crontab)",
|
||||
"daily": "@daily — todos os dias às 00:00",
|
||||
"every": "@every — repetir em um intervalo",
|
||||
"hourly": "@hourly — a cada hora",
|
||||
"hours": "Horas",
|
||||
"interval": "Intervalo",
|
||||
"minutes": "Minutos",
|
||||
"monthly": "@monthly — todo mês",
|
||||
"seconds": "Segundos",
|
||||
"unit": "Unidade",
|
||||
"weekly": "@weekly — toda semana"
|
||||
},
|
||||
"telegramAPIServer": "Servidor API do Telegram",
|
||||
"telegramAPIServerDesc": "O servidor API do Telegram a ser usado. Deixe em branco para usar o servidor padrão.",
|
||||
"telegramBotEnable": "Ativar Bot do Telegram",
|
||||
"telegramBotEnableDesc": "Ativa o bot do Telegram.",
|
||||
"telegramBotLanguage": "Idioma do Bot do Telegram",
|
||||
"telegramChatId": "ID de Chat do Administrador",
|
||||
"telegramChatIdDesc": "O(s) ID(s) de Chat do Administrador no Telegram. (separado por vírgulas)(obtenha aqui {'@'}userinfobot) ou (use o comando '/id' no bot)",
|
||||
"telegramNotifyTime": "Hora da Notificação",
|
||||
"telegramNotifyTimeDesc": "Com que frequência o bot do Telegram envia relatórios periódicos. Escolha um intervalo predefinido ou selecione Personalizado para inserir uma expressão crontab.",
|
||||
"telegramToken": "Token do Telegram",
|
||||
"telegramTokenConfigured": "Configurado; deixe em branco para manter o token atual.",
|
||||
"telegramTokenDesc": "O token do bot do Telegram obtido de '{'@'}BotFather'.",
|
||||
"telegramTokenPlaceholder": "Configurado - insira um novo token para substituir",
|
||||
"testTgBot": "Enviar mensagem de teste",
|
||||
"tgBotNotEnabled": "O bot do Telegram não está ativado",
|
||||
"tgBotNotRunning": "O bot do Telegram não está em execução",
|
||||
"tgEventBusNotify": "Notificações de eventos no Telegram",
|
||||
"tgEventBusNotifyDesc": "Selecione quais eventos disparam notificações no Telegram",
|
||||
"tgNotifyBackup": "Backup do Banco de Dados",
|
||||
"tgNotifyBackupDesc": "Enviar arquivo de backup do banco de dados junto com o relatório.",
|
||||
"tgTestFailed": "Falha no teste do Telegram",
|
||||
"tgTestSuccess": "Mensagem de teste enviada ao Telegram"
|
||||
},
|
||||
"xray": {
|
||||
"importRules": "Importar regras",
|
||||
@@ -1657,7 +1695,182 @@
|
||||
}
|
||||
},
|
||||
"tgbot": {
|
||||
"noIpRecord": "❗ Nenhum registro de IP!"
|
||||
"noIpRecord": "❗ Nenhum registro de IP!",
|
||||
"keyboardClosed": "❌ Teclado fechado!",
|
||||
"noResult": "❗ Nenhum resultado!",
|
||||
"noQuery": "❌ Consulta não encontrada! Por favor, use o comando novamente!",
|
||||
"wentWrong": "❌ Algo deu errado!",
|
||||
"noInbounds": "❗ Nenhum inbound encontrado!",
|
||||
"unlimited": "♾ Ilimitado (Reset)",
|
||||
"add": "Adicionar",
|
||||
"month": "Mês",
|
||||
"months": "Meses",
|
||||
"days": "Dias",
|
||||
"hours": "Horas",
|
||||
"minutes": "Minutos",
|
||||
"unknown": "Desconhecido",
|
||||
"inbounds": "Entradas",
|
||||
"clients": "Clientes",
|
||||
"offline": "🔴 Offline",
|
||||
"online": "🟢 Online",
|
||||
"commands": {
|
||||
"unknown": "❗ Comando desconhecido.",
|
||||
"pleaseChoose": "👇 Escolha:\r\n",
|
||||
"help": "🤖 Bem-vindo a este bot! Ele foi projetado para oferecer dados específicos do painel da web e permite que você faça as modificações necessárias.\r\n\r\n",
|
||||
"start": "👋 Olá <i>{{ .Firstname }}</i>.\r\n",
|
||||
"welcome": "🤖 Bem-vindo ao bot de gerenciamento do <b>{{ .Hostname }}</b>.\r\n",
|
||||
"status": "✅ Bot está OK!",
|
||||
"usage": "❗ Por favor, forneça um texto para pesquisar!",
|
||||
"getID": "🆔 Seu ID: <code>{{ .ID }}</code>",
|
||||
"helpAdminCommands": "Para reiniciar o Xray Core:\r\n<code>/restart</code>\r\n\r\nPara pesquisar por um email de cliente:\r\n<code>/usage [Email]</code>\r\n\r\nPara pesquisar por inbounds (com estatísticas do cliente):\r\n<code>/inbound [Remark]</code>\r\n\r\nTelegram Chat ID:\r\n<code>/id</code>",
|
||||
"helpClientCommands": "Para pesquisar por estatísticas, use o seguinte comando:\r\n\r\n<code>/usage [Email]</code>\r\n\r\nTelegram Chat ID:\r\n<code>/id</code>",
|
||||
"restartUsage": "\r\n\r\n<code>/restart</code>",
|
||||
"restartSuccess": "✅ Operação bem-sucedida!",
|
||||
"restartFailed": "❗ Erro na operação.\r\n\r\n<code>Erro: {{ .Error }}</code>.",
|
||||
"xrayNotRunning": "❗ Xray Core não está em execução.",
|
||||
"startDesc": "Mostrar menu principal",
|
||||
"helpDesc": "Ajuda do bot",
|
||||
"statusDesc": "Verificar status do bot",
|
||||
"idDesc": "Mostrar seu ID do Telegram",
|
||||
"usageDesc": "Ver o uso do cliente: /usage email",
|
||||
"inboundDesc": "Buscar entradas: /inbound nome (admin)",
|
||||
"restartDesc": "Reiniciar o núcleo Xray (admin)",
|
||||
"clearallDesc": "Zerar o tráfego de todos os clientes (admin)"
|
||||
},
|
||||
"messages": {
|
||||
"cpuThreshold": "A carga da CPU {{ .Percent }}% excede o limite de {{ .Threshold }}%",
|
||||
"selectUserFailed": "❌ Erro na seleção do usuário!",
|
||||
"userSaved": "✅ Usuário do Telegram salvo.",
|
||||
"loginSuccess": "✅ Conectado ao painel com sucesso.\r\n",
|
||||
"loginFailed": "❗️Tentativa de login no painel falhou.\r\n",
|
||||
"report": "🕰 Relatórios agendados: {{ .RunTime }}\r\n",
|
||||
"datetime": "⏰ Data&Hora: {{ .DateTime }}\r\n",
|
||||
"hostname": "💻 Host: {{ .Hostname }}\r\n",
|
||||
"version": "🚀 Versão 3X-UI: {{ .Version }}\r\n",
|
||||
"xrayVersion": "📡 Versão Xray: {{ .XrayVersion }}\r\n",
|
||||
"ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
|
||||
"ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
|
||||
"ip": "🌐 IP: {{ .IP }}\r\n",
|
||||
"ips": "🔢 IPs:\r\n{{ .IPs }}\r\n",
|
||||
"serverUpTime": "⏳ Tempo de atividade: {{ .UpTime }} {{ .Unit }}\r\n",
|
||||
"serverLoad": "📈 Carga do sistema: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
|
||||
"serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
|
||||
"tcpCount": "🔹 TCP: {{ .Count }}\r\n",
|
||||
"udpCount": "🔸 UDP: {{ .Count }}\r\n",
|
||||
"traffic": "🚦 Tráfego: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
|
||||
"xrayStatus": "ℹ️ Status: {{ .State }}\r\n",
|
||||
"username": "👤 Nome de usuário: {{ .Username }}\r\n",
|
||||
"reason": "❗️ Motivo: {{ .Reason }}\r\n",
|
||||
"time": "⏰ Hora: {{ .Time }}\r\n",
|
||||
"inbound": "📍 Entrada: {{ .Remark }}\r\n",
|
||||
"port": "🔌 Porta: {{ .Port }}\r\n",
|
||||
"expire": "📅 Data de expiração: {{ .Time }}\r\n",
|
||||
"expireIn": "📅 Expira em: {{ .Time }}\r\n",
|
||||
"active": "💡 Ativo: {{ .Enable }}\r\n",
|
||||
"enabled": "🚨 Ativado: {{ .Enable }}\r\n",
|
||||
"online": "🌐 Status da conexão: {{ .Status }}\r\n",
|
||||
"lastOnline": "🔙 Última vez online: {{ .Time }}\r\n",
|
||||
"email": "📧 Email: {{ .Email }}\r\n",
|
||||
"upload": "🔼 Upload: ↑{{ .Upload }}\r\n",
|
||||
"download": "🔽 Download: ↓{{ .Download }}\r\n",
|
||||
"total": "📊 Total: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
|
||||
"TGUser": "👤 Usuário do Telegram: {{ .TelegramID }}\r\n",
|
||||
"exhaustedCount": "🚨 Contagem de {{ .Type }} esgotado:\r\n",
|
||||
"onlinesCount": "🌐 Clientes online: {{ .Count }}\r\n",
|
||||
"disabled": "🛑 Desativado: {{ .Disabled }}\r\n",
|
||||
"depleteSoon": "🔜 Esgotar em breve: {{ .Deplete }}\r\n\r\n",
|
||||
"backupTime": "🗄 Hora do backup: {{ .Time }}\r\n",
|
||||
"refreshedOn": "\r\n📋🔄 Atualizado em: {{ .Time }}\r\n\r\n",
|
||||
"yes": "✅ Sim",
|
||||
"no": "❌ Não",
|
||||
"received_email": "📧📥 E-mail atualizado.",
|
||||
"received_comment": "💬📥 Comentário atualizado.",
|
||||
"email_prompt": "📧 E-mail Padrão: {{ .ClientEmail }}\n\nDigite seu e-mail.",
|
||||
"comment_prompt": "💬 Comentário Padrão: {{ .ClientComment }}\n\nDigite seu comentário.",
|
||||
"cancel": "❌ Processo Cancelado! \n\nVocê pode iniciar novamente a qualquer momento com /start. 🔄",
|
||||
"error_add_client": "⚠️ Erro:\n\n {{ .error }}",
|
||||
"using_default_value": "Tudo bem, vou manter o valor padrão. 😊",
|
||||
"incorrect_input": "Sua entrada não é válida.\nAs frases devem ser contínuas, sem espaços.\nExemplo correto: aaaaaa\nExemplo incorreto: aaa aaa 🚫",
|
||||
"AreYouSure": "Você tem certeza? 🤔",
|
||||
"SuccessResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Resultado: ✅ Sucesso",
|
||||
"FailedResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Resultado: ❌ Falhou \n\n🛠️ Erro: [ {{ .ErrorMessage }} ]",
|
||||
"FinishProcess": "🔚 Processo de redefinição de tráfego concluído para todos os clientes.",
|
||||
"eventOutboundDown": "O outbound {{ .Tag }} está INATIVO",
|
||||
"eventOutboundUp": "O outbound {{ .Tag }} está ATIVO",
|
||||
"eventErrorDetail": "Erro: {{ .Error }}",
|
||||
"eventDelayDetail": "Latência: {{ .Delay }}ms",
|
||||
"eventXrayCrash": "O Xray FALHOU",
|
||||
"eventXrayCrashError": "Erro: {{ .Error }}",
|
||||
"eventNodeDown": "O nó {{ .Name }} está INATIVO",
|
||||
"eventNodeUp": "O nó {{ .Name }} está ATIVO",
|
||||
"eventLoginFallback": "Falha de login a partir de {{ .Source }}",
|
||||
"memoryThreshold": "Uso de memória {{ .Percent }}% excede o limite de {{ .Threshold }}%"
|
||||
},
|
||||
"buttons": {
|
||||
"closeKeyboard": "❌ Fechar teclado",
|
||||
"cancel": "❌ Cancelar",
|
||||
"cancelReset": "❌ Cancelar redefinição",
|
||||
"cancelIpLimit": "❌ Cancelar limite de IP",
|
||||
"confirmResetTraffic": "✅ Confirmar redefinição de tráfego?",
|
||||
"confirmClearIps": "✅ Confirmar limpar IPs?",
|
||||
"confirmRemoveTGUser": "✅ Confirmar remover usuário do Telegram?",
|
||||
"confirmToggle": "✅ Confirmar ativar/desativar usuário?",
|
||||
"dbBackup": "Obter backup do DB",
|
||||
"serverUsage": "Uso do servidor",
|
||||
"getInbounds": "Obter Inbounds",
|
||||
"depleteSoon": "Esgotar em breve",
|
||||
"clientUsage": "Obter uso",
|
||||
"onlines": "Clientes online",
|
||||
"commands": "Comandos",
|
||||
"refresh": "🔄 Atualizar",
|
||||
"clearIPs": "❌ Limpar IPs",
|
||||
"removeTGUser": "❌ Remover usuário do Telegram",
|
||||
"selectTGUser": "👤 Selecionar usuário do Telegram",
|
||||
"selectOneTGUser": "👤 Selecione um usuário do Telegram:",
|
||||
"resetTraffic": "📈 Redefinir tráfego",
|
||||
"resetExpire": "📅 Alterar data de expiração",
|
||||
"ipLog": "🔢 Log de IP",
|
||||
"ipLimit": "🔢 Limite de IP",
|
||||
"setTGUser": "👤 Definir usuário do Telegram",
|
||||
"toggle": "🔘 Ativar / Desativar",
|
||||
"custom": "🔢 Personalizado",
|
||||
"confirmNumber": "✅ Confirmar: {{ .Num }}",
|
||||
"confirmNumberAdd": "✅ Confirmar adicionar: {{ .Num }}",
|
||||
"limitTraffic": "🚧 Limite de tráfego",
|
||||
"getBanLogs": "Obter logs de banimento",
|
||||
"allClients": "Todos os clientes",
|
||||
"addClient": "Adicionar Cliente",
|
||||
"submitDisable": "Enviar como Desativado ☑️",
|
||||
"submitEnable": "Enviar como Ativado ✅",
|
||||
"use_default": "🏷️ Usar padrão",
|
||||
"change_email": "⚙️📧 Email",
|
||||
"change_comment": "⚙️💬 Comentário",
|
||||
"ResetAllTraffics": "Redefinir Todo o Tráfego",
|
||||
"SortedTrafficUsageReport": "Relatório de Uso de Tráfego Ordenado"
|
||||
},
|
||||
"answers": {
|
||||
"successfulOperation": "✅ Operação bem-sucedida!",
|
||||
"errorOperation": "❗ Erro na operação.",
|
||||
"getInboundsFailed": "❌ Falha ao obter inbounds.",
|
||||
"getClientsFailed": "❌ Falha ao obter clientes.",
|
||||
"canceled": "❌ {{ .Email }}: Operação cancelada.",
|
||||
"clientRefreshSuccess": "✅ {{ .Email }}: Cliente atualizado com sucesso.",
|
||||
"IpRefreshSuccess": "✅ {{ .Email }}: IPs atualizados com sucesso.",
|
||||
"TGIdRefreshSuccess": "✅ {{ .Email }}: Usuário do Telegram do cliente atualizado com sucesso.",
|
||||
"resetTrafficSuccess": "✅ {{ .Email }}: Tráfego redefinido com sucesso.",
|
||||
"setTrafficLimitSuccess": "✅ {{ .Email }}: Limite de tráfego salvo com sucesso.",
|
||||
"expireResetSuccess": "✅ {{ .Email }}: Dias de expiração redefinidos com sucesso.",
|
||||
"resetIpSuccess": "✅ {{ .Email }}: Limite de IP {{ .Count }} salvo com sucesso.",
|
||||
"clearIpSuccess": "✅ {{ .Email }}: IPs limpos com sucesso.",
|
||||
"getIpLog": "✅ {{ .Email }}: Obter log de IP.",
|
||||
"getUserInfo": "✅ {{ .Email }}: Obter informações do usuário do Telegram.",
|
||||
"removedTGUserSuccess": "✅ {{ .Email }}: Usuário do Telegram removido com sucesso.",
|
||||
"enableSuccess": "✅ {{ .Email }}: Ativado com sucesso.",
|
||||
"disableSuccess": "✅ {{ .Email }}: Desativado com sucesso.",
|
||||
"askToAddUserId": "Sua configuração não foi encontrada!\r\nPeça ao seu administrador para usar seu Telegram ChatID em suas configurações.\r\n\r\nSeu ChatID: <code>{{ .TgUserID }}</code>",
|
||||
"chooseClient": "Escolha um cliente para Inbound {{ .Inbound }}",
|
||||
"chooseInbound": "Escolha um Inbound"
|
||||
}
|
||||
},
|
||||
"email": {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user