2025-12-16 20:06:16 +07:00
|
|
|
|
import logging
|
|
|
|
|
|
|
2025-12-16 20:19:45 +07:00
|
|
|
|
from aiogram import Router, F, Bot
|
2025-12-16 20:06:16 +07:00
|
|
|
|
from aiogram.filters import CommandStart, Command, CommandObject
|
|
|
|
|
|
from aiogram.types import Message
|
|
|
|
|
|
|
2025-12-16 20:19:45 +07:00
|
|
|
|
from config import settings
|
2025-12-16 20:06:16 +07:00
|
|
|
|
from keyboards.main_menu import get_main_menu
|
|
|
|
|
|
from services.api_client import api_client
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
router = Router()
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-12-16 20:19:45 +07:00
|
|
|
|
async def get_user_avatar_url(bot: Bot, user_id: int) -> str | None:
|
|
|
|
|
|
"""Get user's Telegram profile photo URL."""
|
|
|
|
|
|
try:
|
|
|
|
|
|
photos = await bot.get_user_profile_photos(user_id, limit=1)
|
|
|
|
|
|
if photos.total_count > 0 and photos.photos:
|
|
|
|
|
|
# Get the largest photo (last in the list)
|
|
|
|
|
|
photo = photos.photos[0][-1]
|
|
|
|
|
|
file = await bot.get_file(photo.file_id)
|
|
|
|
|
|
if file.file_path:
|
|
|
|
|
|
return f"https://api.telegram.org/file/bot{settings.TELEGRAM_BOT_TOKEN}/{file.file_path}"
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.warning(f"[START] Could not get user avatar: {e}")
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-12-16 20:06:16 +07:00
|
|
|
|
@router.message(CommandStart())
|
|
|
|
|
|
async def cmd_start(message: Message, command: CommandObject):
|
|
|
|
|
|
"""Handle /start command with or without deep link."""
|
|
|
|
|
|
logger.info(f"[START] ==================== START COMMAND ====================")
|
|
|
|
|
|
logger.info(f"[START] Telegram user: id={message.from_user.id}, username=@{message.from_user.username}")
|
|
|
|
|
|
logger.info(f"[START] Full message text: '{message.text}'")
|
|
|
|
|
|
logger.info(f"[START] Deep link args (command.args): '{command.args}'")
|
|
|
|
|
|
|
|
|
|
|
|
# Check if there's a deep link token (for account linking)
|
|
|
|
|
|
token = command.args
|
|
|
|
|
|
if token:
|
|
|
|
|
|
logger.info(f"[START] -------- TOKEN RECEIVED --------")
|
|
|
|
|
|
logger.info(f"[START] Token: {token}")
|
|
|
|
|
|
logger.info(f"[START] Token length: {len(token)} chars")
|
|
|
|
|
|
|
2025-12-16 20:19:45 +07:00
|
|
|
|
# Get user's avatar
|
|
|
|
|
|
avatar_url = await get_user_avatar_url(message.bot, message.from_user.id)
|
|
|
|
|
|
logger.info(f"[START] User avatar URL: {avatar_url}")
|
|
|
|
|
|
|
2025-12-16 20:06:16 +07:00
|
|
|
|
logger.info(f"[START] -------- CALLING API --------")
|
|
|
|
|
|
logger.info(f"[START] Sending to /telegram/confirm-link:")
|
|
|
|
|
|
logger.info(f"[START] - token: {token}")
|
|
|
|
|
|
logger.info(f"[START] - telegram_id: {message.from_user.id}")
|
|
|
|
|
|
logger.info(f"[START] - telegram_username: {message.from_user.username}")
|
2025-12-16 20:19:45 +07:00
|
|
|
|
logger.info(f"[START] - telegram_first_name: {message.from_user.first_name}")
|
|
|
|
|
|
logger.info(f"[START] - telegram_last_name: {message.from_user.last_name}")
|
|
|
|
|
|
logger.info(f"[START] - telegram_avatar_url: {avatar_url}")
|
2025-12-16 20:06:16 +07:00
|
|
|
|
|
|
|
|
|
|
result = await api_client.confirm_telegram_link(
|
|
|
|
|
|
token=token,
|
|
|
|
|
|
telegram_id=message.from_user.id,
|
2025-12-16 20:19:45 +07:00
|
|
|
|
telegram_username=message.from_user.username,
|
|
|
|
|
|
telegram_first_name=message.from_user.first_name,
|
|
|
|
|
|
telegram_last_name=message.from_user.last_name,
|
|
|
|
|
|
telegram_avatar_url=avatar_url
|
2025-12-16 20:06:16 +07:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
logger.info(f"[START] -------- API RESPONSE --------")
|
|
|
|
|
|
logger.info(f"[START] Response: {result}")
|
|
|
|
|
|
logger.info(f"[START] Success: {result.get('success')}")
|
|
|
|
|
|
|
|
|
|
|
|
if result.get("success"):
|
|
|
|
|
|
user_nickname = result.get("nickname", "пользователь")
|
|
|
|
|
|
logger.info(f"[START] ✅ LINK SUCCESS! User '{user_nickname}' linked to telegram_id={message.from_user.id}")
|
|
|
|
|
|
await message.answer(
|
|
|
|
|
|
f"<b>Аккаунт успешно привязан!</b>\n\n"
|
|
|
|
|
|
f"Привет, <b>{user_nickname}</b>!\n\n"
|
|
|
|
|
|
f"Теперь ты будешь получать уведомления о:\n"
|
|
|
|
|
|
f"• Начале и окончании событий (Golden Hour, Jackpot и др.)\n"
|
|
|
|
|
|
f"• Старте и завершении марафонов\n"
|
|
|
|
|
|
f"• Спорах по твоим заданиям\n\n"
|
|
|
|
|
|
f"Используй меню ниже для навигации:",
|
|
|
|
|
|
reply_markup=get_main_menu()
|
|
|
|
|
|
)
|
|
|
|
|
|
return
|
|
|
|
|
|
else:
|
|
|
|
|
|
error = result.get("error", "Неизвестная ошибка")
|
|
|
|
|
|
logger.error(f"[START] ❌ LINK FAILED!")
|
|
|
|
|
|
logger.error(f"[START] Error: {error}")
|
|
|
|
|
|
logger.error(f"[START] Token was: {token}")
|
|
|
|
|
|
await message.answer(
|
|
|
|
|
|
f"<b>Ошибка привязки аккаунта</b>\n\n"
|
|
|
|
|
|
f"{error}\n\n"
|
|
|
|
|
|
f"Попробуй получить новую ссылку на сайте.",
|
|
|
|
|
|
reply_markup=get_main_menu()
|
|
|
|
|
|
)
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# No token - regular start
|
|
|
|
|
|
logger.info(f"[START] No token, checking if user is already linked...")
|
|
|
|
|
|
user = await api_client.get_user_by_telegram_id(message.from_user.id)
|
|
|
|
|
|
logger.info(f"[START] API response: {user}")
|
|
|
|
|
|
|
|
|
|
|
|
if user:
|
|
|
|
|
|
await message.answer(
|
|
|
|
|
|
f"<b>С возвращением, {user.get('nickname', 'игрок')}!</b>\n\n"
|
|
|
|
|
|
f"Твой аккаунт привязан. Используй меню для навигации:",
|
|
|
|
|
|
reply_markup=get_main_menu()
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
await message.answer(
|
|
|
|
|
|
"<b>Добро пожаловать в Game Marathon Bot!</b>\n\n"
|
|
|
|
|
|
"Этот бот поможет тебе следить за марафонами и "
|
|
|
|
|
|
"получать уведомления о важных событиях.\n\n"
|
|
|
|
|
|
"<b>Для начала работы:</b>\n"
|
|
|
|
|
|
"1. Зайди на сайт в настройки профиля\n"
|
|
|
|
|
|
"2. Нажми кнопку «Привязать Telegram»\n"
|
|
|
|
|
|
"3. Перейди по полученной ссылке\n\n"
|
|
|
|
|
|
"После привязки ты сможешь:\n"
|
|
|
|
|
|
"• Смотреть свои марафоны\n"
|
|
|
|
|
|
"• Получать уведомления о событиях\n"
|
|
|
|
|
|
"• Следить за статистикой",
|
|
|
|
|
|
reply_markup=get_main_menu()
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.message(Command("help"))
|
|
|
|
|
|
@router.message(F.text == "❓ Помощь")
|
|
|
|
|
|
async def cmd_help(message: Message):
|
|
|
|
|
|
"""Handle /help command."""
|
|
|
|
|
|
await message.answer(
|
|
|
|
|
|
"<b>Справка по командам:</b>\n\n"
|
|
|
|
|
|
"/start - Начать работу с ботом\n"
|
|
|
|
|
|
"/marathons - Мои марафоны\n"
|
|
|
|
|
|
"/stats - Моя статистика\n"
|
|
|
|
|
|
"/settings - Настройки уведомлений\n"
|
|
|
|
|
|
"/help - Эта справка\n\n"
|
|
|
|
|
|
"<b>Уведомления:</b>\n"
|
|
|
|
|
|
"Бот присылает уведомления о:\n"
|
|
|
|
|
|
"• 🌟 Golden Hour - очки x1.5\n"
|
|
|
|
|
|
"• 🎰 Jackpot - очки x3\n"
|
|
|
|
|
|
"• ⚡ Double Risk - половина очков, дропы бесплатны\n"
|
|
|
|
|
|
"• 👥 Common Enemy - общий челлендж\n"
|
|
|
|
|
|
"• 🚀 Старт/финиш марафонов\n"
|
|
|
|
|
|
"• ⚠️ Споры по заданиям",
|
|
|
|
|
|
reply_markup=get_main_menu()
|
|
|
|
|
|
)
|