130 lines
5.1 KiB
Python
130 lines
5.1 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)
|
|
if user_id != settings.ADMIN_USER_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
|