from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.messages.models import Message, MessageIdempotencyKey, MessageReceipt, MessageType async def create_message( db: AsyncSession, *, chat_id: int, sender_id: int, message_type: MessageType, text: str | None, ) -> Message: message = Message(chat_id=chat_id, sender_id=sender_id, type=message_type, text=text) db.add(message) await db.flush() return message async def get_message_by_client_message_id( db: AsyncSession, *, chat_id: int, sender_id: int, client_message_id: str, ) -> Message | None: result = await db.execute( select(Message) .join(MessageIdempotencyKey, MessageIdempotencyKey.message_id == Message.id) .where( MessageIdempotencyKey.chat_id == chat_id, MessageIdempotencyKey.sender_id == sender_id, MessageIdempotencyKey.client_message_id == client_message_id, ) .limit(1) ) return result.scalar_one_or_none() async def create_message_idempotency_key( db: AsyncSession, *, chat_id: int, sender_id: int, client_message_id: str, message_id: int, ) -> MessageIdempotencyKey: key = MessageIdempotencyKey( chat_id=chat_id, sender_id=sender_id, client_message_id=client_message_id, message_id=message_id, ) db.add(key) await db.flush() return key async def get_message_by_id(db: AsyncSession, message_id: int) -> Message | None: result = await db.execute(select(Message).where(Message.id == message_id)) return result.scalar_one_or_none() async def list_chat_messages( db: AsyncSession, chat_id: int, *, limit: int = 50, before_id: int | None = None, ) -> list[Message]: query = select(Message).where(Message.chat_id == chat_id) if before_id is not None: query = query.where(Message.id < before_id) result = await db.execute(query.order_by(Message.id.desc()).limit(limit)) return list(result.scalars().all()) async def delete_message(db: AsyncSession, message: Message) -> None: await db.delete(message) async def get_message_receipt(db: AsyncSession, *, chat_id: int, user_id: int) -> MessageReceipt | None: result = await db.execute( select(MessageReceipt).where( MessageReceipt.chat_id == chat_id, MessageReceipt.user_id == user_id, ) ) return result.scalar_one_or_none() async def create_message_receipt( db: AsyncSession, *, chat_id: int, user_id: int, last_delivered_message_id: int | None, last_read_message_id: int | None, ) -> MessageReceipt: receipt = MessageReceipt( chat_id=chat_id, user_id=user_id, last_delivered_message_id=last_delivered_message_id, last_read_message_id=last_read_message_id, ) db.add(receipt) await db.flush() return receipt