You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
4.2 KiB

from bson import ObjectId
import bson
from fastapi import APIRouter, HTTPException, status
from fastapi.params import Depends
import pymongo
from app.dto import FriendAddDTO
from app.models import HTTPError, User, Friend
from app.utils import friend_not_found, get_current_user, objectid_misformatted
import app.config as config
# Best workaround found for _id typed as ObjectId (creating Exception bcause JSON doesn't support custom types countrary to BSON, used by Mongo)
# also allows to create DTOs at the time, but not at it's best (project structure is chaotic FTM :s)
import app.serializers as serializers # Import all serializers (detailed in __init__.py)
# Database setup
client = pymongo.MongoClient(config.MONGODB_URL, username=config.MONGODB_USERNAME, password=config.MONGODB_PASSWORD)
db = client[config.MONGODB_DATABASE]
friends_collection = db["friends"]
friends_router = APIRouter(
prefix="/friend",
tags=["Friends"]
)
@friends_router.get(
path="/{id}",
responses={401: {"model": HTTPError}, 404: {"model": HTTPError}, 422: {"model": HTTPError}}
)
async def get_friend(id: str, current_user: User = Depends(get_current_user)):
try:
friend = friends_collection.find_one({"_id": ObjectId(id)})
except bson.errors.InvalidId:
objectid_misformatted()
if friend is None: friend_not_found()
return serializers.friend_serialize(friend,False if friend['user_id']==current_user.uid else True)
@friends_router.post(
path="/add",
responses={401: {"model": HTTPError}, 409: {"model": HTTPError}}
)
async def add_friend(friend_to_add: FriendAddDTO, current_user: User = Depends(get_current_user)):
# TODO: test if exists
friend: Friend = friend_to_add.model_dump()
if(current_user.uid == friend["friend_user_id"]):
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="Cannot add yourself as a friend"
)
friend["user_id"] = current_user.uid
friend["status"] = "pending"
friend_id = friends_collection.insert_one(friend).inserted_id
return {"id": str(friend_id)}
@friends_router.delete(
path="/{id}/delete",
responses={401: {"model": HTTPError}, 404: {"model": HTTPError}, 422: {"model": HTTPError}}
)
async def delete_friend(id: str, current_user: User = Depends(get_current_user)):
try:
result = friends_collection.delete_one({"_id": ObjectId(id)})
except bson.errors.InvalidId:
objectid_misformatted()
if result.deleted_count == 0: friend_not_found()
return {"message": "Friend deleted"}
@friends_router.patch(
path="/{id}/accept",
responses={401: {"model": HTTPError}, 404: {"model": HTTPError}, 422: {"model": HTTPError}}
)
async def accept_friend(id: str, current_user: User = Depends(get_current_user)):
try:
check_friend = friends_collection.find_one({"_id": ObjectId(id)})
if check_friend is None: friend_not_found()
if check_friend["status"] != "pending":
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Friend request already accepted"
)
friends_collection.update_one({"_id": ObjectId(id)}, {"$set": {"status": "accepted"}})
except bson.errors.InvalidId:
objectid_misformatted()
return {"message": "Friend request accepted"}
@friends_router.post(
path="/{id}/deny",
responses={401: {"model": HTTPError}, 404: {"model": HTTPError}, 422: {"model": HTTPError}}
)
async def deny_friend(id: str, current_user: User = Depends(get_current_user)):
try:
result = friends_collection.update_one({"_id": ObjectId(id)}, {"$set": {"status": "denied"}})
except bson.errors.InvalidId:
objectid_misformatted()
if result.matched_count == 0: friend_not_found()
return {"message": "Friend request denied"}
@friends_router.get(
path="s",
response_model=list[Friend],
responses={401: {"model": HTTPError}}
)
async def list_friends(current_user: User = Depends(get_current_user)):
return serializers.friends_serialize(friends_collection.find({"user_id": current_user.uid}).to_list(), friends_collection.find({"friend_user_id": current_user.uid}).to_list())