Files
tg_bot_language/bot/handlers/admin.py

258 lines
9.7 KiB
Python
Raw Normal View History

from aiogram import Router, F
from aiogram.filters import Command
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
from config.settings import settings
from database.db import async_session_maker
from database.models import AIProvider
from services.ai_model_service import AIModelService
router = Router()
def get_admin_ids() -> set:
"""Получить множество ID админов"""
if not settings.admin_ids:
return set()
return set(int(x.strip()) for x in settings.admin_ids.split(",") if x.strip())
def is_admin(user_id: int) -> bool:
"""Проверить, является ли пользователь админом"""
return user_id in get_admin_ids()
def get_admin_main_keyboard() -> InlineKeyboardMarkup:
"""Главное меню админки"""
return InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="🤖 Настройка AI модели", callback_data="admin_models")],
[InlineKeyboardButton(text="🌅 Генерация слов дня", callback_data="admin_generate_wod")],
[InlineKeyboardButton(text="📋 Слова дня (сегодня)", callback_data="admin_view_wod")],
[InlineKeyboardButton(text="❌ Закрыть", callback_data="admin_close")]
])
async def get_model_keyboard() -> InlineKeyboardMarkup:
"""Создать клавиатуру выбора AI модели"""
async with async_session_maker() as session:
models = await AIModelService.get_all_models(session)
keyboard = []
for model in models:
marker = "" if model.is_active else ""
provider_emoji = "🟢" if model.provider == AIProvider.openai else "🔵"
keyboard.append([InlineKeyboardButton(
text=f"{marker}{provider_emoji} {model.display_name}",
callback_data=f"admin_model_{model.id}"
)])
keyboard.append([InlineKeyboardButton(text="⬅️ Назад", callback_data="admin_back")])
return InlineKeyboardMarkup(inline_keyboard=keyboard)
@router.message(Command("admin"))
async def cmd_admin(message: Message):
"""Админская панель"""
if not is_admin(message.from_user.id):
return
async with async_session_maker() as session:
await AIModelService.ensure_default_models(session)
active_model = await AIModelService.get_active_model(session)
active_name = active_model.display_name if active_model else "Не выбрана"
text = (
"🔧 <b>Админ-панель</b>\n\n"
f"🤖 Текущая AI модель: <b>{active_name}</b>"
)
await message.answer(text, reply_markup=get_admin_main_keyboard())
@router.callback_query(F.data == "admin_back")
async def admin_back(callback: CallbackQuery):
"""Вернуться в главное меню админки"""
if not is_admin(callback.from_user.id):
return
async with async_session_maker() as session:
active_model = await AIModelService.get_active_model(session)
active_name = active_model.display_name if active_model else "Не выбрана"
text = (
"🔧 <b>Админ-панель</b>\n\n"
f"🤖 Текущая AI модель: <b>{active_name}</b>"
)
await callback.message.edit_text(text, reply_markup=get_admin_main_keyboard())
await callback.answer()
@router.callback_query(F.data == "admin_models")
async def admin_models(callback: CallbackQuery):
"""Показать список моделей"""
if not is_admin(callback.from_user.id):
await callback.answer("⛔ Доступ запрещен", show_alert=True)
return
async with async_session_maker() as session:
active_model = await AIModelService.get_active_model(session)
active_name = active_model.display_name if active_model else "Не выбрана"
text = (
"🤖 <b>Настройка AI модели</b>\n\n"
f"Текущая модель: <b>{active_name}</b>\n\n"
"Выберите модель:"
)
keyboard = await get_model_keyboard()
await callback.message.edit_text(text, reply_markup=keyboard)
await callback.answer()
@router.callback_query(F.data.startswith("admin_model_"))
async def set_admin_model(callback: CallbackQuery):
"""Установить AI модель"""
if not is_admin(callback.from_user.id):
await callback.answer("⛔ Доступ запрещен", show_alert=True)
return
model_id = int(callback.data.split("_")[-1])
async with async_session_maker() as session:
success = await AIModelService.set_active_model(session, model_id)
if success:
active_model = await AIModelService.get_active_model(session)
await callback.answer(f"✅ Модель изменена: {active_model.display_name}")
text = (
"🤖 <b>Настройка AI модели</b>\n\n"
f"Текущая модель: <b>{active_model.display_name}</b>\n\n"
"Выберите модель:"
)
else:
await callback.answer("❌ Ошибка при смене модели", show_alert=True)
text = "🤖 <b>Настройка AI модели</b>\n\n❌ Ошибка при смене модели"
keyboard = await get_model_keyboard()
await callback.message.edit_text(text, reply_markup=keyboard)
@router.callback_query(F.data == "admin_generate_wod")
async def admin_generate_wod(callback: CallbackQuery):
"""Генерация слов дня через кнопку"""
if not is_admin(callback.from_user.id):
await callback.answer("⛔ Доступ запрещен", show_alert=True)
return
await callback.answer()
await callback.message.edit_text("⏳ Генерирую слова дня...")
from services.wordofday_service import wordofday_service
try:
results = await wordofday_service.generate_all_words_for_today()
total = results.get("en", 0) + results.get("ja", 0)
errors = results.get("errors", 0)
text = (
"✅ <b>Генерация завершена</b>\n\n"
f"📊 Всего сгенерировано: {total}\n"
f"🇬🇧 Английский: {results.get('en', 0)}\n"
f"🇯🇵 Японский: {results.get('ja', 0)}\n"
f"❌ Ошибок: {errors}"
)
except Exception as e:
text = f"❌ Ошибка генерации: {e}"
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="⬅️ Назад", callback_data="admin_back")]
])
await callback.message.edit_text(text, reply_markup=keyboard)
@router.callback_query(F.data == "admin_view_wod")
async def admin_view_wod(callback: CallbackQuery):
"""Просмотр всех слов дня за сегодня"""
if not is_admin(callback.from_user.id):
await callback.answer("⛔ Доступ запрещен", show_alert=True)
return
await callback.answer()
from datetime import datetime
from sqlalchemy import select
from database.models import WordOfDay
today = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
async with async_session_maker() as session:
result = await session.execute(
select(WordOfDay).where(WordOfDay.date == today).order_by(WordOfDay.learning_lang, WordOfDay.level)
)
words = result.scalars().all()
if not words:
text = "📋 <b>Слова дня</b>\n\n❌ Слова на сегодня ещё не сгенерированы"
else:
text = f"📋 <b>Слова дня</b> ({today.strftime('%d.%m.%Y')})\n\n"
current_lang = None
for wod in words:
if wod.learning_lang != current_lang:
current_lang = wod.learning_lang
lang_emoji = "🇬🇧" if current_lang == "en" else "🇯🇵"
text += f"\n{lang_emoji} <b>{current_lang.upper()}</b>\n"
text += f"• <b>{wod.level}</b>: {wod.word}"
if wod.transcription:
text += f" [{wod.transcription}]"
text += f"{wod.translation}\n"
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="⬅️ Назад", callback_data="admin_back")]
])
await callback.message.edit_text(text, reply_markup=keyboard)
@router.callback_query(F.data == "admin_close")
async def admin_close(callback: CallbackQuery):
"""Закрыть админ-панель"""
if not is_admin(callback.from_user.id):
return
await callback.message.delete()
await callback.answer()
@router.message(Command("generate_wod"))
async def cmd_generate_wod(message: Message):
"""Принудительная генерация слов дня (команда)"""
if not is_admin(message.from_user.id):
return
from services.wordofday_service import wordofday_service
await message.answer("⏳ Запускаю генерацию слов дня...")
try:
results = await wordofday_service.generate_all_words_for_today()
total = results.get("en", 0) + results.get("ja", 0)
errors = results.get("errors", 0)
text = (
"✅ <b>Генерация завершена</b>\n\n"
f"📊 Всего сгенерировано: {total}\n"
f"🇬🇧 Английский: {results.get('en', 0)}\n"
f"🇯🇵 Японский: {results.get('ja', 0)}\n"
f"❌ Ошибок: {errors}"
)
except Exception as e:
text = f"❌ Ошибка генерации: {e}"
await message.answer(text)