domovoy_bot/handlers/achievements.py
Admin ba4676b0af v1.0 MVP - Инициализация проекта 🏠
 Регистрация и верификация жильцов
 Рейтинг активности (уровни)
 Детект шпионов (Score 0-100)
 Анти-мат система (3 предупреждения → бан)
 Админ-панель с рассылкой
 Учёт квартир (несколько жильцов)
 Телефоны экстренных служб и мастеров
 Еженедельный экспорт JSON
 Прокси (socks5) для обхода РКН

Бекап: backups/versions/v1.0_mvp_2026-02-26/

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-02-27 10:54:16 +00:00

200 lines
7.1 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
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(
'🏆 <b>Ваши достижения</b>\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 = '🏆 <b>Ваши достижения</b>\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'<b>{cat_name}</b>\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 = '🏆 <b>Топ по достижениям</b>\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 = '🏆 <b>Все достижения</b>\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'<b>{cat_name}</b>\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 <user_id>
"""
args = message.text.split()
if len(args) < 2:
await message.answer(
'❌ <b>Использование:</b>\n'
'<code>/user_achievements &lt;user_id&gt;</code>',
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'🏆 <b>Достижения пользователя {user_id}</b>\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')