chat_back/app/services/chat_service.py

129 lines
5 KiB
Python

from datetime import timedelta
from urllib.parse import urljoin
from pydantic import ValidationError
from app.chat.exceptions import UserDontHavePermissionException, UserCanNotReadThisChatException
from app.chat.shemas import SAllowedChats, SChangeData, SPinnedChats, SChat
from app.config import settings
from app.services.redis_service import RedisService
from app.services.user_service import UserService
from app.utils.unit_of_work import UnitOfWork
from app.users.schemas import SInvitationData
from app.services.auth_service import AuthService
class ChatService:
@staticmethod
async def find_chat(uow: UnitOfWork, chat_id: int, user_id: int) -> SChat:
async with uow:
chat = await uow.chat.find_one(chat_id=chat_id, user_id=user_id)
return chat
@staticmethod
async def get_all_chats(uow: UnitOfWork, user_id: int) -> SAllowedChats:
try:
async with RedisService() as redis:
allowed_chats = await redis.get_value(key=f"user_allowed_chats: {user_id}", model=SAllowedChats)
return allowed_chats
except ValidationError:
async with uow:
allowed_chats = await uow.user.get_user_allowed_chats(user_id=user_id)
async with RedisService() as redis:
await redis.set_key(
key=f"user_allowed_chats: {user_id}",
expire_time=timedelta(minutes=30),
value=allowed_chats.model_dump_json()
)
return allowed_chats
@staticmethod
async def create_chat(uow: UnitOfWork, user_id: int, user_to_exclude_id: int, chat_name: str) -> int:
if user_id == user_to_exclude_id:
raise UserCanNotReadThisChatException
user_chat_for = await UserService.find_user(uow=uow, id=user_to_exclude_id)
async with uow:
chat_id = await uow.chat.create_chat(
user_id=user_to_exclude_id,
chat_name=chat_name,
created_by=user_id,
avatar_image=user_chat_for.avatar_image
)
await uow.chat.add_user_to_chat(user_id, chat_id)
await uow.chat.add_user_to_chat(settings.ADMIN_USER_ID, chat_id)
async with RedisService(is_raise=True) as redis:
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
await uow.commit()
return chat_id
@classmethod
async def change_chat_data(cls, uow: UnitOfWork, user_id: int, user_data: SChangeData) -> None:
chat = await cls.find_chat(uow=uow, chat_id=user_data.chat_id, user_id=user_id)
if chat.created_by != user_id:
raise UserDontHavePermissionException
async with uow:
await uow.chat.change_data(
chat_id=user_data.chat_id, chat_name=user_data.chat_name, avatar_image=user_data.avatar_image
)
async with RedisService(is_raise=True) as redis:
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
await uow.commit()
@staticmethod
def create_invitation_link(chat_id: int) -> str:
invitation_data = SInvitationData.model_validate({"chat_id": chat_id})
invitation_token = AuthService.encode_invitation_token(invitation_data)
invitation_link = urljoin(settings.INVITATION_LINK_HOST, f"/submit#code={invitation_token}")
return invitation_link
@classmethod
async def invite_to_chat(cls, uow: UnitOfWork, user_id: int, invitation_token: str) -> None:
invitation_data = AuthService.decode_invitation_token(invitation_token)
chat = await cls.find_chat(uow=uow, chat_id=invitation_data.chat_id, user_id=user_id)
if user_id == chat.chat_for:
raise UserCanNotReadThisChatException
async with uow:
await uow.chat.add_user_to_chat(chat_id=invitation_data.chat_id, user_id=user_id)
async with RedisService(is_raise=True) as redis:
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
await uow.commit()
@classmethod
async def delete_chat(cls, uow: UnitOfWork, user_id: int, chat_id: int) -> None:
chat = await cls.find_chat(uow=uow, chat_id=chat_id, user_id=user_id)
if not user_id == chat.created_by:
raise UserDontHavePermissionException
async with uow:
await uow.chat.delete_chat(chat_id)
async with RedisService(is_raise=True) as redis:
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
await uow.commit()
@classmethod
async def delete_user_from_chat(cls, uow: UnitOfWork, user_id: int, chat_id: int, user_id_for_delete: int) -> None:
chat = await cls.find_chat(uow=uow, chat_id=chat_id, user_id=user_id)
if not user_id == chat.created_by:
raise UserDontHavePermissionException
async with uow:
await uow.chat.delete_user_from_chat(chat_id=chat_id, user_id=user_id_for_delete)
async with RedisService(is_raise=True) as redis:
await redis.delete_key(key=f"user_allowed_chats: {user_id_for_delete}")
await uow.commit()
@staticmethod
async def pin_chat(uow: UnitOfWork, user_id: int, chat_id: int) -> None:
async with uow:
await uow.chat.pin_chat(chat_id=chat_id, user_id=user_id)
await uow.commit()
@staticmethod
async def unpin_chat(uow: UnitOfWork, user_id: int, chat_id: int) -> None:
async with uow:
await uow.chat.unpin_chat(chat_id=chat_id, user_id=user_id)
await uow.commit()
@staticmethod
async def get_pinned_chats(uow: UnitOfWork, user_id: int) -> SPinnedChats:
async with uow:
pinned_chats = await uow.chat.get_pinned_chats(user_id=user_id)
return pinned_chats