194 lines
6.9 KiB
Python
194 lines
6.9 KiB
Python
"""
|
||
Bot handlers
|
||
"""
|
||
|
||
import logging
|
||
from typing import Optional
|
||
|
||
from aiogram import F, types
|
||
from aiogram.filters import CommandStart, Command
|
||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message, WebAppInfo
|
||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||
|
||
from config import config
|
||
from utils import (
|
||
parse_startapp_parameter,
|
||
get_welcome_message,
|
||
validate_reward_amount,
|
||
validate_quiz_id,
|
||
)
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def create_main_keyboard(startapp_param: Optional[str] = None) -> InlineKeyboardMarkup:
|
||
"""Create main keyboard with mini app button"""
|
||
builder = InlineKeyboardBuilder()
|
||
|
||
# Mini app URL with startapp parameter
|
||
mini_app_url = config.frontend_url
|
||
if startapp_param:
|
||
mini_app_url = f"{config.frontend_url}?startapp={startapp_param}"
|
||
|
||
builder.row(
|
||
InlineKeyboardButton(
|
||
text="🎯 Открыть Викторины",
|
||
web_app=WebAppInfo(url=mini_app_url)
|
||
)
|
||
)
|
||
|
||
builder.row(
|
||
InlineKeyboardButton(
|
||
text="📊 Статистика",
|
||
callback_data="stats"
|
||
)
|
||
)
|
||
|
||
return builder.as_markup()
|
||
|
||
|
||
async def handle_start_command(message: Message) -> None:
|
||
"""Handle /start command"""
|
||
startapp_param = None
|
||
|
||
# Extract startapp parameter from command arguments
|
||
if message.text and len(message.text.split()) > 1:
|
||
startapp_param = message.text.split(maxsplit=1)[1]
|
||
|
||
# Parse the startapp parameter
|
||
try:
|
||
parsed_param = parse_startapp_parameter(startapp_param)
|
||
|
||
# Validate parameters
|
||
if parsed_param["type"] == "reward":
|
||
amount = parsed_param.get("amount", 0)
|
||
if not validate_reward_amount(amount):
|
||
logger.warning(f"Invalid reward amount: {amount}")
|
||
parsed_param = {"type": "main"}
|
||
|
||
elif parsed_param["type"] == "quiz":
|
||
quiz_id = parsed_param.get("quiz_id", "")
|
||
if not validate_quiz_id(quiz_id):
|
||
logger.warning(f"Invalid quiz ID: {quiz_id}")
|
||
parsed_param = {"type": "main"}
|
||
|
||
# Get welcome message
|
||
welcome_text = get_welcome_message(parsed_param)
|
||
|
||
# Log the start event
|
||
logger.info(
|
||
f"User {message.from_user.id} started bot with param: {startapp_param}, "
|
||
f"parsed as: {parsed_param}"
|
||
)
|
||
|
||
# Send welcome message with keyboard
|
||
keyboard = create_main_keyboard(startapp_param)
|
||
await message.answer(welcome_text, reply_markup=keyboard)
|
||
|
||
except Exception as e:
|
||
logger.error(f"Error handling start command: {e}")
|
||
# Fallback to main message
|
||
fallback_text = get_welcome_message({"type": "main"})
|
||
keyboard = create_main_keyboard()
|
||
await message.answer(fallback_text, reply_markup=keyboard)
|
||
|
||
|
||
async def handle_text_message(message: Message) -> None:
|
||
"""Handle text messages"""
|
||
text = message.text.lower()
|
||
|
||
if any(word in text for word in ["викторина", "опрос", "тест"]):
|
||
await message.answer(
|
||
"🎯 Хотите пройти викторину? Нажмите на кнопку ниже!",
|
||
reply_markup=create_main_keyboard()
|
||
)
|
||
elif any(word in text for word in ["звезд", "балл", "монет"]):
|
||
await message.answer(
|
||
"⭐ Узнайте свой баланс и потратьте звёзды в мини-приложении!",
|
||
reply_markup=create_main_keyboard()
|
||
)
|
||
elif any(word in text for word in ["магазин", "приз", "подарок"]):
|
||
await message.answer(
|
||
"🛒 Загляните в наш магазин призов!",
|
||
reply_markup=create_main_keyboard()
|
||
)
|
||
else:
|
||
await message.answer(
|
||
"🌟 Я бот для управления викторинами! Используйте кнопки ниже для доступа к мини-приложению.",
|
||
reply_markup=create_main_keyboard()
|
||
)
|
||
|
||
|
||
async def handle_stats_callback(callback: types.CallbackQuery) -> None:
|
||
"""Handle stats button click"""
|
||
await callback.answer("Статистика доступна в мини-приложении!", show_alert=True)
|
||
|
||
|
||
async def handle_help_command(message: Message) -> None:
|
||
"""Handle /help command"""
|
||
help_text = """
|
||
🌟 <b>Звёздные Викторины - Помощь</b>
|
||
|
||
🎯 <b>Как начать:</b>
|
||
Нажмите на кнопку "Открыть Викторины" и начните проходить викторины!
|
||
|
||
🎁 <b>Как получить звёзды:</b>
|
||
• Проходите викторины
|
||
• Сканируйте QR-коды
|
||
• Участвуйте в акциях
|
||
|
||
🛒 <b>Как потратить звёзды:</b>
|
||
• Обменивайте на призы в магазине
|
||
• Получайте скидки и бонусы
|
||
|
||
📱 <b>QR-коды:</b>
|
||
• Сканируйте QR-коды через камеру телефона
|
||
• Или используйте встроенный сканер в приложении
|
||
|
||
🔗 <b>Deep Links:</b>
|
||
• `reward_X` - получить X звёзд
|
||
• `quiz_X` - открыть викторину X
|
||
• `shop` - перейти в магазин
|
||
|
||
❓ <b>Вопросы?</b>
|
||
Используйте кнопки ниже для доступа к мини-приложению!
|
||
"""
|
||
|
||
await message.answer(help_text, reply_markup=create_main_keyboard())
|
||
|
||
|
||
async def handle_unknown_command(message: Message) -> None:
|
||
"""Handle unknown commands"""
|
||
await message.answer(
|
||
"❌ Неизвестная команда. Используйте /help для получения помощи.",
|
||
reply_markup=create_main_keyboard()
|
||
)
|
||
|
||
|
||
async def handle_qr_info_command(message: Message) -> None:
|
||
"""Handle /qr command for QR information"""
|
||
info_text = """
|
||
🎫 <b>Информация о QR-кодах</b>
|
||
|
||
🔒 <b>Система безопасности:</b>
|
||
• QR-коды содержат уникальные токены
|
||
• Каждый токен одноразовый
|
||
• Срок действия - 30 дней
|
||
• Проверка на стороне сервера
|
||
|
||
🎯 <b>Типы QR-кодов:</b>
|
||
• 💰 <b>reward</b> - начисление звёзд
|
||
• 🧠 <b>quiz</b> - открытие викторины
|
||
• 🛒 <b>shop</b> - действия в магазине
|
||
|
||
📱 <b>Как использовать:</b>
|
||
1. Администратор генерирует QR-коды
|
||
2. QR-коды размещаются в нужных местах
|
||
3. Пользователи сканируют их через приложение
|
||
4. Приложение отправляет токен на валидацию
|
||
|
||
⚡ <b>Для администраторов:</b>
|
||
Используйте /admin для генерации QR-кодов
|
||
"""
|
||
|
||
await message.answer(info_text, reply_markup=create_main_keyboard()) |