372 lines
13 KiB
Python
372 lines
13 KiB
Python
"""
|
|
Обработчики админ-панели для управления черным списком
|
|
"""
|
|
import logging
|
|
from aiogram import types
|
|
from aiogram.filters import StateFilter
|
|
from aiogram.fsm.context import FSMContext
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.config import settings
|
|
from app.database.models import User
|
|
from app.services.blacklist_service import blacklist_service
|
|
from app.states import BlacklistStates
|
|
from app.utils.decorators import admin_required, error_handler
|
|
from app.keyboards.admin import get_admin_users_keyboard
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@admin_required
|
|
@error_handler
|
|
async def show_blacklist_settings(
|
|
callback: types.CallbackQuery,
|
|
db_user: User,
|
|
state: FSMContext
|
|
):
|
|
"""
|
|
Показывает настройки черного списка
|
|
"""
|
|
logger.info(f"Вызван обработчик show_blacklist_settings для пользователя {callback.from_user.id}")
|
|
|
|
is_enabled = blacklist_service.is_blacklist_check_enabled()
|
|
github_url = blacklist_service.get_blacklist_github_url()
|
|
blacklist_count = len(await blacklist_service.get_all_blacklisted_users())
|
|
|
|
status_text = "✅ Включена" if is_enabled else "❌ Отключена"
|
|
url_text = github_url if github_url else "Не задан"
|
|
|
|
text = f"""
|
|
🔐 <b>Настройки черного списка</b>
|
|
|
|
Статус: {status_text}
|
|
URL к черному списку: <code>{url_text}</code>
|
|
Количество записей: {blacklist_count}
|
|
|
|
Действия:
|
|
"""
|
|
|
|
keyboard = [
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="🔄 Обновить список" if is_enabled else "🔄 Обновить (откл.)",
|
|
callback_data="admin_blacklist_update"
|
|
)
|
|
],
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="📋 Просмотреть список" if is_enabled else "📋 Просмотр (откл.)",
|
|
callback_data="admin_blacklist_view"
|
|
)
|
|
],
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="✏️ URL к GitHub" if not github_url else "✏️ Изменить URL",
|
|
callback_data="admin_blacklist_set_url"
|
|
)
|
|
],
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="✅ Включить" if not is_enabled else "❌ Отключить",
|
|
callback_data="admin_blacklist_toggle"
|
|
)
|
|
],
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="⬅️ Назад к пользователям",
|
|
callback_data="admin_users"
|
|
)
|
|
]
|
|
]
|
|
|
|
await callback.message.edit_text(
|
|
text,
|
|
reply_markup=types.InlineKeyboardMarkup(inline_keyboard=keyboard)
|
|
)
|
|
await callback.answer()
|
|
|
|
|
|
@admin_required
|
|
@error_handler
|
|
async def toggle_blacklist(
|
|
callback: types.CallbackQuery,
|
|
db_user: User,
|
|
state: FSMContext
|
|
):
|
|
"""
|
|
Переключает статус проверки черного списка
|
|
"""
|
|
# Текущая реализация использует настройки из .env
|
|
# Для полной реализации нужно будет создать сервис настроек
|
|
is_enabled = blacklist_service.is_blacklist_check_enabled()
|
|
|
|
# В реальной реализации нужно будет изменить настройку в базе данных
|
|
# или в системе настроек, но сейчас просто покажем статус
|
|
new_status = not is_enabled
|
|
status_text = "включена" if new_status else "отключена"
|
|
|
|
await callback.message.edit_text(
|
|
f"Статус проверки черного списка: {status_text}\n\n"
|
|
f"Для изменения статуса проверки черного списка измените значение\n"
|
|
f"<code>BLACKLIST_CHECK_ENABLED</code> в файле <code>.env</code>",
|
|
reply_markup=types.InlineKeyboardMarkup(inline_keyboard=[
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="🔄 Обновить статус",
|
|
callback_data="admin_blacklist_settings"
|
|
)
|
|
],
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="⬅️ Назад",
|
|
callback_data="admin_blacklist_settings"
|
|
)
|
|
]
|
|
])
|
|
)
|
|
await callback.answer()
|
|
|
|
|
|
@admin_required
|
|
@error_handler
|
|
async def update_blacklist(
|
|
callback: types.CallbackQuery,
|
|
db_user: User,
|
|
state: FSMContext
|
|
):
|
|
"""
|
|
Обновляет черный список из GitHub
|
|
"""
|
|
success, message = await blacklist_service.force_update_blacklist()
|
|
|
|
if success:
|
|
await callback.message.edit_text(
|
|
f"✅ {message}",
|
|
reply_markup=types.InlineKeyboardMarkup(inline_keyboard=[
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="📋 Просмотреть список",
|
|
callback_data="admin_blacklist_view"
|
|
)
|
|
],
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="🔄 Ручное обновление",
|
|
callback_data="admin_blacklist_update"
|
|
)
|
|
],
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="⬅️ Назад",
|
|
callback_data="admin_blacklist_settings"
|
|
)
|
|
]
|
|
])
|
|
)
|
|
else:
|
|
await callback.message.edit_text(
|
|
f"❌ Ошибка обновления: {message}",
|
|
reply_markup=types.InlineKeyboardMarkup(inline_keyboard=[
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="🔄 Повторить",
|
|
callback_data="admin_blacklist_update"
|
|
)
|
|
],
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="⬅️ Назад",
|
|
callback_data="admin_blacklist_settings"
|
|
)
|
|
]
|
|
])
|
|
)
|
|
await callback.answer()
|
|
|
|
|
|
@admin_required
|
|
@error_handler
|
|
async def show_blacklist_users(
|
|
callback: types.CallbackQuery,
|
|
db_user: User,
|
|
state: FSMContext
|
|
):
|
|
"""
|
|
Показывает список пользователей в черном списке
|
|
"""
|
|
blacklist_users = await blacklist_service.get_all_blacklisted_users()
|
|
|
|
if not blacklist_users:
|
|
text = "Черный список пуст"
|
|
else:
|
|
text = f"🔐 <b>Черный список ({len(blacklist_users)} записей)</b>\n\n"
|
|
|
|
# Показываем первые 20 записей
|
|
for i, (tg_id, username, reason) in enumerate(blacklist_users[:20], 1):
|
|
text += f"{i}. <code>{tg_id}</code> {username or ''} — {reason}\n"
|
|
|
|
if len(blacklist_users) > 20:
|
|
text += f"\n... и еще {len(blacklist_users) - 20} записей"
|
|
|
|
await callback.message.edit_text(
|
|
text,
|
|
reply_markup=types.InlineKeyboardMarkup(inline_keyboard=[
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="🔄 Обновить",
|
|
callback_data="admin_blacklist_view"
|
|
)
|
|
],
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="⬅️ Назад",
|
|
callback_data="admin_blacklist_settings"
|
|
)
|
|
]
|
|
])
|
|
)
|
|
await callback.answer()
|
|
|
|
|
|
@admin_required
|
|
@error_handler
|
|
async def start_set_blacklist_url(
|
|
callback: types.CallbackQuery,
|
|
db_user: User,
|
|
state: FSMContext
|
|
):
|
|
"""
|
|
Начинает процесс установки URL к черному списку
|
|
"""
|
|
current_url = blacklist_service.get_blacklist_github_url() or "не задан"
|
|
|
|
await callback.message.edit_text(
|
|
f"Введите новый URL к файлу черного списка на GitHub\n\n"
|
|
f"Текущий URL: {current_url}\n\n"
|
|
f"Пример: https://raw.githubusercontent.com/username/repository/main/blacklist.txt\n\n"
|
|
f"Для отмены используйте команду /cancel",
|
|
reply_markup=types.InlineKeyboardMarkup(inline_keyboard=[
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="⬅️ Назад",
|
|
callback_data="admin_blacklist_settings"
|
|
)
|
|
]
|
|
])
|
|
)
|
|
|
|
await state.set_state(BlacklistStates.waiting_for_blacklist_url)
|
|
await callback.answer()
|
|
|
|
|
|
@admin_required
|
|
@error_handler
|
|
async def process_blacklist_url(
|
|
message: types.Message,
|
|
db_user: User,
|
|
state: FSMContext
|
|
):
|
|
"""
|
|
Обрабатывает введенный URL к черному списку
|
|
"""
|
|
# Обрабатываем сообщение только если бот ожидает ввод URL
|
|
if await state.get_state() != BlacklistStates.waiting_for_blacklist_url.state:
|
|
return
|
|
|
|
url = message.text.strip()
|
|
|
|
# В реальной реализации нужно сохранить URL в систему настроек
|
|
# В текущей реализации просто выводим сообщение
|
|
if url.lower() in ['/cancel', 'отмена', 'cancel']:
|
|
await message.answer(
|
|
"Настройка URL отменена",
|
|
reply_markup=types.InlineKeyboardMarkup(inline_keyboard=[
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="🔐 Настройки черного списка",
|
|
callback_data="admin_blacklist_settings"
|
|
)
|
|
]
|
|
])
|
|
)
|
|
await state.clear()
|
|
return
|
|
|
|
# Проверяем, что URL выглядит корректно
|
|
if not url.startswith(('http://', 'https://')):
|
|
await message.answer(
|
|
"❌ Некорректный URL. URL должен начинаться с http:// или https://",
|
|
reply_markup=types.InlineKeyboardMarkup(inline_keyboard=[
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="🔐 Настройки черного списка",
|
|
callback_data="admin_blacklist_settings"
|
|
)
|
|
]
|
|
])
|
|
)
|
|
return
|
|
|
|
# В реальной системе здесь нужно сохранить URL в базу данных настроек
|
|
# или в систему конфигурации
|
|
|
|
await message.answer(
|
|
f"✅ URL к черному списку установлен:\n<code>{url}</code>\n\n"
|
|
f"Для применения изменений перезапустите бота или измените значение\n"
|
|
f"<code>BLACKLIST_GITHUB_URL</code> в файле <code>.env</code>",
|
|
reply_markup=types.InlineKeyboardMarkup(inline_keyboard=[
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="🔄 Обновить список",
|
|
callback_data="admin_blacklist_update"
|
|
)
|
|
],
|
|
[
|
|
types.InlineKeyboardButton(
|
|
text="🔐 Настройки черного списка",
|
|
callback_data="admin_blacklist_settings"
|
|
)
|
|
]
|
|
])
|
|
)
|
|
await state.clear()
|
|
|
|
|
|
def register_blacklist_handlers(dp):
|
|
"""
|
|
Регистрация обработчиков черного списка
|
|
"""
|
|
# Обработчик показа настроек черного списка
|
|
# Этот обработчик нужно будет вызывать из меню пользователей или отдельно
|
|
dp.callback_query.register(
|
|
show_blacklist_settings,
|
|
lambda c: c.data == "admin_blacklist_settings"
|
|
)
|
|
|
|
# Обработчики для взаимодействия с черным списком
|
|
dp.callback_query.register(
|
|
toggle_blacklist,
|
|
lambda c: c.data == "admin_blacklist_toggle"
|
|
)
|
|
|
|
dp.callback_query.register(
|
|
update_blacklist,
|
|
lambda c: c.data == "admin_blacklist_update"
|
|
)
|
|
|
|
dp.callback_query.register(
|
|
show_blacklist_users,
|
|
lambda c: c.data == "admin_blacklist_view"
|
|
)
|
|
|
|
dp.callback_query.register(
|
|
start_set_blacklist_url,
|
|
lambda c: c.data == "admin_blacklist_set_url"
|
|
)
|
|
|
|
# Обработчик сообщений для установки URL (работает только в нужном состоянии)
|
|
dp.message.register(
|
|
process_blacklist_url,
|
|
StateFilter(BlacklistStates.waiting_for_blacklist_url)
|
|
)
|