From 377188a015b17eda726c2a73001755e0ef972b8f Mon Sep 17 00:00:00 2001 From: Kenik Date: Mon, 22 Jun 2026 07:40:04 +0300 Subject: [PATCH] =?UTF-8?q?=D0=90=D0=B4=D0=BC=D0=B8=D0=BD-=D0=BF=D0=B0?= =?UTF-8?q?=D0=BD=D0=B5=D0=BB=D1=8C=20=D0=B2=20=D0=B1=D0=BE=D1=82=D0=B5:?= =?UTF-8?q?=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA=D0=B0=20=C2=AB=D0=90=D0=B4?= =?UTF-8?q?=D0=BC=D0=B8=D0=BD=D0=BA=D0=B0=C2=BB=20=D0=B8=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=B4=D0=B5=D0=BB=D1=8B=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA?= =?UTF-8?q?=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - В главном меню у администраторов появляется кнопка «Админка ⚙️» (видна только в сообщениях админу; не-админа код всё равно не пускает). - Админ-панель с кнопками: Статистика, Управление услугами, Рассылка, В главное меню — вместо запоминания текстовых команд. - Доступ строго по config.ADMIN_IDS на сервере. Co-Authored-By: Claude Opus 4.8 --- bot.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 14 deletions(-) diff --git a/bot.py b/bot.py index db68a29..cb42f7b 100644 --- a/bot.py +++ b/bot.py @@ -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]):