""" 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')