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, SDeletedChat, SAllowedChats, SMessageList, SPinnedChats, SPinnedMessages ) from app.unit_of_work import UnitOfWork from app.users.dependencies import check_verificated_user_with_exc from app.utils.auth import AuthService, encode_invitation_token, decode_invitation_token from app.users.schemas import SCreateInvitationLink, SUser, SInvitationData router = APIRouter(prefix="/chat", tags=["Чат"]) @router.get( "", status_code=status.HTTP_200_OK, response_model=SAllowedChats, ) 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 {"allowed_chats": 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) ): if user.id == user_to_exclude: raise UserCanNotReadThisChatException async with uow: chat_id = await uow.chat.create(user_id=user_to_exclude, chat_name=chat_name, created_by=user.id) await uow.chat.add_user_to_chat(user.id, chat_id) await uow.chat.add_user_to_chat(settings.ADMIN_USER_ID, chat_id) await uow.commit() @router.get( "/get_last_message/{chat_id}", status_code=status.HTTP_200_OK, response_model=SMessageList, ) 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 {"messages": message} @router.get( "/get_some_messages/{chat_id}", status_code=status.HTTP_200_OK, response_model=SMessageList, ) 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": 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) invitation_data = SInvitationData.model_validate({"chat_id": chat_id}) invitation_token = encode_invitation_token(invitation_data) invitation_link = settings.INVITATION_LINK_HOST + "/api/chat/invite_to_chat/" + invitation_token return {"invitation_link": invitation_link} @router.get( "/invite_to_chat/{invitation_token}", status_code=status.HTTP_200_OK, response_model=None, ) async def invite_to_chat( invitation_token: str, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork) ): invitation_data = decode_invitation_token(invitation_token) async with uow: chat = await uow.chat.find_one_or_none(id=invitation_data.chat_id) if user.id == chat.chat_for: raise UserCanNotReadThisChatException await uow.chat.add_user_to_chat(chat_id=invitation_data.chat_id, user_id=user.id) await uow.commit() @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=SPinnedChats, ) async def get_pinned_chats(user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)): async with uow: return {"pinned_chats": await uow.chat.get_pinned_chats(user_id=user.id)} @router.get( "/pinned_messages/{chat_id}", status_code=status.HTTP_200_OK, response_model=SPinnedMessages, ) 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 {"pinned_messages": messages}