domovoy_bot/keyboards/admin_menu.py
Admin d81ee6d238 АВТОВЕРИФИКАЦИЯ АКТИВНЫХ ПОЛЬЗОВАТЕЛЕЙ
 Реализовано:
- Автоверификация по 50+ сообщениям
- Кнопка админу ' Автоверификация'
- Веб-админка → Пользователи → Статистика + Кнопка
- Плавный ввод верификации

🎯 Как работает:
1. Бот считает сообщения пользователей
2. Кто набрал 50+ сообщений — считается 'своим'
3. Админ жмёт кнопку → все активные верифицируются
4. Веб-админка показывает статистику:
   - Всего пользователей
   - Верифицировано
   - Не верифицировано
   - Активных для верификации

📝 Преимущества:
- Не нужно проверять 200 человек вручную
- Активные жильцы сразу получают доступ
- Админы проверяют только подозрительных
- Мотивация: телефоны только после верификации

🧪 Тест:
/admin →  Автоверификация
или
Веб-админка → Пользователи → Верифицировать всех

💡 Плавный ввод:
- Бот предлагает верификацию, но не требует
- Телефоны и функции только после верификации
- Жильцы сами мотивированы пройти верификацию

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-03 18:41:29 +00:00

341 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Клавиатуры для админа
"""
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardBuilder
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton
from typing import Optional
def get_admin_main_menu() -> InlineKeyboardMarkup:
"""Главное меню админа (inline)"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(text='📊 Статистика', callback_data='admin_stats'),
InlineKeyboardButton(text='🕵️ Шпионы', callback_data='admin_spies'),
)
builder.row(
InlineKeyboardButton(text='👥 Пользователи', callback_data='admin_users'),
InlineKeyboardButton(text='⏳ Непроверенные', callback_data='admin_unverified'),
)
builder.row(
InlineKeyboardButton(text='🏆 Рейтинг', callback_data='admin_rating'),
InlineKeyboardButton(text='☠️ Токсичность', callback_data='admin_toxicity'),
)
builder.row(
InlineKeyboardButton(text='🏠 Квартиры', callback_data='admin_apartments'),
InlineKeyboardButton(text='⚠️ Предупреждения', callback_data='admin_warnings'),
)
builder.row(
InlineKeyboardButton(text='🔇 Муты', callback_data='admin_muted'),
InlineKeyboardButton(text='🚫 Баны', callback_data='admin_banned'),
)
builder.row(
InlineKeyboardButton(text='🔍 Поиск', callback_data='admin_search'),
InlineKeyboardButton(text='👤 Действия', callback_data='admin_user_actions'),
)
builder.row(
InlineKeyboardButton(text='📥 Экспорт', callback_data='admin_export'),
InlineKeyboardButton(text='📤 Рассылка', callback_data='admin_broadcast'),
)
builder.row(
InlineKeyboardButton(text='🚫 Отозвать вериф.', callback_data='admin_unverify'),
InlineKeyboardButton(text='📋 Список не вериф.', callback_data='admin_unverified_list'),
)
builder.row(
InlineKeyboardButton(text='⚡ Автоверификация', callback_data='admin_auto_verify'),
)
builder.row(
InlineKeyboardButton(text='❓ Помощь', callback_data='admin_help'),
)
return builder.as_markup()
def get_admin_reply_menu() -> ReplyKeyboardMarkup:
"""Главное меню админа (reply - кнопки под полем ввода)"""
builder = ReplyKeyboardBuilder()
builder.row(
KeyboardButton(text='📊 Статистика'),
KeyboardButton(text='🕵️ Шпионы'),
)
builder.row(
KeyboardButton(text='👥 Пользователи'),
KeyboardButton(text='⏳ Непроверенные'),
)
builder.row(
KeyboardButton(text='🏠 Квартиры'),
KeyboardButton(text='⚠️ Предупреждения'),
)
builder.row(
KeyboardButton(text='🏆 Рейтинг'),
KeyboardButton(text='📥 Экспорт'),
)
builder.row(
KeyboardButton(text='📤 Рассылка'),
)
builder.row(
KeyboardButton(text='🚫 Отозвать вериф.'),
KeyboardButton(text='📋 Не верифицированные'),
)
builder.row(
KeyboardButton(text='❓ Помощь'),
)
return builder.as_markup(resize_keyboard=True)
def get_admin_help_menu() -> InlineKeyboardMarkup:
"""Меню помощи админа"""
builder = InlineKeyboardBuilder()
builder.button(text='🔙 Назад', callback_data='admin_menu')
return builder.as_markup()
def get_admin_apartments_menu() -> InlineKeyboardMarkup:
"""Меню квартир"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(text='📊 Статистика квартир', callback_data='admin_apt_stats'),
)
builder.row(
InlineKeyboardButton(text='🔙 Назад', callback_data='admin_menu'),
)
return builder.as_markup()
def get_admin_warnings_menu() -> InlineKeyboardMarkup:
"""Меню предупреждений"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(text='📋 Список предупреждений', callback_data='admin_warn_list'),
)
builder.row(
InlineKeyboardButton(text='🔙 Назад', callback_data='admin_menu'),
)
return builder.as_markup()
def get_admin_rating_menu() -> InlineKeyboardMarkup:
"""Меню рейтинга"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(text='🏆 Топ-10', callback_data='admin_top'),
InlineKeyboardButton(text='📊 Уровни', callback_data='admin_rank'),
)
builder.row(
InlineKeyboardButton(text='🔙 Назад', callback_data='admin_menu'),
)
return builder.as_markup()
def get_admin_toxicity_menu() -> InlineKeyboardMarkup:
"""Меню токсичности"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(text='☠️ Топ токсичных', callback_data='admin_toxic_top'),
InlineKeyboardButton(text='📊 Статистика', callback_data='admin_toxic_stats'),
)
builder.row(
InlineKeyboardButton(text='🔙 Назад', callback_data='admin_menu'),
)
return builder.as_markup()
def get_admin_search_menu() -> InlineKeyboardMarkup:
"""Меню поиска"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(text='🏠 Поиск квартиры', callback_data='admin_search_apt'),
InlineKeyboardButton(text='👤 Поиск пользователя', callback_data='admin_search_user'),
)
builder.row(
InlineKeyboardButton(text='🔙 Назад', callback_data='admin_menu'),
)
return builder.as_markup()
def get_user_pagination_keyboard(
users: list,
page: int = 0,
page_size: int = 20,
action_prefix: str = 'user_action'
) -> InlineKeyboardMarkup:
"""
Клавиатура с пагинацией для списка пользователей
:param users: список пользователей (User модели)
:param page: текущая страница (0-based)
:param page_size: размер страницы
:param action_prefix: префикс для callback_data
"""
builder = InlineKeyboardBuilder()
total_pages = (len(users) + page_size - 1) // page_size
# Получаем пользователей для текущей страницы
start_idx = page * page_size
end_idx = min(start_idx + page_size, len(users))
page_users = users[start_idx:end_idx]
# Кнопки для каждого пользователя
for user in page_users:
status = '' if user.verified else ''
name = user.full_name or f'user{user.user_id}'
apt = f' (кв. {user.apartment})' if user.apartment else ''
button_text = f"{status} {name}{apt} | {user.user_id}"
builder.button(
text=button_text,
callback_data=f'{action_prefix}_{user.user_id}'
)
# Кнопки навигации
nav_buttons = []
if page > 0:
nav_buttons.append(InlineKeyboardButton(text='⬅️ Назад', callback_data=f'{action_prefix}_page_{page - 1}'))
if page < total_pages - 1:
nav_buttons.append(InlineKeyboardButton(text='Вперёд ➡️', callback_data=f'{action_prefix}_page_{page + 1}'))
if nav_buttons:
builder.row(*nav_buttons)
# Инфо о странице
builder.row(
InlineKeyboardButton(text=f'📄 Стр. {page + 1}/{total_pages}', callback_data='page_info'),
InlineKeyboardButton(text='🔙 Назад', callback_data='admin_menu'),
)
return builder.as_markup()
def get_user_action_menu(user_id: int, user_name: str, apartment: Optional[str] = None) -> InlineKeyboardMarkup:
"""
Меню действий с пользователем
:param user_id: ID пользователя
:param user_name: имя пользователя
:param apartment: номер квартиры
"""
builder = InlineKeyboardBuilder()
apt_info = f' (кв. {apartment})' if apartment else ''
builder.row(
InlineKeyboardButton(text=f'👤 {user_name}{apt_info}', callback_data='user_info_label'),
)
builder.row(
InlineKeyboardButton(text=f'ID: {user_id}', callback_data='user_id_label'),
)
builder.row(
InlineKeyboardButton(text='⚠️ Предупредить', callback_data=f'user_warn_{user_id}'),
InlineKeyboardButton(text='🚫 Забанить', callback_data=f'user_ban_{user_id}'),
)
builder.row(
InlineKeyboardButton(text='✅ Разбанить', callback_data=f'user_unban_{user_id}'),
InlineKeyboardButton(text='🔓 Снять вериф.', callback_data=f'user_revoke_{user_id}'),
)
builder.row(
InlineKeyboardButton(text='⏳ Отозвать (7д)', callback_data=f'user_unverify_{user_id}'),
InlineKeyboardButton(text='📊 Рейтинг', callback_data=f'user_rating_{user_id}'),
)
builder.row(
InlineKeyboardButton(text='📝 История', callback_data=f'user_history_{user_id}'),
InlineKeyboardButton(text='📞 Телефон', callback_data=f'user_phone_{user_id}'),
)
builder.row(
InlineKeyboardButton(text='🔙 Назад к списку', callback_data='admin_user_actions'),
InlineKeyboardButton(text='🔙 В меню', callback_data='admin_menu'),
)
return builder.as_markup()
def get_admin_antispam_menu() -> InlineKeyboardMarkup:
"""Меню анти-спама/анти-мата"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(text='📋 Стоп-слова', callback_data='admin_bad_words'),
InlineKeyboardButton(text='🌐 Домены', callback_data='admin_bad_domains'),
)
builder.row(
InlineKeyboardButton(text='🔑 Паттерны', callback_data='admin_bad_patterns'),
InlineKeyboardButton(text='🔑 Ключевые слова', callback_data='admin_bad_keywords'),
)
builder.row(
InlineKeyboardButton(text='🔙 Назад', callback_data='admin_menu'),
)
return builder.as_markup()
def get_bad_words_list_keyboard(words: list, page: int = 0, page_size: int = 20) -> InlineKeyboardMarkup:
"""Клавиатура со списком стоп-слов"""
builder = InlineKeyboardBuilder()
total_pages = (len(words) + page_size - 1) // page_size if words else 1
start_idx = page * page_size
end_idx = min(start_idx + page_size, len(words))
page_words = words[start_idx:end_idx]
for word in page_words:
builder.button(
text=f'{word}',
callback_data=f'badword_del_{word}'
)
builder.row(
InlineKeyboardButton(text=' Добавить слово', callback_data='badword_add'),
)
nav_buttons = []
if page > 0:
nav_buttons.append(InlineKeyboardButton(text='⬅️', callback_data=f'badwords_page_{page - 1}'))
if page < total_pages - 1:
nav_buttons.append(InlineKeyboardButton(text='➡️', callback_data=f'badwords_page_{page + 1}'))
if nav_buttons:
builder.row(*nav_buttons)
builder.row(
InlineKeyboardButton(text='🔙 Назад', callback_data='admin_warnings'),
)
return builder.as_markup()
def get_yes_no_keyboard(callback_prefix: str) -> InlineKeyboardMarkup:
"""Клавиатура Да/Нет с кастомным префиксом"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(text='✅ Да', callback_data=f'{callback_prefix}_yes'),
InlineKeyboardButton(text='❌ Нет', callback_data=f'{callback_prefix}_no'),
)
return builder.as_markup()
def get_back_keyboard(back_callback: str = 'admin_menu') -> InlineKeyboardMarkup:
"""Простая клавиатура с кнопкой Назад"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(text='🔙 Назад', callback_data=back_callback),
)
return builder.as_markup()