chat_back/app/services/message_service.py

131 lines
4.1 KiB
Python

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