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": "Tanpa kedaluwarsa",
|
||||
"copyAllConfigs": "Salin Semua Konfigurasi",
|
||||
"copyAllConfigsCopied": "Semua konfigurasi tersalin",
|
||||
"email": "Email"
|
||||
"email": "Email",
|
||||
"individualLinks": "Tautan individual"
|
||||
},
|
||||
"menu": {
|
||||
"theme": "Tema",
|
||||
@@ -1168,7 +1169,44 @@
|
||||
"httpMethodDesc": "Metode yang dipakai untuk permintaan probe.",
|
||||
"note": "Penyeimbang leastPing/leastLoad selalu membawa burstObservatory. Sakelar ini menyesuaikan parameter probe-nya — matikan untuk memakai bawaan default. Perubahan berlaku setelah panel dimulai ulang."
|
||||
}
|
||||
}
|
||||
},
|
||||
"TGBotSettings": "Bot Telegram",
|
||||
"notifications": "Notifikasi",
|
||||
"notifyTime": {
|
||||
"custom": "Kustom (crontab)",
|
||||
"daily": "@daily — setiap hari pukul 00:00",
|
||||
"every": "@every — ulangi dalam interval",
|
||||
"hourly": "@hourly — setiap jam",
|
||||
"hours": "Jam",
|
||||
"interval": "Interval",
|
||||
"minutes": "Menit",
|
||||
"monthly": "@monthly — setiap bulan",
|
||||
"seconds": "Detik",
|
||||
"unit": "Satuan",
|
||||
"weekly": "@weekly — setiap minggu"
|
||||
},
|
||||
"telegramAPIServer": "Server API Telegram",
|
||||
"telegramAPIServerDesc": "Server API Telegram yang akan digunakan. Biarkan kosong untuk menggunakan server default.",
|
||||
"telegramBotEnable": "Aktifkan Bot Telegram",
|
||||
"telegramBotEnableDesc": "Mengaktifkan bot Telegram.",
|
||||
"telegramBotLanguage": "Bahasa Bot Telegram",
|
||||
"telegramChatId": "ID Obrolan Admin",
|
||||
"telegramChatIdDesc": "ID Obrolan Admin Telegram. (dipisahkan koma)(dapatkan di sini {'@'}userinfobot) atau (gunakan perintah '/id' di bot)",
|
||||
"telegramNotifyTime": "Waktu Notifikasi",
|
||||
"telegramNotifyTimeDesc": "Seberapa sering bot Telegram mengirim laporan berkala. Pilih interval siap pakai, atau pilih Kustom untuk memasukkan ekspresi crontab.",
|
||||
"telegramToken": "Token Telegram",
|
||||
"telegramTokenConfigured": "Terkonfigurasi; kosongkan untuk mempertahankan token saat ini.",
|
||||
"telegramTokenDesc": "Token bot Telegram yang diperoleh dari '{'@'}BotFather'.",
|
||||
"telegramTokenPlaceholder": "Terkonfigurasi - masukkan token baru untuk mengganti",
|
||||
"testTgBot": "Kirim Pesan Uji",
|
||||
"tgBotNotEnabled": "Bot Telegram tidak aktif",
|
||||
"tgBotNotRunning": "Bot Telegram tidak berjalan",
|
||||
"tgEventBusNotify": "Notifikasi Peristiwa Telegram",
|
||||
"tgEventBusNotifyDesc": "Pilih peristiwa yang memicu notifikasi Telegram",
|
||||
"tgNotifyBackup": "Cadangan Database",
|
||||
"tgNotifyBackupDesc": "Kirim berkas cadangan database dengan laporan.",
|
||||
"tgTestFailed": "Uji Telegram gagal",
|
||||
"tgTestSuccess": "Pesan uji terkirim ke Telegram"
|
||||
},
|
||||
"xray": {
|
||||
"save": "Simpan",
|
||||
@@ -1657,7 +1695,182 @@
|
||||
}
|
||||
},
|
||||
"tgbot": {
|
||||
"noIpRecord": "❗ Tidak ada Catatan IP!"
|
||||
"noIpRecord": "❗ Tidak ada Catatan IP!",
|
||||
"keyboardClosed": "❌ Keyboard ditutup!",
|
||||
"noResult": "❗ Tidak ada hasil!",
|
||||
"noQuery": "❌ Kueri tidak ditemukan! Silakan gunakan perintah lagi!",
|
||||
"wentWrong": "❌ Terjadi kesalahan!",
|
||||
"noInbounds": "❗ Tidak ada inbound yang ditemukan!",
|
||||
"unlimited": "♾ Tidak terbatas (Reset)",
|
||||
"add": "Tambah",
|
||||
"month": "Bulan",
|
||||
"months": "Bulan",
|
||||
"days": "Hari",
|
||||
"hours": "Jam",
|
||||
"minutes": "Menit",
|
||||
"unknown": "Tidak diketahui",
|
||||
"inbounds": "Inbound",
|
||||
"clients": "Klien",
|
||||
"offline": "🔴 Offline",
|
||||
"online": "🟢 Online",
|
||||
"commands": {
|
||||
"unknown": "❗ Perintah tidak dikenal.",
|
||||
"pleaseChoose": "👇 Harap pilih:\r\n",
|
||||
"help": "🤖 Selamat datang di bot ini! Ini dirancang untuk menyediakan data tertentu dari panel web dan memungkinkan Anda melakukan modifikasi sesuai kebutuhan.\r\n\r\n",
|
||||
"start": "👋 Halo <i>{{ .Firstname }}</i>.\r\n",
|
||||
"welcome": "🤖 Selamat datang di <b>{{.Hostname }}</b> bot managemen.\r\n",
|
||||
"status": "✅ Bot dalam keadaan baik!",
|
||||
"usage": "❗ Harap berikan teks untuk mencari!",
|
||||
"getID": "🆔 ID Anda: <code>{{ .ID }}</code>",
|
||||
"helpAdminCommands": "Untuk memulai ulang Xray Core:\r\n<code>/restart</code>\r\n\r\nUntuk mencari email klien:\r\n<code>/usage [Email]</code>\r\n\r\nUntuk mencari inbound (dengan statistik klien):\r\n<code>/inbound [Catatan]</code>\r\n\r\nID Obrolan Telegram:\r\n<code>/id</code>",
|
||||
"helpClientCommands": "Untuk mencari statistik, gunakan perintah berikut:\r\n<code>/usage [Email]</code>\r\n\r\nID Obrolan Telegram:\r\n<code>/id</code>",
|
||||
"restartUsage": "\r\n\r\n<code>/restart</code>",
|
||||
"restartSuccess": "✅ Operasi berhasil!",
|
||||
"restartFailed": "❗ Kesalahan dalam operasi.\r\n\r\n<code>Error: {{ .Error }}</code>.",
|
||||
"xrayNotRunning": "❗ Xray Core tidak berjalan.",
|
||||
"startDesc": "Tampilkan menu utama",
|
||||
"helpDesc": "Bantuan bot",
|
||||
"statusDesc": "Periksa status bot",
|
||||
"idDesc": "Tampilkan ID Telegram Anda",
|
||||
"usageDesc": "Lihat pemakaian klien: /usage email",
|
||||
"inboundDesc": "Cari inbound: /inbound nama (admin)",
|
||||
"restartDesc": "Mulai ulang inti Xray (admin)",
|
||||
"clearallDesc": "Reset trafik semua klien (admin)"
|
||||
},
|
||||
"messages": {
|
||||
"cpuThreshold": "Beban CPU {{ .Percent }}% melebihi batas {{ .Threshold }}%",
|
||||
"selectUserFailed": "❌ Kesalahan dalam pemilihan pengguna!",
|
||||
"userSaved": "✅ Pengguna Telegram tersimpan.",
|
||||
"loginSuccess": "✅ Berhasil masuk ke panel.\r\n",
|
||||
"loginFailed": "❗️ Gagal masuk ke panel.\r\n",
|
||||
"report": "🕰 Laporan Terjadwal: {{ .RunTime }}\r\n",
|
||||
"datetime": "⏰ Tanggal & Waktu: {{ .DateTime }}\r\n",
|
||||
"hostname": "💻 Host: {{ .Hostname }}\r\n",
|
||||
"version": "🚀 Versi 3X-UI: {{ .Version }}\r\n",
|
||||
"xrayVersion": "📡 Versi Xray: {{ .XrayVersion }}\r\n",
|
||||
"ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
|
||||
"ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
|
||||
"ip": "🌐 IP: {{ .IP }}\r\n",
|
||||
"ips": "🔢 IP:\r\n{{ .IPs }}\r\n",
|
||||
"serverUpTime": "⏳ Waktu Aktif: {{ .UpTime }} {{ .Unit }}\r\n",
|
||||
"serverLoad": "📈 Beban Sistem: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
|
||||
"serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
|
||||
"tcpCount": "🔹 TCP: {{ .Count }}\r\n",
|
||||
"udpCount": "🔸 UDP: {{ .Count }}\r\n",
|
||||
"traffic": "🚦 Lalu Lintas: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
|
||||
"xrayStatus": "ℹ️ Status: {{ .State }}\r\n",
|
||||
"username": "👤 Nama Pengguna: {{ .Username }}\r\n",
|
||||
"reason": "❗️ Alasan: {{ .Reason }}\r\n",
|
||||
"time": "⏰ Waktu: {{ .Time }}\r\n",
|
||||
"inbound": "📍 Inbound: {{ .Remark }}\r\n",
|
||||
"port": "🔌 Port: {{ .Port }}\r\n",
|
||||
"expire": "📅 Tanggal Kadaluarsa: {{ .Time }}\r\n",
|
||||
"expireIn": "📅 Kadaluarsa Dalam: {{ .Time }}\r\n",
|
||||
"active": "💡 Aktif: {{ .Enable }}\r\n",
|
||||
"enabled": "🚨 Diaktifkan: {{ .Enable }}\r\n",
|
||||
"online": "🌐 Status Koneksi: {{ .Status }}\r\n",
|
||||
"lastOnline": "🔙 Terakhir online: {{ .Time }}\r\n",
|
||||
"email": "📧 Email: {{ .Email }}\r\n",
|
||||
"upload": "🔼 Unggah: ↑{{ .Upload }}\r\n",
|
||||
"download": "🔽 Unduh: ↓{{ .Download }}\r\n",
|
||||
"total": "📊 Total: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
|
||||
"TGUser": "👤 Pengguna Telegram: {{ .TelegramID }}\r\n",
|
||||
"exhaustedCount": "🚨 Jumlah Habis {{ .Type }}:\r\n",
|
||||
"onlinesCount": "🌐 Klien Online: {{ .Count }}\r\n",
|
||||
"disabled": "🛑 Dinonaktifkan: {{ .Disabled }}\r\n",
|
||||
"depleteSoon": "🔜 Habis Sebentar: {{ .Deplete }}\r\n\r\n",
|
||||
"backupTime": "🗄 Waktu Backup: {{ .Time }}\r\n",
|
||||
"refreshedOn": "\r\n📋🔄 Diperbarui Pada: {{ .Time }}\r\n\r\n",
|
||||
"yes": "✅ Ya",
|
||||
"no": "❌ Tidak",
|
||||
"received_email": "📧📥 Email diperbarui.",
|
||||
"received_comment": "💬📥 Komentar diperbarui.",
|
||||
"email_prompt": "📧 Email Default: {{ .ClientEmail }}\n\nMasukkan email Anda.",
|
||||
"comment_prompt": "💬 Komentar Default: {{ .ClientComment }}\n\nMasukkan komentar Anda.",
|
||||
"cancel": "❌ Proses Dibatalkan! \n\nAnda dapat /start lagi kapan saja. 🔄",
|
||||
"error_add_client": "⚠️ Error:\n\n {{ .error }}",
|
||||
"using_default_value": "Oke, saya akan tetap menggunakan nilai default. 😊",
|
||||
"incorrect_input": "Masukan Anda tidak valid.\nFrasa harus berlanjut tanpa spasi.\nContoh benar: aaaaaa\nContoh salah: aaa aaa 🚫",
|
||||
"AreYouSure": "Apakah kamu yakin? 🤔",
|
||||
"SuccessResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Hasil: ✅ Berhasil",
|
||||
"FailedResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Hasil: ❌ Gagal \n\n🛠️ Kesalahan: [ {{ .ErrorMessage }} ]",
|
||||
"FinishProcess": "🔚 Proses reset traffic selesai untuk semua klien.",
|
||||
"eventOutboundDown": "Outbound {{ .Tag }} MATI",
|
||||
"eventOutboundUp": "Outbound {{ .Tag }} AKTIF",
|
||||
"eventErrorDetail": "Kesalahan: {{ .Error }}",
|
||||
"eventDelayDetail": "Penundaan: {{ .Delay }}ms",
|
||||
"eventXrayCrash": "Xray CRASH",
|
||||
"eventXrayCrashError": "Kesalahan: {{ .Error }}",
|
||||
"eventNodeDown": "Node {{ .Name }} MATI",
|
||||
"eventNodeUp": "Node {{ .Name }} AKTIF",
|
||||
"eventLoginFallback": "Gagal masuk dari {{ .Source }}",
|
||||
"memoryThreshold": "Penggunaan memori {{ .Percent }}% melebihi ambang batas {{ .Threshold }}%"
|
||||
},
|
||||
"buttons": {
|
||||
"closeKeyboard": "❌ Tutup Papan Ketik",
|
||||
"cancel": "❌ Batal",
|
||||
"cancelReset": "❌ Batal Reset",
|
||||
"cancelIpLimit": "❌ Batal Batas IP",
|
||||
"confirmResetTraffic": "✅ Konfirmasi Reset Lalu Lintas?",
|
||||
"confirmClearIps": "✅ Konfirmasi Hapus IPs?",
|
||||
"confirmRemoveTGUser": "✅ Konfirmasi Hapus Pengguna Telegram?",
|
||||
"confirmToggle": "✅ Konfirmasi Aktifkan/Nonaktifkan Pengguna?",
|
||||
"dbBackup": "Dapatkan Cadangan DB",
|
||||
"serverUsage": "Penggunaan Server",
|
||||
"getInbounds": "Dapatkan Inbounds",
|
||||
"depleteSoon": "Habis Sebentar",
|
||||
"clientUsage": "Dapatkan Penggunaan",
|
||||
"onlines": "Klien Online",
|
||||
"commands": "Perintah",
|
||||
"refresh": "🔄 Perbarui",
|
||||
"clearIPs": "❌ Hapus IPs",
|
||||
"removeTGUser": "❌ Hapus Pengguna Telegram",
|
||||
"selectTGUser": "👤 Pilih Pengguna Telegram",
|
||||
"selectOneTGUser": "👤 Pilih Pengguna Telegram:",
|
||||
"resetTraffic": "📈 Reset Lalu Lintas",
|
||||
"resetExpire": "📅 Ubah Tanggal Kadaluarsa",
|
||||
"ipLog": "🔢 Log IP",
|
||||
"ipLimit": "🔢 Batas IP",
|
||||
"setTGUser": "👤 Set Pengguna Telegram",
|
||||
"toggle": "🔘 Aktifkan / Nonaktifkan",
|
||||
"custom": "🔢 Kustom",
|
||||
"confirmNumber": "✅ Konfirmasi: {{ .Num }}",
|
||||
"confirmNumberAdd": "✅ Konfirmasi menambahkan: {{ .Num }}",
|
||||
"limitTraffic": "🚧 Batas Lalu Lintas",
|
||||
"getBanLogs": "Dapatkan Log Pemblokiran",
|
||||
"allClients": "Semua Klien",
|
||||
"addClient": "Tambah Klien",
|
||||
"submitDisable": "Kirim Sebagai Nonaktif ☑️",
|
||||
"submitEnable": "Kirim Sebagai Aktif ✅",
|
||||
"use_default": "🏷️ Gunakan Default",
|
||||
"change_email": "⚙️📧 Email",
|
||||
"change_comment": "⚙️💬 Komentar",
|
||||
"ResetAllTraffics": "Reset Semua Lalu Lintas",
|
||||
"SortedTrafficUsageReport": "Laporan Penggunaan Lalu Lintas yang Terurut"
|
||||
},
|
||||
"answers": {
|
||||
"successfulOperation": "✅ Operasi berhasil!",
|
||||
"errorOperation": "❗ Kesalahan dalam operasi.",
|
||||
"getInboundsFailed": "❌ Gagal mendapatkan inbounds.",
|
||||
"getClientsFailed": "❌ Gagal mendapatkan klien.",
|
||||
"canceled": "❌ {{ .Email }}: Operasi dibatalkan.",
|
||||
"clientRefreshSuccess": "✅ {{ .Email }}: Klien diperbarui dengan berhasil.",
|
||||
"IpRefreshSuccess": "✅ {{ .Email }}: IP diperbarui dengan berhasil.",
|
||||
"TGIdRefreshSuccess": "✅ {{ .Email }}: Pengguna Telegram Klien diperbarui dengan berhasil.",
|
||||
"resetTrafficSuccess": "✅ {{ .Email }}: Lalu lintas direset dengan berhasil.",
|
||||
"setTrafficLimitSuccess": "✅ {{ .Email }}: Batas lalu lintas disimpan dengan berhasil.",
|
||||
"expireResetSuccess": "✅ {{ .Email }}: Hari kadaluarsa direset dengan berhasil.",
|
||||
"resetIpSuccess": "✅ {{ .Email }}: Batas IP {{ .Count }} disimpan dengan berhasil.",
|
||||
"clearIpSuccess": "✅ {{ .Email }}: IP dihapus dengan berhasil.",
|
||||
"getIpLog": "✅ {{ .Email }}: Dapatkan Log IP.",
|
||||
"getUserInfo": "✅ {{ .Email }}: Dapatkan Info Pengguna Telegram.",
|
||||
"removedTGUserSuccess": "✅ {{ .Email }}: Pengguna Telegram dihapus dengan berhasil.",
|
||||
"enableSuccess": "✅ {{ .Email }}: Diaktifkan dengan berhasil.",
|
||||
"disableSuccess": "✅ {{ .Email }}: Dinonaktifkan dengan berhasil.",
|
||||
"askToAddUserId": "Konfigurasi Anda tidak ditemukan!\r\nSilakan minta admin Anda untuk menggunakan ChatID Telegram Anda dalam konfigurasi Anda.\r\n\r\nChatID Pengguna Anda: <code>{{ .TgUserID }}</code>",
|
||||
"chooseClient": "Pilih Klien untuk Inbound {{ .Inbound }}",
|
||||
"chooseInbound": "Pilih Inbound"
|
||||
}
|
||||
},
|
||||
"email": {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user