""" Thanks — система благодарностей пользователей """ import logging from aiogram import Router, F from aiogram.types import Message from aiogram.filters import Command, StateFilter from aiogram.fsm.state import State, StatesGroup from aiogram.fsm.context import FSMContext from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from database.db import AsyncSessionLocal from database.models import User from services.thanks import ThanksService from services.achievements import AchievementsService logger = logging.getLogger(__name__) router = Router() # ============================================================================= # FSM для отправки благодарности # ============================================================================= class ThankState(StatesGroup): waiting_for_user = State() waiting_for_message = State() # ============================================================================= # ОТПРАВКА БЛАГОДАРНОСТИ # ============================================================================= @router.message(Command('thank')) @router.message(Command('спасибо')) async def cmd_thank(message: Message, state: FSMContext): """ Поблагодарить пользователя Использование: /thank @username или /thank """ args = message.text.split(maxsplit=1) if len(args) < 2: await message.answer( '🙏 Отправить благодарность\n\n' 'Использование:\n' '/thank @username\n' 'или\n' '/thank \n\n' 'Или ответьте на сообщение командой /thank', parse_mode='HTML' ) return # Получаем пользователя target_username = args[1].replace('@', '') async with AsyncSessionLocal() as session: # Ищем по username stmt = select(User).where(User.username == target_username) result = await session.execute(stmt) target_user = result.scalar_one_or_none() if not target_user: # Пробуем по ID try: target_id = int(target_username) target_user = await session.get(User, target_id) except ValueError: pass if not target_user: await message.answer(f'❌ Пользователь @{target_username} не найден') return # Проверяем что не сам себе if target_user.user_id == message.from_user.id: await message.answer('❌ Нельзя поблагодарить самого себя!') return # Проверяем не благодарил ли уже сегодня thanks_service = ThanksService(session) if await thanks_service.has_thanked_today(message.from_user.id, target_user.user_id): await message.answer( '⚠️ Вы уже благодарили этого пользователя сегодня!\n' 'Можно поблагодарить только один раз в день.' ) return # Сохраняем данные для следующего шага await state.update_data(target_user_id=target_user.user_id) await state.update_data(target_name=target_user.full_name or f'@{target_user.username}') await message.answer( f'🙏 Благодарность для {target_user.full_name or f"@{target_user.username}"}\n\n' 'Отправьте текст благодарности (необязательно) или "пропустить":', parse_mode='HTML' ) await state.set_state(ThankState.waiting_for_message) @router.message(ThankState.waiting_for_message) async def process_thank_message(message: Message, state: FSMContext): """Получили текст благодарности""" data = await state.get_data() target_user_id = data.get('target_user_id') target_name = data.get('target_name') thank_message = message.text if message.text.lower() != 'пропустить' else None async with AsyncSessionLocal() as session: thanks_service = ThanksService(session) success = await thanks_service.give_thank( message.from_user.id, target_user_id, thank_message ) if success: # Уведомляем отправителя await message.answer( f'✅ Благодарность отправлена!\n\n' f'Получатель: {target_name}\n' f'{"Сообщение: " + thank_message if thank_message else ""}', parse_mode='HTML' ) # Уведомляем получателя try: await message.bot.send_message( target_user_id, f'🙏 Вам благодарность!\n\n' f'От: {message.from_user.full_name}\n' f'{"Сообщение: " + thank_message if thank_message else "Спасибо за помощь!"}\n\n' f'+10 к рейтингу!', parse_mode='HTML' ) except Exception as e: logger.error(f'Не удалось уведомить о благодарности: {e}') # Обновляем рейтинг получателя (+10) target_user = await session.get(User, target_user_id) if target_user: target_user.rating += 10 target_user.update_level() # Проверяем достижение "Помощник" (получил благодарность) achievements_service = AchievementsService(session) awarded = await achievements_service.check_and_award( target_user_id, helper=True # Флаг для достижения помощника ) if 'helper' in awarded: await message.bot.send_message( target_user_id, '🏆 Новое достижение!\n\n' '🤝 Помощник\n\n' 'Получил благодарность от соседа\n\n' 'Продолжайте помогать!', parse_mode='HTML' ) await session.commit() await state.clear() # ============================================================================= # МОИ БЛАГОДАРНОСТИ # ============================================================================= @router.message(Command('my_thanks')) @router.message(Command('мои_спасибо')) async def cmd_my_thanks(message: Message): """Показать свои благодарности""" user_id = message.from_user.id async with AsyncSessionLocal() as session: thanks_service = ThanksService(session) stats = await thanks_service.get_user_thanks(user_id) text = '🙏 Ваши благодарности\n\n' text += f'✅ Получено: {stats["received"]}\n' text += f'📤 Отправлено: {stats["given"]}\n' if stats['last_received']: text += '\nПоследние полученные:\n' for thank in stats['last_received'][:3]: text += f' • От user{thank["from"]}: {thank["message"] or "Спасибо!"}\n' await message.answer(text, parse_mode='HTML') # ============================================================================= # ТОП ПО БЛАГОДАРНОСТЯМ # ============================================================================= @router.message(Command('thanks_top')) @router.message(Command('топ_спасибо')) async def cmd_thanks_top(message: Message): """Топ пользователей по благодарностям""" async with AsyncSessionLocal() as session: thanks_service = ThanksService(session) leaderboard = await thanks_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["thanks"]} благодар.\n' await message.answer(text, parse_mode='HTML') # ============================================================================= # ИСТОРИЯ БЛАГОДАРНОСТЕЙ # ============================================================================= @router.message(Command('thanks_history')) @router.message(Command('история_спасибо')) async def cmd_thanks_history(message: Message): """История благодарностей пользователя""" user_id = message.from_user.id async with AsyncSessionLocal() as session: thanks_service = ThanksService(session) history = await thanks_service.get_thanks_history(user_id) if not history: await message.answer('ℹ️ История благодарностей пуста') return text = '🙏 История благодарностей\n\n' for thank in history[:10]: if thank['is_received']: text += f'✅ Получено от user{thank["from"]}: {thank["message"] or "Спасибо!"}\n' else: text += f'📤 Отправлено user{thank["to"]}: {thank["message"] or "Спасибо!"}\n' await message.answer(text, parse_mode='HTML')