"""
Achievements — достижения пользователей
"""
import logging
from aiogram import Router, F
from aiogram.types import Message
from aiogram.filters import Command
from sqlalchemy.ext.asyncio import AsyncSession
from database.db import AsyncSessionLocal
from services.achievements import AchievementsService
from utils.decorators import admin_only
logger = logging.getLogger(__name__)
router = Router()
# =============================================================================
# МОИ ДОСТИЖЕНИЯ
# =============================================================================
@router.message(Command('achievements'))
@router.message(Command('достижения'))
async def cmd_achievements(message: Message):
"""Показать свои достижения"""
user_id = message.from_user.id
async with AsyncSessionLocal() as session:
service = AchievementsService(session)
achievements = await service.get_user_achievements(user_id)
if not achievements:
await message.answer(
'🏆 Ваши достижения\n\n'
'Пока нет достижений.\n\n'
'Получайте достижения за:\n'
'• Активность в чате\n'
'• Верификацию\n'
'• Высокий рейтинг\n'
'• Участие в опросах\n'
'• Публикацию объявлений',
parse_mode='HTML'
)
return
# Группируем по категориям
by_category = {}
for ach in achievements:
cat = ach['category']
if cat not in by_category:
by_category[cat] = []
by_category[cat].append(ach)
text = '🏆 Ваши достижения\n\n'
text += f'Всего: {len(achievements)}\n\n'
category_names = {
'activity': '📝 Активность',
'verification': '✅ Верификация',
'rating': '⭐ Рейтинг',
'time': '⏰ Время',
'social': '🤝 Социальные',
'security': '🔒 Безопасность',
'streak': '📅 Серии',
'polls': '📊 Опросы',
'ads': '📢 Объявления'
}
for cat, cats_achievements in by_category.items():
cat_name = category_names.get(cat, cat.capitalize())
text += f'{cat_name}\n'
for ach in cats_achievements:
text += f" {ach['emoji']} {ach['name']}\n"
text += '\n'
await message.answer(text, parse_mode='HTML')
# =============================================================================
# ТОП ПО ДОСТИЖЕНИЯМ
# =============================================================================
@router.message(Command('achievements_top'))
@router.message(Command('топ_достижений'))
@admin_only
async def cmd_achievements_top(message: Message):
"""Топ пользователей по достижениям"""
async with AsyncSessionLocal() as session:
service = AchievementsService(session)
leaderboard = await service.get_leaderboard(10)
if not leaderboard:
await message.answer('ℹ️ Пока нет достижений у пользователей')
return
text = '🏆 Топ по достижениям\n\n'
medals = ['🥇', '🥈', '🥉']
for i, user in enumerate(leaderboard):
medal = medals[i] if i < 3 else f'{i+1}.'
text += f'{medal} {user["name"]} (кв. {user["apartment"]}) — {user["achievements"]} достиж.\n'
await message.answer(text, parse_mode='HTML')
# =============================================================================
# СПИСОК ВСЕХ ДОСТИЖЕНИЙ
# =============================================================================
@router.message(Command('all_achievements'))
@router.message(Command('все_достижения'))
@admin_only
async def cmd_all_achievements(message: Message):
"""Список всех доступных достижений"""
async with AsyncSessionLocal() as session:
service = AchievementsService(session)
all_achievements = await service.get_all_achievements()
text = '🏆 Все достижения\n\n'
text += f'Всего: {len(all_achievements)}\n\n'
# Группируем по категориям
by_category = {}
for ach_type, ach_data in all_achievements.items():
cat = ach_data.get('category', 'other')
if cat not in by_category:
by_category[cat] = []
by_category[cat].append((ach_type, ach_data))
category_names = {
'activity': '📝 Активность',
'verification': '✅ Верификация',
'rating': '⭐ Рейтинг',
'time': '⏰ Время',
'social': '🤝 Социальные',
'security': '🔒 Безопасность',
'streak': '📅 Серии',
'polls': '📊 Опросы',
'ads': '📢 Объявления'
}
for cat, cats_achievements in sorted(by_category.items()):
cat_name = category_names.get(cat, cat.capitalize())
text += f'{cat_name}\n'
for ach_type, ach_data in cats_achievements:
text += f" {ach_data.get('emoji', '🏆')} {ach_data.get('name', ach_type)}\n"
text += f" └─ {ach_data.get('description', '')}\n"
text += '\n'
await message.answer(text, parse_mode='HTML')
# =============================================================================
# ДОСТИЖЕНИЯ ПОЛЬЗОВАТЕЛЯ
# =============================================================================
@router.message(Command('user_achievements'))
@router.message(Command('достижения_пользователя'))
@admin_only
async def cmd_user_achievements(message: Message):
"""
Показать достижения пользователя
Использование: /user_achievements
"""
args = message.text.split()
if len(args) < 2:
await message.answer(
'❌ Использование:\n'
'/user_achievements <user_id>',
parse_mode='HTML'
)
return
try:
user_id = int(args[1])
except ValueError:
await message.answer('❌ Неверный ID пользователя')
return
async with AsyncSessionLocal() as session:
service = AchievementsService(session)
achievements = await service.get_user_achievements(user_id)
if not achievements:
await message.answer(f'ℹ️ У пользователя {user_id} нет достижений')
return
text = f'🏆 Достижения пользователя {user_id}\n\n'
text += f'Всего: {len(achievements)}\n\n'
for ach in achievements:
text += f" {ach['emoji']} {ach['name']}\n"
text += f" └─ {ach['earned_at'][:10]}\n"
await message.answer(text, parse_mode='HTML')