from datetime import datetime, UTC, timedelta from uuid import UUID from app.chat.shemas import SMessage, SSendMessage, SPinnedMessages, SMessageList, SMessageRaw, SMessageRawList from app.services import user_service from app.users.schemas import SUser from app.utils.unit_of_work import UnitOfWork _users: dict[int, tuple[SUser, datetime]] = {} async def _get_cached_user(uow: UnitOfWork, user_id: int) -> SUser: if user_id in _users and _users[user_id][1] > datetime.now(UTC): return _users[user_id][0] user = await user_service.find_user(uow=uow, id=user_id) _users[user_id] = user, datetime.now(UTC) + timedelta(minutes=5) return user async def _add_avatar_image_and_username_to_message(uow: UnitOfWork, message: SMessageRaw) -> SMessage: user = await _get_cached_user(uow=uow, user_id=message.user_id) message = message.model_dump() message["avatar_image"] = str(user.avatar_image) message["username"] = user.username return SMessage.model_validate(message) async def _add_avatar_image_and_username_to_message_list( uow: UnitOfWork, messages: SMessageRawList, ) -> SMessageList: return SMessageList.model_validate( { "messages": [ await _add_avatar_image_and_username_to_message(uow=uow, message=message) for message in messages.message_raw_list ] if messages.message_raw_list else None } ) async def send_message( uow: UnitOfWork, user_id: int, chat_id: int, message: SSendMessage, ) -> SMessage: async with uow: if message.answer: answer_message = await uow.message.get_message_by_id(message_id=message.answer) message_id = await uow.message.send_message( user_id=user_id, chat_id=chat_id, message=message.message, image_url=message.image_url, answer_id=answer_message.id, answer_message=answer_message.message, answer_image_url=answer_message.answer_image_url, ) else: message_id = await uow.message.send_message( user_id=user_id, chat_id=chat_id, message=message.message, image_url=message.image_url, ) new_message = await get_message_by_id(uow=uow, message_id=message_id) return new_message async def delete_message(uow: UnitOfWork, message_id: UUID) -> None: async with uow: await uow.message.delete_message(message_id=message_id) async def edit_message(uow: UnitOfWork, message_id: UUID, new_message: str, new_image_url: str) -> None: async with uow: await uow.message.edit_message( message_id=message_id, new_message=new_message, new_image_url=new_image_url, ) async def pin_message(uow: UnitOfWork, chat_id: int, user_id: int, message_id: UUID) -> SMessage: async with uow: await uow.chat.pin_message(chat_id=chat_id, message_id=message_id, user_id=user_id) await uow.commit() pinned_message = await get_message_by_id(uow=uow, message_id=message_id) return pinned_message async def unpin_message(uow: UnitOfWork, chat_id: int, message_id: UUID) -> None: async with uow: await uow.chat.unpin_message(chat_id=chat_id, message_id=message_id) await uow.commit() async def get_message_by_id(uow: UnitOfWork, message_id: UUID) -> SMessage: async with uow: raw_message = await uow.message.get_message_by_id(message_id=message_id) message = await _add_avatar_image_and_username_to_message(uow=uow, message=raw_message) return message async def get_pinned_messages(uow: UnitOfWork, chat_id: int) -> SPinnedMessages: async with uow: pinned_messages_ids = await uow.chat.get_pinned_messages_ids(chat_id=chat_id) raw_messages = await uow.message.get_messages_by_ids(messages_ids=pinned_messages_ids) pinned_messages = await _add_avatar_image_and_username_to_message_list(uow=uow, messages=raw_messages) return SPinnedMessages.model_validate({"pinned_messages": pinned_messages.messages}) async def get_some_messages( uow: UnitOfWork, chat_id: int, message_number_from: int, messages_to_get: int, ) -> SMessageList: async with uow: messages = await uow.message.get_some_messages( chat_id=chat_id, message_number_from=message_number_from, messages_to_get=messages_to_get, ) messages = await _add_avatar_image_and_username_to_message_list(uow=uow, messages=messages) return messages