Админ-панель в боте: кнопка «Админка» и разделы кнопками
- В главном меню у администраторов появляется кнопка «Админка ⚙️» (видна только в сообщениях админу; не-админа код всё равно не пускает). - Админ-панель с кнопками: Статистика, Управление услугами, Рассылка, В главное меню — вместо запоминания текстовых команд. - Доступ строго по config.ADMIN_IDS на сервере. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -71,8 +71,8 @@ def is_valid_name(text: str) -> bool:
|
||||
# КЛАВИАТУРЫ ДЛЯ ИНТЕРФЕЙСА (UX/UI ВКонтакте)
|
||||
# ==========================================
|
||||
|
||||
def get_main_keyboard() -> str:
|
||||
"""Главное меню бота."""
|
||||
def get_main_keyboard(is_admin: bool = False) -> str:
|
||||
"""Главное меню бота. Для админа добавляется кнопка «Админка ⚙️»."""
|
||||
keyboard = VkKeyboard(one_time=False)
|
||||
# Кнопка начать опрос (зеленая)
|
||||
keyboard.add_button("Заполнить заявку 📝", color=VkKeyboardColor.PRIMARY)
|
||||
@@ -83,6 +83,23 @@ def get_main_keyboard() -> str:
|
||||
# Кнопки FAQ и оператора
|
||||
keyboard.add_button("Частые вопросы ❓", color=VkKeyboardColor.SECONDARY)
|
||||
keyboard.add_button("Позвать оператора 🧑💼", color=VkKeyboardColor.NEGATIVE)
|
||||
# Кнопка админ-панели — только для администраторов (отдельной строкой)
|
||||
if is_admin:
|
||||
keyboard.add_line()
|
||||
keyboard.add_button("Админка ⚙️", color=VkKeyboardColor.PRIMARY)
|
||||
return keyboard.get_keyboard()
|
||||
|
||||
|
||||
def get_admin_keyboard() -> str:
|
||||
"""Клавиатура админ-панели с разделами."""
|
||||
keyboard = VkKeyboard(one_time=False)
|
||||
keyboard.add_button("Статистика 📊", color=VkKeyboardColor.SECONDARY)
|
||||
keyboard.add_line()
|
||||
keyboard.add_button("Управление услугами ⚙️", color=VkKeyboardColor.SECONDARY)
|
||||
keyboard.add_line()
|
||||
keyboard.add_button("Рассылка 📣", color=VkKeyboardColor.SECONDARY)
|
||||
keyboard.add_line()
|
||||
keyboard.add_button("В главное меню ↩️", color=VkKeyboardColor.PRIMARY)
|
||||
return keyboard.get_keyboard()
|
||||
|
||||
|
||||
@@ -343,6 +360,22 @@ class VKBotApplication:
|
||||
self._msg_times[user_id] = times
|
||||
return len(times) > FLOOD_MAX_MSGS
|
||||
|
||||
def _is_admin(self, user_id: int) -> bool:
|
||||
"""Является ли пользователь администратором (по config.ADMIN_IDS)."""
|
||||
return hasattr(config, "ADMIN_IDS") and user_id in config.ADMIN_IDS
|
||||
|
||||
def _send_admin_panel(self, user_id: int):
|
||||
"""Главный экран админ-панели с кнопками разделов."""
|
||||
self.send_message(
|
||||
user_id,
|
||||
"⚙️ Админ-панель ИКП\n\n"
|
||||
"Выберите раздел на кнопках ниже:\n"
|
||||
"• 📊 Статистика — заявки, отклики, диалоги\n"
|
||||
"• ⚙️ Управление услугами — добавить/изменить/удалить\n"
|
||||
"• 📣 Рассылка — сообщение подписчикам",
|
||||
keyboard=get_admin_keyboard()
|
||||
)
|
||||
|
||||
def _notify_allowed(self, user_id: int) -> bool:
|
||||
"""Антиспам: не чаще раза в NOTIFY_COOLDOWN_SEC уведомляем оператора об одном пользователе."""
|
||||
now = time.time()
|
||||
@@ -377,11 +410,24 @@ class VKBotApplication:
|
||||
user_data = db.get_user_data(user_id)
|
||||
state = user_data["state"]
|
||||
|
||||
# Глобальная обработка админ-команд (доступна только пользователям из ADMIN_IDS)
|
||||
if hasattr(config, "ADMIN_IDS") and user_id in config.ADMIN_IDS:
|
||||
if text_lower in ["админка", "/admin", "услуги"]:
|
||||
# Глобальная обработка админ-команд и кнопок (только для ADMIN_IDS)
|
||||
if self._is_admin(user_id):
|
||||
if text_lower in ["админка", "админка ⚙️", "/admin"]:
|
||||
self._send_admin_panel(user_id)
|
||||
return
|
||||
elif text_lower in ["статистика 📊", "стата", "статистика", "/stats"]:
|
||||
self._handle_admin_stats(user_id)
|
||||
return
|
||||
elif text_lower in ["управление услугами ⚙️", "управление услугами", "услуги"]:
|
||||
self._send_admin_menu(user_id)
|
||||
return
|
||||
elif text_lower in ["рассылка 📣", "рассылка"]:
|
||||
# Кнопка без текста — показываем инструкцию
|
||||
self._handle_admin_broadcast(user_id, "рассылка")
|
||||
return
|
||||
elif text_lower.startswith("рассылка"):
|
||||
self._handle_admin_broadcast(user_id, text_clean)
|
||||
return
|
||||
elif text_lower.startswith("ред "):
|
||||
self._handle_admin_edit(user_id, text_clean)
|
||||
return
|
||||
@@ -391,11 +437,11 @@ class VKBotApplication:
|
||||
elif text_lower.startswith("удал "):
|
||||
self._handle_admin_delete(user_id, text_clean)
|
||||
return
|
||||
elif text_lower in ["стата", "статистика", "/stats"]:
|
||||
self._handle_admin_stats(user_id)
|
||||
return
|
||||
elif text_lower.startswith("рассылка"):
|
||||
self._handle_admin_broadcast(user_id, text_clean)
|
||||
elif text_lower in ["в главное меню ↩️"]:
|
||||
self.send_message(
|
||||
user_id, "🏠 Главное меню.",
|
||||
keyboard=get_main_keyboard(is_admin=True)
|
||||
)
|
||||
return
|
||||
|
||||
# Глобальная отписка от рассылки (доступна в любом состоянии)
|
||||
@@ -542,11 +588,11 @@ class VKBotApplication:
|
||||
return
|
||||
|
||||
# 3. Возврат в главное меню
|
||||
if text_lower in ["назад в меню ↩️", "меню", "назад"]:
|
||||
if text_lower in ["назад в меню ↩️", "меню", "назад", "в главное меню ↩️"]:
|
||||
self.send_message(
|
||||
user_id,
|
||||
"🏠 Вы вернулись в главное меню. Выберите интересующее действие:",
|
||||
keyboard=get_main_keyboard()
|
||||
keyboard=get_main_keyboard(is_admin=self._is_admin(user_id))
|
||||
)
|
||||
return
|
||||
|
||||
@@ -576,7 +622,7 @@ class VKBotApplication:
|
||||
"Я помогу быстро оформить заявку на тренировки, рассказать об услугах или связать вас с командой. "
|
||||
"Также у нас открыт набор игроков и сотрудников — загляните в раздел «Карьера в ИКП 💼».\n\n"
|
||||
"Выберите действие на кнопках ниже 👇",
|
||||
keyboard=get_main_keyboard(),
|
||||
keyboard=get_main_keyboard(is_admin=self._is_admin(user_id)),
|
||||
attachment=self.get_logo_attachment(user_id)
|
||||
)
|
||||
return
|
||||
@@ -586,7 +632,7 @@ class VKBotApplication:
|
||||
user_id,
|
||||
"🤔 Я пока только учусь и не смог полностью распознать ваш запрос.\n\n"
|
||||
"Пожалуйста, воспользуйтесь кнопками меню ниже или напишите 'оператор', чтобы я пригласил специалиста.",
|
||||
keyboard=get_main_keyboard()
|
||||
keyboard=get_main_keyboard(is_admin=self._is_admin(user_id))
|
||||
)
|
||||
|
||||
def _send_returning_prompt(self, user_id: int, user_data: Dict[str, Any]):
|
||||
|
||||
Reference in New Issue
Block a user