263 lines
9.5 KiB
Python
263 lines
9.5 KiB
Python
from aiogram import Router, F
|
||
from aiogram.filters import Command
|
||
from aiogram.types import Message, CallbackQuery
|
||
|
||
from keyboards.main_menu import get_main_menu
|
||
from keyboards.inline import get_marathons_keyboard, get_marathon_details_keyboard, get_settings_keyboard
|
||
from services.api_client import api_client
|
||
|
||
router = Router()
|
||
|
||
|
||
@router.message(Command("marathons"))
|
||
@router.message(F.text == "📊 Мои марафоны")
|
||
async def cmd_marathons(message: Message):
|
||
"""Show user's marathons."""
|
||
user = await api_client.get_user_by_telegram_id(message.from_user.id)
|
||
|
||
if not user:
|
||
await message.answer(
|
||
"Сначала привяжи аккаунт через настройки профиля на сайте.",
|
||
reply_markup=get_main_menu()
|
||
)
|
||
return
|
||
|
||
marathons = await api_client.get_user_marathons(message.from_user.id)
|
||
|
||
if not marathons:
|
||
await message.answer(
|
||
"<b>Мои марафоны</b>\n\n"
|
||
"У тебя пока нет активных марафонов.\n"
|
||
"Присоединись к марафону на сайте!",
|
||
reply_markup=get_main_menu()
|
||
)
|
||
return
|
||
|
||
text = "<b>📊 Мои марафоны</b>\n\n"
|
||
|
||
for m in marathons:
|
||
status_emoji = {
|
||
"preparing": "⏳",
|
||
"active": "🎮",
|
||
"finished": "🏁"
|
||
}.get(m.get("status"), "❓")
|
||
|
||
text += f"{status_emoji} <b>{m.get('title')}</b>\n"
|
||
text += f" Очки: {m.get('total_points', 0)} | "
|
||
text += f"Место: #{m.get('position', '?')}\n\n"
|
||
|
||
await message.answer(
|
||
text,
|
||
reply_markup=get_marathons_keyboard(marathons)
|
||
)
|
||
|
||
|
||
@router.callback_query(F.data.startswith("marathon:"))
|
||
async def marathon_details(callback: CallbackQuery):
|
||
"""Show marathon details."""
|
||
marathon_id = int(callback.data.split(":")[1])
|
||
|
||
details = await api_client.get_marathon_details(
|
||
marathon_id=marathon_id,
|
||
telegram_id=callback.from_user.id
|
||
)
|
||
|
||
if not details:
|
||
await callback.answer("Не удалось загрузить данные марафона", show_alert=True)
|
||
return
|
||
|
||
marathon = details.get("marathon", {})
|
||
participant = details.get("participant", {})
|
||
active_events = details.get("active_events", [])
|
||
current_assignment = details.get("current_assignment")
|
||
|
||
status_text = {
|
||
"preparing": "⏳ Подготовка",
|
||
"active": "🎮 Активен",
|
||
"finished": "🏁 Завершён"
|
||
}.get(marathon.get("status"), "❓")
|
||
|
||
text = f"<b>{marathon.get('title')}</b>\n"
|
||
text += f"Статус: {status_text}\n\n"
|
||
|
||
text += f"<b>📈 Твоя статистика:</b>\n"
|
||
text += f"• Очки: <b>{participant.get('total_points', 0)}</b>\n"
|
||
text += f"• Место: <b>#{details.get('position', '?')}</b>\n"
|
||
text += f"• Стрик: <b>{participant.get('current_streak', 0)}</b> 🔥\n"
|
||
text += f"• Дропов: <b>{participant.get('drop_count', 0)}</b>\n\n"
|
||
|
||
if active_events:
|
||
text += "<b>⚡ Активные события:</b>\n"
|
||
for event in active_events:
|
||
event_emoji = {
|
||
"golden_hour": "🌟",
|
||
"jackpot": "🎰",
|
||
"double_risk": "⚡",
|
||
"common_enemy": "👥",
|
||
"swap": "🔄",
|
||
"game_choice": "🎲"
|
||
}.get(event.get("type"), "📌")
|
||
text += f"{event_emoji} {event.get('type', '').replace('_', ' ').title()}\n"
|
||
text += "\n"
|
||
|
||
if current_assignment:
|
||
challenge = current_assignment.get("challenge", {})
|
||
game = challenge.get("game", {})
|
||
text += f"<b>🎯 Текущее задание:</b>\n"
|
||
text += f"Игра: {game.get('title', 'N/A')}\n"
|
||
text += f"Задание: {challenge.get('title', 'N/A')}\n"
|
||
text += f"Сложность: {challenge.get('difficulty', 'N/A')}\n"
|
||
text += f"Очки: {challenge.get('points', 0)}\n"
|
||
|
||
await callback.message.edit_text(
|
||
text,
|
||
reply_markup=get_marathon_details_keyboard(marathon_id)
|
||
)
|
||
await callback.answer()
|
||
|
||
|
||
@router.callback_query(F.data == "back_to_marathons")
|
||
async def back_to_marathons(callback: CallbackQuery):
|
||
"""Go back to marathons list."""
|
||
marathons = await api_client.get_user_marathons(callback.from_user.id)
|
||
|
||
if not marathons:
|
||
await callback.message.edit_text(
|
||
"<b>Мои марафоны</b>\n\n"
|
||
"У тебя пока нет активных марафонов."
|
||
)
|
||
await callback.answer()
|
||
return
|
||
|
||
text = "<b>📊 Мои марафоны</b>\n\n"
|
||
|
||
for m in marathons:
|
||
status_emoji = {
|
||
"preparing": "⏳",
|
||
"active": "🎮",
|
||
"finished": "🏁"
|
||
}.get(m.get("status"), "❓")
|
||
|
||
text += f"{status_emoji} <b>{m.get('title')}</b>\n"
|
||
text += f" Очки: {m.get('total_points', 0)} | "
|
||
text += f"Место: #{m.get('position', '?')}\n\n"
|
||
|
||
await callback.message.edit_text(
|
||
text,
|
||
reply_markup=get_marathons_keyboard(marathons)
|
||
)
|
||
await callback.answer()
|
||
|
||
|
||
@router.message(Command("stats"))
|
||
@router.message(F.text == "📈 Статистика")
|
||
async def cmd_stats(message: Message):
|
||
"""Show user's overall statistics."""
|
||
user = await api_client.get_user_by_telegram_id(message.from_user.id)
|
||
|
||
if not user:
|
||
await message.answer(
|
||
"Сначала привяжи аккаунт через настройки профиля на сайте.",
|
||
reply_markup=get_main_menu()
|
||
)
|
||
return
|
||
|
||
stats = await api_client.get_user_stats(message.from_user.id)
|
||
|
||
if not stats:
|
||
await message.answer(
|
||
"<b>📈 Статистика</b>\n\n"
|
||
"Пока нет данных для отображения.\n"
|
||
"Начни участвовать в марафонах!",
|
||
reply_markup=get_main_menu()
|
||
)
|
||
return
|
||
|
||
text = f"<b>📈 Общая статистика</b>\n\n"
|
||
text += f"👤 <b>{user.get('nickname', 'Игрок')}</b>\n\n"
|
||
text += f"🏆 Марафонов завершено: <b>{stats.get('marathons_completed', 0)}</b>\n"
|
||
text += f"🎮 Марафонов активно: <b>{stats.get('marathons_active', 0)}</b>\n"
|
||
text += f"✅ Заданий выполнено: <b>{stats.get('challenges_completed', 0)}</b>\n"
|
||
text += f"💰 Всего очков: <b>{stats.get('total_points', 0)}</b>\n"
|
||
text += f"🔥 Лучший стрик: <b>{stats.get('best_streak', 0)}</b>\n"
|
||
|
||
await message.answer(text, reply_markup=get_main_menu())
|
||
|
||
|
||
@router.message(Command("settings"))
|
||
@router.message(F.text == "⚙️ Настройки")
|
||
async def cmd_settings(message: Message):
|
||
"""Show notification settings."""
|
||
user = await api_client.get_user_by_telegram_id(message.from_user.id)
|
||
|
||
if not user:
|
||
await message.answer(
|
||
"Сначала привяжи аккаунт через настройки профиля на сайте.",
|
||
reply_markup=get_main_menu()
|
||
)
|
||
return
|
||
|
||
# Get current notification settings
|
||
settings = await api_client.get_notification_settings(message.from_user.id)
|
||
if not settings:
|
||
settings = {"notify_events": True, "notify_disputes": True, "notify_moderation": True}
|
||
|
||
await message.answer(
|
||
"<b>⚙️ Настройки уведомлений</b>\n\n"
|
||
"Нажми на категорию, чтобы включить/выключить:\n\n"
|
||
"✅ — уведомления включены\n"
|
||
"❌ — уведомления выключены\n\n"
|
||
"<i>Уведомления о старте/финише марафонов и коды безопасности нельзя отключить.</i>",
|
||
reply_markup=get_settings_keyboard(settings)
|
||
)
|
||
|
||
|
||
@router.callback_query(F.data.startswith("toggle:"))
|
||
async def toggle_notification(callback: CallbackQuery):
|
||
"""Toggle notification setting."""
|
||
setting_name = callback.data.split(":")[1]
|
||
|
||
# Get current settings
|
||
current_settings = await api_client.get_notification_settings(callback.from_user.id)
|
||
if not current_settings:
|
||
await callback.answer("Не удалось загрузить настройки", show_alert=True)
|
||
return
|
||
|
||
# Toggle the setting
|
||
current_value = current_settings.get(setting_name, True)
|
||
new_value = not current_value
|
||
|
||
# Update on backend
|
||
result = await api_client.update_notification_settings(
|
||
callback.from_user.id,
|
||
{setting_name: new_value}
|
||
)
|
||
|
||
if not result or result.get("error"):
|
||
await callback.answer("Не удалось сохранить настройки", show_alert=True)
|
||
return
|
||
|
||
# Update keyboard with new values
|
||
await callback.message.edit_reply_markup(
|
||
reply_markup=get_settings_keyboard(result)
|
||
)
|
||
|
||
status = "включены" if new_value else "выключены"
|
||
setting_names = {
|
||
"notify_events": "События",
|
||
"notify_disputes": "Споры",
|
||
"notify_moderation": "Модерация"
|
||
}
|
||
await callback.answer(f"{setting_names.get(setting_name, setting_name)}: {status}")
|
||
|
||
|
||
@router.callback_query(F.data == "back_to_menu")
|
||
async def back_to_menu(callback: CallbackQuery):
|
||
"""Go back to main menu from settings."""
|
||
await callback.message.delete()
|
||
await callback.message.answer(
|
||
"Главное меню",
|
||
reply_markup=get_main_menu()
|
||
)
|
||
await callback.answer()
|