from cryptography.fernet import Fernet from fastapi import APIRouter, Depends, status from app.config import settings from app.exceptions import UserDontHavePermissionException, MessageNotFoundException, UserCanNotReadThisChatException from app.chat.shemas import SMessage, SLastMessages, SPinnedChat, SDeletedUser, SChat, SDeletedChat from app.unit_of_work import UnitOfWork from app.users.dependencies import check_verificated_user_with_exc from app.users.auth import ADMIN_USER_ID, AuthService from app.users.schemas import SCreateInvitationLink, SUserAddedToChat, SUser router = APIRouter(prefix="/chat", tags=["Чат"]) @router.get( "", status_code=status.HTTP_200_OK, response_model=list[SChat] ) async def get_all_chats(user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): async with uow: result = await uow.user.get_user_allowed_chats(user.id) return result @router.post( "/create_chat", status_code=status.HTTP_201_CREATED, response_model=None, ) async def create_chat(user_to_exclude: int, chat_name: str, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): async with uow: if user.id == user_to_exclude: raise UserCanNotReadThisChatException chat_id = await uow.chat.create(user_id=user_to_exclude, chat_name=chat_name, created_by=user.id) user_added_to_chat = await uow.chat.add_user_to_chat(user.id, chat_id) await uow.chat.add_user_to_chat(ADMIN_USER_ID, chat_id) return user_added_to_chat @router.get( "/get_last_message/{chat_id}", status_code=status.HTTP_200_OK, response_model=list[SMessage] ) async def get_last_message(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id) async with uow: message = await uow.chat.get_some_messages(chat_id=chat_id, message_number_from=0, messages_to_get=1) if message is None: raise MessageNotFoundException for mes in message: mes["created_at"] = mes["created_at"].isoformat() return message @router.get( "/get_some_messages/{chat_id}", status_code=status.HTTP_200_OK, response_model=list[SMessage] ) async def get_some_messages( chat_id: int, last_messages: SLastMessages = Depends(), user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork) ): await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id) async with uow: messages = await uow.chat.get_some_messages( chat_id=chat_id, message_number_from=last_messages.messages_loaded, messages_to_get=last_messages.messages_to_get ) if not messages: raise MessageNotFoundException for mes in messages: mes["created_at"] = mes["created_at"].isoformat() return messages @router.get( "/message/{chat_id}", status_code=status.HTTP_200_OK, response_model=SMessage ) async def get_message_by_id(chat_id: int, message_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id) async with uow: message = await uow.chat.get_message_by_id(message_id=message_id) if not message: raise MessageNotFoundException message = dict(message) message["created_at"] = message["created_at"].isoformat() return message @router.get( "/create_invitation_link", status_code=status.HTTP_201_CREATED, response_model=SCreateInvitationLink, ) async def create_invitation_link(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id) cipher_suite = Fernet(settings.INVITATION_LINK_TOKEN_KEY) invitation_token = cipher_suite.encrypt(str(chat_id).encode()) invitation_link = settings.INVITATION_LINK_HOST + "/api/chat/invite_to_chat/" + str(invitation_token).split("'")[1] return {"invitation_link": invitation_link} @router.get( "/invite_to_chat/{invitation_token}", status_code=status.HTTP_200_OK, response_model=SUserAddedToChat, ) async def invite_to_chat(invitation_token: str, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): async with uow: invitation_token = invitation_token.encode() cipher_suite = Fernet(settings.INVITATION_LINK_TOKEN_KEY) chat_id = int(cipher_suite.decrypt(invitation_token)) chat = await uow.chat.find_one_or_none(id=chat_id) if user.id == chat.chat_for: raise UserCanNotReadThisChatException return {"user_added_to_chat": await uow.chat.add_user_to_chat(chat_id=chat_id, user_id=user.id)} @router.delete( "/delete_chat/{chat_id}", status_code=status.HTTP_200_OK, response_model=SDeletedChat, ) async def delete_chat(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): async with uow: chat = await uow.chat.find_one_or_none(id=chat_id) if user.id == chat.created_by: return {"deleted_chat": await uow.chat.delete_chat(chat_id)} raise UserDontHavePermissionException @router.delete( "/delete_user_from_chat/{chat_id}", status_code=status.HTTP_200_OK, response_model=SDeletedUser ) async def delete_user_from_chat(chat_id: int, user_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): async with uow: chat = await uow.chat.find_one_or_none(id=chat_id) if user.id == chat.created_by: return {"deleted_user": await uow.chat.delete_user(chat_id=chat_id, user_id=user_id)} raise UserDontHavePermissionException @router.post( "/pin_chat", status_code=status.HTTP_200_OK, response_model=SPinnedChat ) async def pinn_chat(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id) async with uow: await uow.chat.pin_chat(chat_id=chat_id, user_id=user.id) return {"chat_id": chat_id, "user_id": user.id} @router.delete( "/unpin_chat", status_code=status.HTTP_200_OK, response_model=SPinnedChat ) async def unpinn_chat(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id) async with uow: await uow.chat.unpin_chat(chat_id=chat_id, user_id=user.id) return {"chat_id": chat_id, "user_id": user.id} @router.get( "/get_pinned_chats", status_code=status.HTTP_200_OK, response_model=list[SChat] ) async def get_pinned_chats(user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): async with uow: return await uow.chat.get_pinned_chats(user_id=user.id) @router.get( "/pinned_messages/{chat_id}", status_code=status.HTTP_200_OK, response_model=list[SMessage] | None ) async def pinned_messages(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id) async with uow: messages = await uow.chat.get_pinned_messages(chat_id=chat_id) if messages: for mes in messages: mes["created_at"] = mes["created_at"].isoformat() return messages