"""
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 = """
π ΠΠ²ΡΠ·Π΄Π½ΡΠ΅ ΠΠΈΠΊΡΠΎΡΠΈΠ½Ρ - ΠΠΎΠΌΠΎΡΡ
π― ΠΠ°ΠΊ Π½Π°ΡΠ°ΡΡ:
ΠΠ°ΠΆΠΌΠΈΡΠ΅ Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡ "ΠΡΠΊΡΡΡΡ ΠΠΈΠΊΡΠΎΡΠΈΠ½Ρ" ΠΈ Π½Π°ΡΠ½ΠΈΡΠ΅ ΠΏΡΠΎΡ
ΠΎΠ΄ΠΈΡΡ Π²ΠΈΠΊΡΠΎΡΠΈΠ½Ρ!
π ΠΠ°ΠΊ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π·Π²ΡΠ·Π΄Ρ:
β’ ΠΡΠΎΡ
ΠΎΠ΄ΠΈΡΠ΅ Π²ΠΈΠΊΡΠΎΡΠΈΠ½Ρ
β’ Π‘ΠΊΠ°Π½ΠΈΡΡΠΉΡΠ΅ QR-ΠΊΠΎΠ΄Ρ
β’ Π£ΡΠ°ΡΡΠ²ΡΠΉΡΠ΅ Π² Π°ΠΊΡΠΈΡΡ
π ΠΠ°ΠΊ ΠΏΠΎΡΡΠ°ΡΠΈΡΡ Π·Π²ΡΠ·Π΄Ρ:
β’ ΠΠ±ΠΌΠ΅Π½ΠΈΠ²Π°ΠΉΡΠ΅ Π½Π° ΠΏΡΠΈΠ·Ρ Π² ΠΌΠ°Π³Π°Π·ΠΈΠ½Π΅
β’ ΠΠΎΠ»ΡΡΠ°ΠΉΡΠ΅ ΡΠΊΠΈΠ΄ΠΊΠΈ ΠΈ Π±ΠΎΠ½ΡΡΡ
π± QR-ΠΊΠΎΠ΄Ρ:
β’ Π‘ΠΊΠ°Π½ΠΈΡΡΠΉΡΠ΅ QR-ΠΊΠΎΠ΄Ρ ΡΠ΅ΡΠ΅Π· ΠΊΠ°ΠΌΠ΅ΡΡ ΡΠ΅Π»Π΅ΡΠΎΠ½Π°
β’ ΠΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠΉ ΡΠΊΠ°Π½Π΅Ρ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ
π Deep Links:
β’ `reward_X` - ΠΏΠΎΠ»ΡΡΠΈΡΡ X Π·Π²ΡΠ·Π΄
β’ `quiz_X` - ΠΎΡΠΊΡΡΡΡ Π²ΠΈΠΊΡΠΎΡΠΈΠ½Ρ X
β’ `shop` - ΠΏΠ΅ΡΠ΅ΠΉΡΠΈ Π² ΠΌΠ°Π³Π°Π·ΠΈΠ½
β ΠΠΎΠΏΡΠΎΡΡ?
ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ ΠΊΠ½ΠΎΠΏΠΊΠΈ Π½ΠΈΠΆΠ΅ Π΄Π»Ρ Π΄ΠΎΡΡΡΠΏΠ° ΠΊ ΠΌΠΈΠ½ΠΈ-ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ!
"""
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 = """
π« ΠΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ QR-ΠΊΠΎΠ΄Π°Ρ
π Π‘ΠΈΡΡΠ΅ΠΌΠ° Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ:
β’ QR-ΠΊΠΎΠ΄Ρ ΡΠΎΠ΄Π΅ΡΠΆΠ°Ρ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠ΅ ΡΠΎΠΊΠ΅Π½Ρ
β’ ΠΠ°ΠΆΠ΄ΡΠΉ ΡΠΎΠΊΠ΅Π½ ΠΎΠ΄Π½ΠΎΡΠ°Π·ΠΎΠ²ΡΠΉ
β’ Π‘ΡΠΎΠΊ Π΄Π΅ΠΉΡΡΠ²ΠΈΡ - 30 Π΄Π½Π΅ΠΉ
β’ ΠΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ ΡΠ΅ΡΠ²Π΅ΡΠ°
π― Π’ΠΈΠΏΡ QR-ΠΊΠΎΠ΄ΠΎΠ²:
β’ π° reward - Π½Π°ΡΠΈΡΠ»Π΅Π½ΠΈΠ΅ Π·Π²ΡΠ·Π΄
β’ π§ quiz - ΠΎΡΠΊΡΡΡΠΈΠ΅ Π²ΠΈΠΊΡΠΎΡΠΈΠ½Ρ
β’ π shop - Π΄Π΅ΠΉΡΡΠ²ΠΈΡ Π² ΠΌΠ°Π³Π°Π·ΠΈΠ½Π΅
π± ΠΠ°ΠΊ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ:
1. ΠΠ΄ΠΌΠΈΠ½ΠΈΡΡΡΠ°ΡΠΎΡ Π³Π΅Π½Π΅ΡΠΈΡΡΠ΅Ρ QR-ΠΊΠΎΠ΄Ρ
2. QR-ΠΊΠΎΠ΄Ρ ΡΠ°Π·ΠΌΠ΅ΡΠ°ΡΡΡΡ Π² Π½ΡΠΆΠ½ΡΡ
ΠΌΠ΅ΡΡΠ°Ρ
3. ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΠΈ ΡΠΊΠ°Π½ΠΈΡΡΡΡ ΠΈΡ
ΡΠ΅ΡΠ΅Π· ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅
4. ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅Ρ ΡΠΎΠΊΠ΅Π½ Π½Π° Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡ
β‘ ΠΠ»Ρ Π°Π΄ΠΌΠΈΠ½ΠΈΡΡΡΠ°ΡΠΎΡΠΎΠ²:
ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ /admin Π΄Π»Ρ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠΈ QR-ΠΊΠΎΠ΄ΠΎΠ²
"""
await message.answer(info_text, reply_markup=create_main_keyboard())