""" Admin handlers for QR code management """ import logging from typing import Optional from aiogram import F, types from aiogram.filters import Command from aiogram.types import ( InlineKeyboardButton, InlineKeyboardMarkup, Message, CallbackQuery, ) from aiogram.utils.keyboard import InlineKeyboardBuilder from config import config from qr_service import QRService logger = logging.getLogger(__name__) def create_admin_keyboard() -> InlineKeyboardMarkup: """Create admin keyboard""" builder = InlineKeyboardBuilder() builder.row( InlineKeyboardButton(text="🎫 Генерировать QR-коды", callback_data="admin_generate_qr") ) builder.row( InlineKeyboardButton(text="📊 Статистика", callback_data="admin_stats") ) builder.row( InlineKeyboardButton(text="🔧 Настройки", callback_data="admin_settings") ) return builder.as_markup() def create_qr_type_keyboard() -> InlineKeyboardMarkup: """Create QR type selection keyboard""" builder = InlineKeyboardBuilder() builder.row( InlineKeyboardButton(text="💰 Награда", callback_data="qr_type_reward") ) builder.row( InlineKeyboardButton(text="🧠 Викторина", callback_data="qr_type_quiz") ) builder.row( InlineKeyboardButton(text="🛒 Магазин", callback_data="qr_type_shop") ) builder.row( InlineKeyboardButton(text="❌ Отмена", callback_data="admin_cancel") ) return builder.as_markup() def create_main_keyboard() -> InlineKeyboardMarkup: """Create main keyboard with mini app button""" builder = InlineKeyboardBuilder() builder.row( InlineKeyboardButton( text="🎯 Открыть Викторины", web_app=types.WebAppInfo(url=config.frontend_url) ) ) return builder.as_markup() async def handle_admin_command(message: Message) -> None: """Handle /admin command""" if not config.has_admin_privileges(message.from_user.id): await message.answer( "❌ У вас нет прав для доступа к панели администратора." ) return user_role = "Администратор" if config.is_admin(message.from_user.id) else "Оператор" await message.answer( f"🛡️ Панель администратора\n\n" f"👤 Ваша роль: {user_role}\n" f"🆔 ID: {message.from_user.id}\n\n" f"Выберите действие:", reply_markup=create_admin_keyboard() ) async def handle_generate_qr_callback(callback: CallbackQuery) -> None: """Handle generate QR callback""" if not config.has_admin_privileges(callback.from_user.id): await callback.answer("❌ Доступ запрещен", show_alert=True) return await callback.message.edit_text( "🎫 Выберите тип QR-кода для генерации:", reply_markup=create_qr_type_keyboard() ) await callback.answer() async def handle_qr_type_callback(callback: CallbackQuery) -> None: """Handle QR type selection callback""" if not config.has_admin_privileges(callback.from_user.id): await callback.answer("❌ Доступ запрещен", show_alert=True) return qr_type = callback.data.split("_")[-1] type_descriptions = { "reward": "💰 Награда (звёзды)", "quiz": "🧠 Викторина", "shop": "🛒 Магазин" } # Store the selected type in user state # For simplicity, we'll use a simple approach. In production, use a proper state machine instructions = { "reward": "Введите сумму награды в звёздах (1-1000):", "quiz": "Введите ID викторины:", "shop": "Введите действие для магазина (например: discount_10):" } await callback.message.edit_text( f"🎫 {type_descriptions.get(qr_type, qr_type)}\n\n" f"{instructions.get(qr_type)}", reply_markup=types.InlineKeyboardMarkup( inline_keyboard=[ [types.InlineKeyboardButton(text="❌ Отмена", callback_data="admin_cancel")] ] ) ) await callback.answer() async def handle_qr_generation_text(message: Message) -> None: """Handle QR generation text input""" if not config.has_admin_privileges(message.from_user.id): await message.answer("❌ Доступ запрещен") return # This is a simplified approach. In production, use proper state management text = message.text.strip() # Try to determine the type based on context # For now, we'll assume it's a reward if it's a number try: amount = int(text) if 1 <= amount <= 1000: # Generate reward QR codes await generate_reward_qr_codes(message, amount) return except ValueError: pass # If not a number, ask for clarification await message.answer( "🎫 Пожалуйста, уточните тип QR-кода:\n\n" "1. Для награды: введите число (1-1000)\n" "2. Для викторины: введите 'quiz ID' (например: quiz 123)\n" "3. Для магазина: введите 'shop действие' (например: shop discount_10)\n\n" "Или используйте /admin для выбора типа", reply_markup=create_admin_keyboard() ) async def generate_reward_qr_codes(message: Message, amount: int, count: int = 5) -> None: """Generate reward QR codes""" async with QRService() as qr_service: try: is_valid, error_msg = qr_service.validate_qr_request("reward", str(amount), count) if not is_valid: await message.answer(f"❌ {error_msg}") return tokens = await qr_service.generate_qr_codes("reward", str(amount), count) response_text = qr_service.format_qr_examples( tokens, "reward", f"QR-коды для награды {amount} ⭐" ) await message.answer( response_text, reply_markup=create_admin_keyboard() ) except Exception as e: logger.error(f"Error generating QR codes: {e}") await message.answer( f"❌ Ошибка при генерации QR-кодов: {e}", reply_markup=create_admin_keyboard() ) async def handle_admin_cancel_callback(callback: CallbackQuery) -> None: """Handle admin cancel callback""" await callback.message.edit_text( "❌ Операция отменена", reply_markup=create_admin_keyboard() ) await callback.answer() async def handle_admin_stats_callback(callback: CallbackQuery) -> None: """Handle admin stats callback""" if not config.has_admin_privileges(callback.from_user.id): await callback.answer("❌ Доступ запрещен", show_alert=True) return # Placeholder for stats await callback.answer("📊 Статистика в разработке", show_alert=True) async def handle_admin_settings_callback(callback: CallbackQuery) -> None: """Handle admin settings callback""" if not config.is_admin(callback.from_user.id): await callback.answer("❌ Только администраторы могут менять настройки", show_alert=True) return # Placeholder for settings await callback.answer("🔧 Настройки в разработке", show_alert=True)