from aiogram import F, Router from aiogram.types import ChatMemberUpdated, Message from app.core.database import AsyncSessionLocal from app.models.managed_chat import ManagedChat from app.models.lottery import Lottery, LotteryStatus from app.models.passphrase_verification import PassphraseVerification from sqlalchemy import select router = Router() @router.my_chat_member(F.chat.type.in_({"group", "supergroup", "channel"})) async def bot_chat_member_updated(event: ChatMemberUpdated) -> None: """Record or update the bot's presence in a group/channel.""" async with AsyncSessionLocal() as db: chat = event.chat new_status = event.new_chat_member.status result = await db.execute( select(ManagedChat).where(ManagedChat.id == chat.id) ) managed = result.scalar_one_or_none() if new_status in ("member", "administrator"): if managed is None: managed = ManagedChat( id=chat.id, title=chat.title or "", username=getattr(chat, 'username', None), chat_type=chat.type, ) db.add(managed) else: managed.is_active = True managed.title = chat.title or managed.title managed.username = getattr(chat, 'username', None) await db.commit() elif new_status in ("left", "kicked") and managed is not None: managed.is_active = False await db.commit() @router.channel_post(F.chat.type == "channel") @router.message(F.chat.type.in_({"group", "supergroup"})) async def on_chat_message(message: Message) -> None: """Track latest message ID and detect passphrase submissions.""" async with AsyncSessionLocal() as db: result = await db.execute(select(ManagedChat).where(ManagedChat.id == message.chat.id)) managed = result.scalar_one_or_none() if managed is None: managed = ManagedChat( id=message.chat.id, title=message.chat.title or "", username=getattr(message.chat, "username", None), chat_type=message.chat.type, last_message_id=message.message_id, ) db.add(managed) elif message.message_id > (managed.last_message_id or 0): managed.last_message_id = message.message_id await db.commit() if message.text and message.from_user: text = message.text.strip() uid = message.from_user.id cid = message.chat.id async with AsyncSessionLocal() as db2: r = await db2.execute( select(Lottery).where( Lottery.status == LotteryStatus.ACTIVE, Lottery.require_membership == True, ) ) for lottery in r.scalars().all(): ids = lottery.required_chat_ids or [] phrases = lottery.required_chat_passphrases or [] for i, chat_id in enumerate(ids): if chat_id == cid and i < len(phrases) and phrases[i] and text == phrases[i]: existing = await db2.execute( select(PassphraseVerification).where( PassphraseVerification.lottery_id == lottery.id, PassphraseVerification.chat_id == cid, PassphraseVerification.user_id == uid, ) ) if existing.scalar_one_or_none() is None: db2.add(PassphraseVerification( lottery_id=lottery.id, chat_id=cid, user_id=uid )) await db2.commit() break