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": "بدون انتهاء",
|
||||
"copyAllConfigs": "نسخ جميع الإعدادات",
|
||||
"copyAllConfigsCopied": "تم نسخ جميع الإعدادات",
|
||||
"email": "البريد"
|
||||
"email": "البريد",
|
||||
"individualLinks": "روابط فردية"
|
||||
},
|
||||
"menu": {
|
||||
"theme": "الثيم",
|
||||
@@ -1168,7 +1169,44 @@
|
||||
"httpMethodDesc": "الأسلوب المستخدم في طلبات probe.",
|
||||
"note": "تحمل موزّعات leastPing/leastLoad دائمًا burstObservatory. يخصّص هذا المفتاح معاملات probe — أوقفه لاستخدام الإعدادات الافتراضية المدمجة. تُطبَّق التغييرات بعد إعادة تشغيل اللوحة."
|
||||
}
|
||||
}
|
||||
},
|
||||
"TGBotSettings": "بوت تيليجرام",
|
||||
"notifications": "الإشعارات",
|
||||
"notifyTime": {
|
||||
"custom": "مخصص (crontab)",
|
||||
"daily": "@daily — كل يوم الساعة 00:00",
|
||||
"every": "@every — التكرار ضمن فترة",
|
||||
"hourly": "@hourly — كل ساعة",
|
||||
"hours": "ساعات",
|
||||
"interval": "الفاصل الزمني",
|
||||
"minutes": "دقائق",
|
||||
"monthly": "@monthly — كل شهر",
|
||||
"seconds": "ثوانٍ",
|
||||
"unit": "الوحدة",
|
||||
"weekly": "@weekly — كل أسبوع"
|
||||
},
|
||||
"telegramAPIServer": "خادم API لتيليجرام",
|
||||
"telegramAPIServerDesc": "سيرفر Telegram API المستخدم. سيبه فاضي لاستخدام الافتراضي.",
|
||||
"telegramBotEnable": "تفعيل بوت Telegram",
|
||||
"telegramBotEnableDesc": "يفعل بوت Telegram.",
|
||||
"telegramBotLanguage": "لغة بوت Telegram",
|
||||
"telegramChatId": "ID شات الأدمن",
|
||||
"telegramChatIdDesc": "ID شات الأدمن في Telegram. (مفصول بفواصل)(تقدر تجيبه من {'@'}userinfobot) أو (استخدم '/id' في البوت)",
|
||||
"telegramNotifyTime": "وقت الإشعار",
|
||||
"telegramNotifyTimeDesc": "عدد مرات إرسال البوت للتقارير الدورية. اختر فترة جاهزة، أو اختر «مخصص» لإدخال تعبير crontab.",
|
||||
"telegramToken": "رمز تيليجرام",
|
||||
"telegramTokenConfigured": "مهيأ؛ اتركه فارغاً للاحتفاظ بالتوكن الحالي.",
|
||||
"telegramTokenDesc": "توكن البوت اللي جبت من '{'@'}BotFather'.",
|
||||
"telegramTokenPlaceholder": "مهيأ — أدخل توكن جديد لاستبداله",
|
||||
"testTgBot": "إرسال رسالة تجريبية",
|
||||
"tgBotNotEnabled": "بوت Telegram غير مفعّل",
|
||||
"tgBotNotRunning": "بوت Telegram لا يعمل",
|
||||
"tgEventBusNotify": "إشعارات الأحداث عبر Telegram",
|
||||
"tgEventBusNotifyDesc": "اختر الأحداث التي تُطلق إشعارات Telegram",
|
||||
"tgNotifyBackup": "نسخة احتياطية لقاعدة البيانات",
|
||||
"tgNotifyBackupDesc": "ابعت ملف النسخة الاحتياطية لقاعدة البيانات مع التقرير.",
|
||||
"tgTestFailed": "فشل اختبار Telegram",
|
||||
"tgTestSuccess": "تم إرسال رسالة تجريبية إلى Telegram"
|
||||
},
|
||||
"xray": {
|
||||
"save": "احفظ",
|
||||
@@ -1657,7 +1695,182 @@
|
||||
}
|
||||
},
|
||||
"tgbot": {
|
||||
"noIpRecord": "❗ لا يوجد سجل IP!"
|
||||
"noIpRecord": "❗ لا يوجد سجل IP!",
|
||||
"keyboardClosed": "❌ لوحة المفاتيح مغلقة!",
|
||||
"noResult": "❗ لا يوجد نتائج!",
|
||||
"noQuery": "❌ لم يتم العثور على الاستعلام! يرجى استخدام الأمر مرة أخرى!",
|
||||
"wentWrong": "❌ حدث خطأ ما!",
|
||||
"noInbounds": "❗ لم يتم العثور على أي وارد!",
|
||||
"unlimited": "♾ غير محدود (إعادة تعيين)",
|
||||
"add": "إضافة",
|
||||
"month": "شهر",
|
||||
"months": "أشهر",
|
||||
"days": "أيام",
|
||||
"hours": "ساعات",
|
||||
"minutes": "دقائق",
|
||||
"unknown": "غير معروف",
|
||||
"inbounds": "الواردات",
|
||||
"clients": "العملاء",
|
||||
"offline": "🔴 غير متصل",
|
||||
"online": "🟢 متصل",
|
||||
"commands": {
|
||||
"unknown": "❗ أمر مش معروف.",
|
||||
"pleaseChoose": "👇 من فضلك اختار:\r\n",
|
||||
"help": "🤖 أهلا بيك في البوت! البوت ده معمول عشان يديك بيانات معينة من البانل ويسمحلك بالتعديلات.",
|
||||
"start": "👋 أهلا <i>{{ .Firstname }}</i>.\r\n",
|
||||
"welcome": "🤖 أهلا بيك في بوت إدارة <b>{{ .Hostname }}</b>.\r\n",
|
||||
"status": "✅ البوت شغال!",
|
||||
"usage": "❗ من فضلك ادخل نص للتبحث عنه!",
|
||||
"getID": "🆔 الـ ID بتاعك: <code>{{ .ID }}</code>",
|
||||
"helpAdminCommands": "عشان تعيد تشغيل Xray Core:\r\n<code>/restart</code>\r\n\r\nعشان تدور على إيميل عميل:\r\n<code>/usage [Email]</code>\r\n\r\nعشان تدور على إدخالات (مع إحصائيات العملاء):\r\n<code>/inbound [Remark]</code>\r\n\r\nID شات Telegram:\r\n<code>/id</code>",
|
||||
"helpClientCommands": "عشان تدور على الإحصائيات، استخدم الأمر ده:\r\n\r\n<code>/usage [Email]</code>\r\n\r\nID شات Telegram:\r\n<code>/id</code>",
|
||||
"restartUsage": "\r\n\r\n<code>/restart</code>",
|
||||
"restartSuccess": "✅ العملية نجحت!",
|
||||
"restartFailed": "❗ حصل خطأ في العملية.\r\n\r\n<code>Error: {{ .Error }}</code>.",
|
||||
"xrayNotRunning": "❗ Xray Core مش شغال.",
|
||||
"startDesc": "عرض القائمة الرئيسية",
|
||||
"helpDesc": "مساعدة البوت",
|
||||
"statusDesc": "التحقق من حالة البوت",
|
||||
"idDesc": "عرض معرف Telegram الخاص بك",
|
||||
"usageDesc": "عرض استهلاك العميل: /usage البريد",
|
||||
"inboundDesc": "البحث في الواردات: /inbound الاسم (مشرف)",
|
||||
"restartDesc": "إعادة تشغيل نواة Xray (مشرف)",
|
||||
"clearallDesc": "تصفير استهلاك جميع العملاء (مشرف)"
|
||||
},
|
||||
"messages": {
|
||||
"cpuThreshold": "حمل المعالج {{ .Percent }}% عدى الحد المسموح ({{ .Threshold }}%)",
|
||||
"selectUserFailed": "❌ حصل خطأ في اختيار المستخدم!",
|
||||
"userSaved": "✅ حفظت بيانات مستخدم Telegram.",
|
||||
"loginSuccess": "✅ تسجيل الدخول للبانل تم بنجاح.\r\n",
|
||||
"loginFailed": "❗️فشل محاولة تسجيل الدخول للبانل.\r\n",
|
||||
"report": "🕰 التقارير المجدولة: {{ .RunTime }}\r\n",
|
||||
"datetime": "⏰ التاريخ والوقت: {{ .DateTime }}\r\n",
|
||||
"hostname": "💻 المضيف: {{ .Hostname }}\r\n",
|
||||
"version": "🚀 نسخة 3X-UI: {{ .Version }}\r\n",
|
||||
"xrayVersion": "📡 نسخة 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": "⏳ وقت التشغيل: {{ .UpTime }} {{ .Unit }}\r\n",
|
||||
"serverLoad": "📈 تحميل النظام: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
|
||||
"serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
|
||||
"tcpCount": "🔹 TCP: {{ .Count }}\r\n",
|
||||
"udpCount": "🔸 UDP: {{ .Count }}\r\n",
|
||||
"traffic": "🚦 الترافيك: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
|
||||
"xrayStatus": "ℹ️ الحالة: {{ .State }}\r\n",
|
||||
"username": "👤 اسم المستخدم: {{ .Username }}\r\n",
|
||||
"reason": "❗️ السبب: {{ .Reason }}\r\n",
|
||||
"time": "⏰ الوقت: {{ .Time }}\r\n",
|
||||
"inbound": "📍 الوارد: {{ .Remark }}\r\n",
|
||||
"port": "🔌 المنفذ: {{ .Port }}\r\n",
|
||||
"expire": "📅 تاريخ الانتهاء: {{ .Time }}\r\n",
|
||||
"expireIn": "📅 هيخلص بعد: {{ .Time }}\r\n",
|
||||
"active": "💡 مفعل: {{ .Enable }}\r\n",
|
||||
"enabled": "🚨 مفعل: {{ .Enable }}\r\n",
|
||||
"online": "🌐 حالة الاتصال: {{ .Status }}\r\n",
|
||||
"lastOnline": "🔙 آخر متصل: {{ .Time }}\r\n",
|
||||
"email": "📧 البريد: {{ .Email }}\r\n",
|
||||
"upload": "🔼 الرفع: ↑{{ .Upload }}\r\n",
|
||||
"download": "🔽 التنزيل: ↓{{ .Download }}\r\n",
|
||||
"total": "📊 الإجمالي: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
|
||||
"TGUser": "👤 مستخدم Telegram: {{ .TelegramID }}\r\n",
|
||||
"exhaustedCount": "🚨 عدد النفاذ لـ {{ .Type }}:\r\n",
|
||||
"onlinesCount": "🌐 العملاء الأونلاين: {{ .Count }}\r\n",
|
||||
"disabled": "🛑 معطل: {{ .Disabled }}\r\n",
|
||||
"depleteSoon": "🔜 هينتهي قريب: {{ .Deplete }}\r\n\r\n",
|
||||
"backupTime": "🗄 وقت النسخة الاحتياطية: {{ .Time }}\r\n",
|
||||
"refreshedOn": "\r\n📋🔄 اتحدّث في: {{ .Time }}\r\n\r\n",
|
||||
"yes": "✅ أيوه",
|
||||
"no": "❌ لا",
|
||||
"received_email": "📧📥 الإيميل اتحدث.",
|
||||
"received_comment": "💬📥 التعليق اتحدث.",
|
||||
"email_prompt": "📧 الإيميل الافتراضي: {{ .ClientEmail }}\n\nادخل الإيميل بتاعك.",
|
||||
"comment_prompt": "💬 التعليق الافتراضي: {{ .ClientComment }}\n\nادخل تعليقك.",
|
||||
"cancel": "❌ العملية اتلغت! \n\nممكن تبدأ من /start في أي وقت. 🔄",
|
||||
"error_add_client": "⚠️ خطأ:\n\n {{ .error }}",
|
||||
"using_default_value": "تمام، هشيل على القيمة الافتراضية. 😊",
|
||||
"incorrect_input": "المدخلات مش صحيحة.\nالكلمات لازم تكون متصلة من غير فراغات.\nمثال صحيح: aaaaaa\nمثال غلط: aaa aaa 🚫",
|
||||
"AreYouSure": "إنت متأكد؟ 🤔",
|
||||
"SuccessResetTraffic": "📧 البريد الإلكتروني: {{ .ClientEmail }}\n🏁 النتيجة: ✅ تم بنجاح",
|
||||
"FailedResetTraffic": "📧 البريد الإلكتروني: {{ .ClientEmail }}\n🏁 النتيجة: ❌ فشل \n\n🛠️ الخطأ: [ {{ .ErrorMessage }} ]",
|
||||
"FinishProcess": "🔚 عملية إعادة ضبط الترافيك خلصت لكل العملاء.",
|
||||
"eventOutboundDown": "الصادر {{ .Tag }} غير متصل",
|
||||
"eventOutboundUp": "الصادر {{ .Tag }} متصل",
|
||||
"eventErrorDetail": "الخطأ: {{ .Error }}",
|
||||
"eventDelayDetail": "التأخير: {{ .Delay }} مللي ثانية",
|
||||
"eventXrayCrash": "تعطّل Xray",
|
||||
"eventXrayCrashError": "الخطأ: {{ .Error }}",
|
||||
"eventNodeDown": "العقدة {{ .Name }} غير متصلة",
|
||||
"eventNodeUp": "العقدة {{ .Name }} متصلة",
|
||||
"eventLoginFallback": "فشل تسجيل الدخول من {{ .Source }}",
|
||||
"memoryThreshold": "استخدام الذاكرة {{ .Percent }}% يتجاوز الحد {{ .Threshold }}%"
|
||||
},
|
||||
"buttons": {
|
||||
"closeKeyboard": "❌ اقفل الكيبورد",
|
||||
"cancel": "❌ إلغاء",
|
||||
"cancelReset": "❌ إلغاء إعادة الضبط",
|
||||
"cancelIpLimit": "❌ إلغاء حد الـ IP",
|
||||
"confirmResetTraffic": "✅ تأكيد إعادة ضبط الترافيك؟",
|
||||
"confirmClearIps": "✅ تأكيد مسح الـ IPs؟",
|
||||
"confirmRemoveTGUser": "✅ تأكيد حذف مستخدم Telegram؟",
|
||||
"confirmToggle": "✅ تأكيد تفعيل/تعطيل المستخدم؟",
|
||||
"dbBackup": "احصل على نسخة DB",
|
||||
"serverUsage": "استخدام السيرفر",
|
||||
"getInbounds": "احصل على الإدخالات",
|
||||
"depleteSoon": "هينتهي قريب",
|
||||
"clientUsage": "استخدام العميل",
|
||||
"onlines": "العملاء الأونلاين",
|
||||
"commands": "الأوامر",
|
||||
"refresh": "🔄 تجديد",
|
||||
"clearIPs": "❌ مسح الـ IPs",
|
||||
"removeTGUser": "❌ حذف مستخدم Telegram",
|
||||
"selectTGUser": "👤 اختار مستخدم Telegram",
|
||||
"selectOneTGUser": "👤 اختار مستخدم Telegram:",
|
||||
"resetTraffic": "📈 إعادة ضبط الترافيك",
|
||||
"resetExpire": "📅 تغيير تاريخ الانتهاء",
|
||||
"ipLog": "🔢 سجل الـ IP",
|
||||
"ipLimit": "🔢 حد الـ IP",
|
||||
"setTGUser": "👤 ضبط مستخدم Telegram",
|
||||
"toggle": "🔘 تفعيل / تعطيل",
|
||||
"custom": "🔢 مخصص",
|
||||
"confirmNumber": "✅ تأكيد: {{ .Num }}",
|
||||
"confirmNumberAdd": "✅ تأكيد إضافة: {{ .Num }}",
|
||||
"limitTraffic": "🚧 حد الترافيك",
|
||||
"getBanLogs": "احصل على سجلات الحظر",
|
||||
"allClients": "كل العملاء",
|
||||
"addClient": "إضافة عميل",
|
||||
"submitDisable": "إرسال كمعطّل ☑️",
|
||||
"submitEnable": "إرسال كمفعّل ✅",
|
||||
"use_default": "🏷️ استخدام الإعدادات الافتراضية",
|
||||
"change_email": "⚙️📧 البريد",
|
||||
"change_comment": "⚙️💬 تعليق",
|
||||
"ResetAllTraffics": "إعادة ضبط جميع الترافيك",
|
||||
"SortedTrafficUsageReport": "تقرير استخدام الترافيك المرتب"
|
||||
},
|
||||
"answers": {
|
||||
"successfulOperation": "✅ العملية نجحت!",
|
||||
"errorOperation": "❗ حصل خطأ في العملية.",
|
||||
"getInboundsFailed": "❌ فشل الحصول على الإدخالات.",
|
||||
"getClientsFailed": "❌ فشل الحصول على العملاء.",
|
||||
"canceled": "❌ {{ .Email }}: العملية اتلغت.",
|
||||
"clientRefreshSuccess": "✅ {{ .Email }}: العميل اتحدث بنجاح.",
|
||||
"IpRefreshSuccess": "✅ {{ .Email }}: الـ IPs اتحدثت بنجاح.",
|
||||
"TGIdRefreshSuccess": "✅ {{ .Email }}: مستخدم Telegram اتحدث بنجاح.",
|
||||
"resetTrafficSuccess": "✅ {{ .Email }}: الترافيك اتظبط بنجاح.",
|
||||
"setTrafficLimitSuccess": "✅ {{ .Email }}: حد الترافيك اتسجل بنجاح.",
|
||||
"expireResetSuccess": "✅ {{ .Email }}: أيام الانتهاء اتظبطت بنجاح.",
|
||||
"resetIpSuccess": "✅ {{ .Email }}: حد الـ IP ({{ .Count }}) اتسجل بنجاح.",
|
||||
"clearIpSuccess": "✅ {{ .Email }}: الـ IPs اتمسحت بنجاح.",
|
||||
"getIpLog": "✅ {{ .Email }}: سجل الـ IP اتجاب.",
|
||||
"getUserInfo": "✅ {{ .Email }}: بيانات مستخدم Telegram اتجاب.",
|
||||
"removedTGUserSuccess": "✅ {{ .Email }}: مستخدم Telegram اتحذف بنجاح.",
|
||||
"enableSuccess": "✅ {{ .Email }}: اتفعل بنجاح.",
|
||||
"disableSuccess": "✅ {{ .Email }}: اتعطل بنجاح.",
|
||||
"askToAddUserId": "مافيش إعدادات ليك!\r\nاطلب من الأدمن يضيف الـ Telegram ChatID الخاص بيك في إعداداتك.\r\n\r\nالـ ChatID بتاعك: <code>{{ .TgUserID }}</code>",
|
||||
"chooseClient": "اختار عميل للإدخال {{ .Inbound }}",
|
||||
"chooseInbound": "اختار الإدخال"
|
||||
}
|
||||
},
|
||||
"email": {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user