Add user rating support!
It took me too long to complete it, I hope this thing will work for more than 10 minutes. It also breaks when user rated a level that was already rated.
This commit is contained in:
parent
270cae46b2
commit
44b79518a5
3 changed files with 113 additions and 24 deletions
|
@ -53,6 +53,10 @@ class User(BaseModel):
|
|||
Username: str = "magmaus3"
|
||||
Email: str = "user@example.com"
|
||||
|
||||
# Ratings have to be stored in the following format: {mapID: rating},
|
||||
# where rating is either 1 or 5, or None.
|
||||
Ratings: dict = {}
|
||||
|
||||
|
||||
class Notification(BaseModel):
|
||||
"""Pydantic model for Notifications
|
||||
|
|
|
@ -37,6 +37,8 @@ def auth_check(Authorization):
|
|||
- wrongpass = wrong password
|
||||
- [dictionary] = query
|
||||
"""
|
||||
if Authorization is None:
|
||||
return False, "noauth"
|
||||
username, password = Authorization.split(":")
|
||||
|
||||
query = user_collection.find_one({"Username": username})
|
||||
|
|
|
@ -2,6 +2,7 @@ from datetime import datetime
|
|||
from fastapi import FastAPI, Form, File, UploadFile, Header, HTTPException, Body
|
||||
from fastapi.responses import PlainTextResponse
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from pydantic import BaseModel
|
||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
|
||||
from typing import Union, Optional, Any
|
||||
|
@ -166,7 +167,17 @@ async def getMap(mapID: int):
|
|||
|
||||
|
||||
@app.post("/api/v1/map/{mapID}/start")
|
||||
async def startMap(mapID: int):
|
||||
async def startMap(
|
||||
mapID: int,
|
||||
Authorization: Union[str, None] = Header(default=None)
|
||||
):
|
||||
authcheck = db.auth_check(Authorization)
|
||||
if not authcheck[0] and authcheck[1] == "nouser":
|
||||
raise HTTPException(404, detail="User not found")
|
||||
elif not authcheck[0] and authcheck[1] == "wrongpass":
|
||||
raise HTTPException(403, detail="Wrong password")
|
||||
elif authcheck[0]:
|
||||
userData = types.User(**authcheck[1])
|
||||
query = db.maps_collection.find_one({"ID": mapID})
|
||||
del query["_id"]
|
||||
|
||||
|
@ -178,9 +189,9 @@ async def startMap(mapID: int):
|
|||
"Difficulty": 0,
|
||||
"Followed": False,
|
||||
"Played": True,
|
||||
"Rating": 5,
|
||||
"TagIDs": "1,8,9",
|
||||
"TagNames": "Boss/Avoidance,Music,Art",
|
||||
"Rating": userData.Ratings[str(mapID)] if str(mapID) in userData.Ratings else -1,
|
||||
"TagIDs": query["TagIDs"],
|
||||
"TagNames": query["TagNames"],
|
||||
}
|
||||
return returned_resp
|
||||
|
||||
|
@ -213,12 +224,10 @@ async def stopMapPlay(
|
|||
)
|
||||
if query is not None:
|
||||
del query["_id"]
|
||||
print(__import__("json").dumps(query, indent=4))
|
||||
|
||||
BestUserTime = None
|
||||
BestTime = None
|
||||
if query is not None and "Leaderboard" in query:
|
||||
print("-" * 3)
|
||||
for i in query["Leaderboard"]:
|
||||
if i["UserID"] == userData.ID:
|
||||
if BestUserTime is None or BestUserTime > i["BestPlaytime"]:
|
||||
|
@ -227,10 +236,7 @@ async def stopMapPlay(
|
|||
BestTime = i["BestPlaytime"]
|
||||
if len(query["Leaderboard"]) <= 1 and i["UserID"] != userData.ID:
|
||||
FirstClear = True
|
||||
print(BestUserTime, BestTime)
|
||||
if BestUserTime is None or playtime < BestUserTime:
|
||||
print(BestUserTime)
|
||||
|
||||
updateQuery = db.maps_collection.update_one(
|
||||
{"ID": mapID},
|
||||
{"$pull": {"Leaderboard": {"UserID": userData.ID}},
|
||||
|
@ -271,7 +277,6 @@ async def stopMapPlay(
|
|||
},
|
||||
)
|
||||
if BestTime is None or playtime < BestTime:
|
||||
print(BestTime, playtime)
|
||||
NewMapRecord = True
|
||||
|
||||
hook.execute_hooks(
|
||||
|
@ -368,6 +373,84 @@ async def upload_map(
|
|||
return {"MapCode": MapCode}
|
||||
# raise HTTPException(501)
|
||||
|
||||
class Rating(BaseModel):
|
||||
Rating: int
|
||||
|
||||
@app.post("/api/v1/map/{mapID}/rating")
|
||||
async def rateMap(mapID: int, Rating: Rating, Authorization: Union[str, None] = Header(default=None)):
|
||||
authcheck = db.auth_check(Authorization)
|
||||
if not authcheck[0] and authcheck[1] == "nouser":
|
||||
raise HTTPException(404, detail="User not found")
|
||||
elif not authcheck[0] and authcheck[1] == "wrongpass":
|
||||
raise HTTPException(403, detail="Wrong password")
|
||||
elif authcheck[0]:
|
||||
userData = types.User(**authcheck[1])
|
||||
|
||||
userRating = userData.Ratings[str(mapID)] if str(mapID) in userData.Ratings else 0
|
||||
print(userRating, type(userRating))
|
||||
|
||||
|
||||
if Rating.Rating == 5:
|
||||
if userRating is not None and userRating == 5:
|
||||
raise HTTPException(400, detail="Map already rated! Set rating in request to -1 to unrate.")
|
||||
additional = {}
|
||||
if userRating == 1:
|
||||
additional = {"NumThumbsDown": -1}
|
||||
query = db.maps_collection.update_one({"ID": mapID}, {"$inc": {"NumThumbsUp":1, "NumRatings": 1, **additional}})
|
||||
userRating = 5
|
||||
elif Rating.Rating == 1:
|
||||
if userRating is not None and userRating == 1:
|
||||
raise HTTPException(400, detail="Map already rated! Set rating in request to -1 to unrate.")
|
||||
additional = {}
|
||||
if userRating == 5:
|
||||
additional = {"NumThumbsUp": -1}
|
||||
query = db.maps_collection.update_one({"ID": mapID}, {"$inc": {"NumThumbsDown": 1, "NumRatings": 1, **additional}})
|
||||
userRating = 1
|
||||
elif Rating.Rating == -1:
|
||||
if userRating is None or userRating == -1:
|
||||
raise HTTPException(400, detail="Map is not rated!")
|
||||
key = ""
|
||||
if userRating == 5:
|
||||
key = "NumThumbsUp"
|
||||
elif userRating == 1:
|
||||
key = "NumThumbsDown"
|
||||
else:
|
||||
raise HTTPException(400, detail=f"Previous rating was not 5 or 1. It was {userRating} [{repr(type(userRating))}]")
|
||||
query = db.maps_collection.update_one({"ID": mapID}, {"$inc": {"NumRatings": -1, key: -1}})
|
||||
userRating = -1
|
||||
query = db.maps_collection.find_one({"ID": mapID})
|
||||
|
||||
print(userRating, "+")
|
||||
userQuery = db.user_collection.update_one({"ID": userData.ID}, {"$set": {f"Ratings.{mapID}": userRating} })
|
||||
print(userQuery.raw_result)
|
||||
|
||||
return {
|
||||
"Exists": True,
|
||||
"TagIDs": query["TagIDs"],
|
||||
"TagNames": query["TagNames"],
|
||||
"UserMap": {
|
||||
"BestDeaths": 0,
|
||||
"BestFullPlaytime": 0,
|
||||
"BestFullPlaytimeTime": None,
|
||||
"BestPlaytime": 0,
|
||||
"BestPlaytimeTime": None,
|
||||
"BestReplay": "",
|
||||
"Clear": False,
|
||||
"Difficulty": 0,
|
||||
"FirstClearInvalid": False,
|
||||
"FirstClearPlaytime": 0,
|
||||
"FirstClearTime": False,
|
||||
"FirstDeathTimeValid": False,
|
||||
"FirstDeaths": -1,
|
||||
"FirstPlayRecorded": True,
|
||||
"FirstPlaytime": -1,
|
||||
"FullClear": False,
|
||||
"MapID": mapID,
|
||||
"Played": True,
|
||||
"Rating": userRating,
|
||||
"UserID": userData.ID
|
||||
}
|
||||
}
|
||||
|
||||
@app.get("/api/v1/map/{mapID}/besttimes/{maxEntries}")
|
||||
async def getMapLeaderboard(mapID: int, maxEntries: int = 5):
|
||||
|
@ -497,14 +580,14 @@ async def reportContent(
|
|||
async def featuredlist():
|
||||
"""Returns the list id of the weekly levels list."""
|
||||
# FIXME Add playlists
|
||||
return
|
||||
raise HTTPException(404, detail="Not available due to lack of playlist support.")
|
||||
|
||||
|
||||
@app.get("/api/v1/followcheck")
|
||||
async def followcheck():
|
||||
"""Check, if creators that the user follows uploaded new levels."""
|
||||
# FIXME: Stub
|
||||
return 1
|
||||
raise HTTPException(404, detail="Not available due to follows not being implemented.")
|
||||
|
||||
|
||||
def start():
|
||||
|
|
Loading…
Reference in a new issue