feat: мульти-провайдер AI, выбор типов заданий, настройка количества
- Добавлена поддержка нескольких AI провайдеров (OpenAI, Google Gemini) - Добавлена админ-панель (/admin) для переключения AI моделей - Добавлен AIModelService для управления моделями в БД - Добавлен выбор типа заданий (микс, перевод слов, подстановка, перевод предложений) - Добавлена настройка количества заданий (5-15) - ai_service динамически выбирает провайдера на основе активной модели - Обработка ограничений моделей (temperature, response_format) - Очистка markdown обёртки из ответов Gemini 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
102
bot/handlers/admin.py
Normal file
102
bot/handlers/admin.py
Normal file
@@ -0,0 +1,102 @@
|
||||
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()
|
||||
|
||||
|
||||
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_close")])
|
||||
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>\n\n"
|
||||
"Выберите модель для генерации:"
|
||||
)
|
||||
|
||||
keyboard = await get_model_keyboard()
|
||||
await message.answer(text, reply_markup=keyboard)
|
||||
|
||||
|
||||
@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>Админ-панель</b>\n\n"
|
||||
f"🤖 Текущая AI модель: <b>{active_model.display_name}</b>\n\n"
|
||||
"Выберите модель для генерации:"
|
||||
)
|
||||
else:
|
||||
await callback.answer("❌ Ошибка при смене модели", show_alert=True)
|
||||
text = "🔧 <b>Админ-панель</b>\n\n❌ Ошибка при смене модели"
|
||||
|
||||
keyboard = await get_model_keyboard()
|
||||
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()
|
||||
Reference in New Issue
Block a user