From f2c4f7031ece2cd5156d751bdfc7cba477ef76a6 Mon Sep 17 00:00:00 2001 From: "mamonov.ep" Date: Wed, 10 Dec 2025 11:05:11 +0300 Subject: [PATCH] =?UTF-8?q?refactor:=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD-?= =?UTF-8?q?=D0=BF=D0=B0=D0=BD=D0=B5=D0=BB=D1=8C=20=D1=81=20=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=8E=20=D0=B8=20=D0=BF=D1=80=D0=BE=D1=81=D0=BC=D0=BE?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=BC=20=D1=81=D0=BB=D0=BE=D0=B2=20=D0=B4?= =?UTF-8?q?=D0=BD=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Главное меню: настройка модели, генерация слов дня, просмотр слов - Кнопка "Слова дня (сегодня)" показывает все сгенерированные слова - Навигация между разделами 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- bot/handlers/admin.py | 147 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 137 insertions(+), 10 deletions(-) diff --git a/bot/handlers/admin.py b/bot/handlers/admin.py index f3c7224..9461e27 100644 --- a/bot/handlers/admin.py +++ b/bot/handlers/admin.py @@ -22,6 +22,16 @@ 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: @@ -36,7 +46,7 @@ async def get_model_keyboard() -> InlineKeyboardMarkup: callback_data=f"admin_model_{model.id}" )]) - keyboard.append([InlineKeyboardButton(text="❌ Закрыть", callback_data="admin_close")]) + keyboard.append([InlineKeyboardButton(text="⬅️ Назад", callback_data="admin_back")]) return InlineKeyboardMarkup(inline_keyboard=keyboard) @@ -46,7 +56,6 @@ 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) @@ -55,12 +64,53 @@ async def cmd_admin(message: Message): text = ( "🔧 Админ-панель\n\n" - f"🤖 Текущая AI модель: {active_name}\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 message.answer(text, reply_markup=keyboard) + await callback.message.edit_text(text, reply_markup=keyboard) + await callback.answer() @router.callback_query(F.data.startswith("admin_model_")) @@ -80,18 +130,95 @@ async def set_admin_model(callback: CallbackQuery): await callback.answer(f"✅ Модель изменена: {active_model.display_name}") text = ( - "🔧 Админ-панель\n\n" - f"🤖 Текущая AI модель: {active_model.display_name}\n\n" - "Выберите модель для генерации:" + "🤖 Настройка AI модели\n\n" + f"Текущая модель: {active_model.display_name}\n\n" + "Выберите модель:" ) else: await callback.answer("❌ Ошибка при смене модели", show_alert=True) - text = "🔧 Админ-панель\n\n❌ Ошибка при смене модели" + 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): """Закрыть админ-панель""" @@ -104,7 +231,7 @@ async def admin_close(callback: CallbackQuery): @router.message(Command("generate_wod")) async def cmd_generate_wod(message: Message): - """Принудительная генерация слов дня""" + """Принудительная генерация слов дня (команда)""" if not is_admin(message.from_user.id): return