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 = ( "🔧 Админ-панель\n\n" f"🤖 Текущая AI модель: {active_name}" ) 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 = ( "🔧 Админ-панель\n\n" f"🤖 Текущая AI модель: {active_name}" ) 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 = ( "🤖 Настройка AI модели\n\n" f"Текущая модель: {active_name}\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 = ( "🤖 Настройка AI модели\n\n" f"Текущая модель: {active_model.display_name}\n\n" "Выберите модель:" ) else: await callback.answer("❌ Ошибка при смене модели", show_alert=True) text = "🤖 Настройка AI модели\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 = ( "✅ Генерация завершена\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 = "📋 Слова дня\n\n❌ Слова на сегодня ещё не сгенерированы" else: text = f"📋 Слова дня ({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} {current_lang.upper()}\n" text += f"• {wod.level}: {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 = ( "✅ Генерация завершена\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)