diff --git a/services/admin_bot.py b/services/admin_bot.py
index 739e0a0..53b0393 100644
--- a/services/admin_bot.py
+++ b/services/admin_bot.py
@@ -42,12 +42,14 @@ def clamp_for_telegram(text: str, has_media: bool) -> str:
def get_persian_main_menu(is_paused: bool = False):
- pause_btn = "▶️ راهاندازی و ادامه سیستم" if is_paused else "🛑 توقف اضطراری سیستم"
+ pause_btn = "▶️ راهاندازی سیستم" if is_paused else "🛑 توقف سیستم"
return [
- [Button.text("🏠 منوی اصلی", resize=True), Button.text("📊 آمار و وضعیت ناوگان", resize=True), Button.text("🔑 کد لاگین", resize=True)],
- [Button.text("📡 کانالهای مبدا", resize=True), Button.text("🎯 کانالهای مقصد", resize=True), Button.text("🌐 وبسایتهای مبدا", resize=True)],
- [Button.text("📂 دستهبندیها", resize=True), Button.text("🧠 تنظیمات و لاگهای AI", resize=True), Button.text("⚠️ خطاهای سیستم", resize=True)],
- [Button.text("➕ افزودن مبدا / مقصد", resize=True), Button.text("📨 پستهای بررسینشده", resize=True), Button.text(pause_btn, resize=True)],
+ [Button.text("🏠 منوی اصلی", resize=True), Button.text("📊 آمار ناوگان", resize=True)],
+ [Button.text("📡 کانالهای مبدا", resize=True), Button.text("🎯 کانالهای مقصد", resize=True)],
+ [Button.text("🌐 وبسایتهای مبدا", resize=True), Button.text("📂 دستهبندیها", resize=True)],
+ [Button.text("🧠 تنظیمات AI", resize=True), Button.text("⚠️ خطاهای سیستم", resize=True)],
+ [Button.text("➕ افزودن مبدا / مقصد", resize=True), Button.text("📨 پستهای بررسینشده", resize=True)],
+ [Button.text("🔑 کد لاگین", resize=True), Button.text(pause_btn, resize=True)],
[Button.text("❓ راهنمای سیستم", resize=True)]
]
@@ -1267,7 +1269,7 @@ class AdminBotService:
def _register_handlers(self):
# --- Start / Menu ---
- @self.client.on(events.NewMessage(pattern=r"(?i)^(/start|/menu|منو)$"))
+ @self.client.on(events.NewMessage(pattern=r"(?i)^(/start|/menu|منو|منوی اصلی|🏠 منوی اصلی)$"))
async def cmd_start(event: events.NewMessage.Event):
if not self.is_admin(event.sender_id):
await event.reply(f"⛔ دسترسی غیرمجاز. شناسه عددی شما: {event.sender_id}", parse_mode="html")
@@ -1290,7 +1292,7 @@ class AdminBotService:
await event.reply(welcome_text, parse_mode="html", buttons=menu)
# --- Statistics & Grafana Metrics Report ---
- @self.client.on(events.NewMessage(pattern=r"(?i)^(/stats|/report|📊 آمار و وضعیت ناوگان|📊 گزارش و آمار سیستم)$"))
+ @self.client.on(events.NewMessage(pattern=r"(?i)^(/stats|/report|📊 آمار ناوگان|📊 آمار و وضعیت ناوگان|📊 گزارش و آمار سیستم)$"))
async def cmd_stats(event: events.NewMessage.Event):
if not self.is_admin(event.sender_id):
return
@@ -1309,16 +1311,24 @@ class AdminBotService:
# --- AI Settings & Logs ---
- @self.client.on(events.NewMessage(pattern=r"(?i)^(/ai|🧠 تنظیمات و لاگهای AI)$"))
+ @self.client.on(events.NewMessage(pattern=r"(?i)^(/ai|🧠 تنظیمات AI|🧠 تنظیمات و لاگهای AI)$"))
async def cmd_ai(event: events.NewMessage.Event):
if not self.is_admin(event.sender_id):
return
text, buttons = await self._render_ai_menu()
await event.reply(text, parse_mode="html", buttons=buttons)
+ # --- System Errors ---
+ @self.client.on(events.NewMessage(pattern=r"(?i)^(/errors|/err|⚠️ خطاهای سیستم)$"))
+ async def cmd_errors(event: events.NewMessage.Event):
+ if not self.is_admin(event.sender_id):
+ return
+ text, buttons = await self._render_error_report()
+ await event.reply(text, parse_mode="html", buttons=buttons or None)
+
# --- Userbot Authentication ---
- @self.client.on(events.NewMessage(pattern=r"(?i)^(/request_code|🔑 درخواست کد لاگین)$"))
+ @self.client.on(events.NewMessage(pattern=r"(?i)^(/request_code|🔑 کد لاگین|🔑 درخواست کد لاگین)$"))
async def cmd_request_code(event: events.NewMessage.Event):
if not self.is_admin(event.sender_id):
return
@@ -1377,7 +1387,7 @@ class AdminBotService:
await event.reply(text, parse_mode="html", buttons=buttons or None)
# --- Categories Management ---
- @self.client.on(events.NewMessage(pattern=r"(?i)^(/categories|/cats|📂 دستهبندی کانالها)$"))
+ @self.client.on(events.NewMessage(pattern=r"(?i)^(/categories|/cats|📂 دستهبندیها|📂 دستهبندی کانالها)$"))
async def cmd_categories(event: events.NewMessage.Event):
if not self.is_admin(event.sender_id):
return
@@ -1411,7 +1421,7 @@ class AdminBotService:
await event.reply(guide, parse_mode="html", buttons=get_cancel_button())
# --- Re-send unreviewed posts ---
- @self.client.on(events.NewMessage(pattern=r"(?i)^(/pending|📨 ارسال پستهای بررسینشده)$"))
+ @self.client.on(events.NewMessage(pattern=r"(?i)^(/pending|📨 پستهای بررسینشده|📨 ارسال پستهای بررسینشده)$"))
async def cmd_pending(event: events.NewMessage.Event):
if not self.is_admin(event.sender_id):
return
@@ -1433,7 +1443,7 @@ class AdminBotService:
)
# --- System Pause / Emergency Stop & Resume ---
- @self.client.on(events.NewMessage(pattern=r"(?i)^(/pause|/stop|🛑 توقف اضطراری سیستم)$"))
+ @self.client.on(events.NewMessage(pattern=r"(?i)^(/pause|/stop|🛑 توقف سیستم|🛑 توقف اضطراری سیستم)$"))
async def cmd_pause(event: events.NewMessage.Event):
if not self.is_admin(event.sender_id):
return
@@ -1443,12 +1453,12 @@ class AdminBotService:
"• ⏸ دریافت خودکار پستهای جدید از کانالهای مبدا متوقف شد.\n"
"• ⏸ ارسال زمانبندیشده پستها به کانالهای مقصد متوقف شد.\n"
"• 🟢 پنل مدیریت، دستورات و پیامهای ادمین همچنان کاملاً فعال هستند.\n\n"
- "برای از سرگیری فعالیت سیستم، روی دکمه «▶️ راهاندازی و ادامه سیستم» بزنید."
+ "برای از سرگیری فعالیت سیستم، روی دکمه «▶️ راهاندازی سیستم» بزنید."
)
menu = await self.get_menu()
await event.reply(text, parse_mode="html", buttons=menu)
- @self.client.on(events.NewMessage(pattern=r"(?i)^(/resume|/start_fleet|▶️ راهاندازی و ادامه سیستم)$"))
+ @self.client.on(events.NewMessage(pattern=r"(?i)^(/resume|/start_fleet|▶️ راهاندازی سیستم|▶️ راهاندازی و ادامه سیستم)$"))
async def cmd_resume(event: events.NewMessage.Event):
if not self.is_admin(event.sender_id):
return
@@ -1572,15 +1582,19 @@ class AdminBotService:
text = (event.raw_text or "").strip()
# Ignore main menu commands
- if text in ["/start", "/menu", "منو", "/stats", "📊 آمار و وضعیت ناوگان",
+ if text in ["/start", "/menu", "منو", "منوی اصلی", "🏠 منوی اصلی",
+ "/stats", "/report", "📊 آمار ناوگان", "📊 آمار و وضعیت ناوگان", "📊 گزارش و آمار سیستم",
"/sources", "📡 کانالهای مبدا", "/targets", "🎯 کانالهای مقصد",
- "/request_code", "🔑 درخواست کد لاگین",
- "/pending", "📨 ارسال پستهای بررسینشده",
- "/errors", "⚠️ خطاهای سیستم",
- "/ai", "🧠 تنظیمات و لاگهای AI",
- "/categories", "/cats", "📂 دستهبندی کانالها",
- "/pause", "/stop", "🛑 توقف اضطراری سیستم",
- "/resume", "/start_fleet", "▶️ راهاندازی و ادامه سیستم"]:
+ "/websites", "/sites", "🌐 وبسایتهای مبدا",
+ "/request_code", "🔑 کد لاگین", "🔑 درخواست کد لاگین",
+ "/pending", "📨 پستهای بررسینشده", "📨 ارسال پستهای بررسینشده",
+ "/errors", "/err", "⚠️ خطاهای سیستم",
+ "/ai", "🧠 تنظیمات AI", "🧠 تنظیمات و لاگهای AI",
+ "/categories", "/cats", "📂 دستهبندیها", "📂 دستهبندی کانالها",
+ "/add", "➕ افزودن مبدا / مقصد", "➕ افزودن کانال مبدا", "➕ افزودن کانال مقصد",
+ "/pause", "/stop", "🛑 توقف سیستم", "🛑 توقف اضطراری سیستم",
+ "/resume", "/start_fleet", "▶️ راهاندازی سیستم", "▶️ راهاندازی و ادامه سیستم",
+ "/help", "❓ راهنمای سیستم"]:
return
# Cancel command
diff --git a/tests/test_target_context_and_website_custom_needs.py b/tests/test_target_context_and_website_custom_needs.py
index b6d4b83..8e849aa 100644
--- a/tests/test_target_context_and_website_custom_needs.py
+++ b/tests/test_target_context_and_website_custom_needs.py
@@ -112,11 +112,11 @@ async def test_website_custom_needs_and_prompt_injection():
async def test_menu_layout():
menu = get_persian_main_menu(is_paused=False)
- assert len(menu) == 5
+ assert len(menu) == 7
first_row_texts = [getattr(getattr(b, "button", None), "text", str(b)) for b in menu[0]]
assert any("🏠 منوی اصلی" in t for t in first_row_texts)
- fourth_row_texts = [getattr(getattr(b, "button", None), "text", str(b)) for b in menu[3]]
- assert any("➕ افزودن مبدا / مقصد" in t for t in fourth_row_texts)
+ fifth_row_texts = [getattr(getattr(b, "button", None), "text", str(b)) for b in menu[4]]
+ assert any("➕ افزودن مبدا / مقصد" in t for t in fifth_row_texts)
async def main():