diff --git a/customiwmserver/data_types.py b/customiwmserver/data_types.py index 9ac6567..525e5eb 100644 --- a/customiwmserver/data_types.py +++ b/customiwmserver/data_types.py @@ -1,6 +1,6 @@ from pydantic import BaseModel from typing import List, Optional, Union - +from datetime import datetime class User(BaseModel): """Pydantic model for user data. @@ -13,7 +13,7 @@ class User(BaseModel): CapeColor: int = 0 Costume: int = 0 Country: int = 0 - CreatedAt: str = "2020-02-14T10:03:40Z" + CreatedAt: str = datetime.strftime(datetime.now(), "%Y-%m-%dT%H:%M:%SZ") DeathEffect: int = 0 DeletedAt: Optional[str] = None FacialExpression: int = 0 @@ -49,7 +49,7 @@ class User(BaseModel): SwordSpr: int = 0 TextSnd: int = 0 Unlocks: str = "" - UpdatedAt: str = "2020-03-26T05:22:32Z" + UpdatedAt: str = datetime.strftime(datetime.now(), "%Y-%m-%dT%H:%M:%SZ") Username: str = "magmaus3" Email: str = "user@example.com" @@ -115,8 +115,8 @@ class Notification(BaseModel): otherwise the game crashes (as of `Early Access Ver 0.786`) """ - CreatedAt: str = "2008-01-18T00:00:00Z" - UpdatedAt: str = "2008-01-18T00:00:00Z" + CreatedAt: str = datetime.strftime(datetime.now(), "%Y-%m-%dT%H:%M:%SZ") + UpdatedAt: str = datetime.strftime(datetime.now(), "%Y-%m-%dT%H:%M:%SZ") DeletedAt: Optional[str] = None ForUserID: int = 0 ID: int = 0 @@ -151,7 +151,7 @@ class Map(BaseModel): Name: str = "Interesting level" Description: str = "" Version: int = 90 - CreatedAt: str = "2022-06-18T15:10:02Z" + CreatedAt: str = datetime.strftime(datetime.now(), "%Y-%m-%dT%H:%M:%SZ") DeletedAt: Union[str, None] = None MapCode: str = "AAABBAAA" Listed: bool = True @@ -234,7 +234,7 @@ class MapLeaderboard(BaseModel): """Pydantic model for Map record leaderboards.""" BestPlaytime: int - BestPlaytimeTime: str + BestPlaytimeTime: str = datetime.strftime(datetime.now(), "%Y-%m-%dT%H:%M:%SZ") BestReplay: str CreatorName: str UserID: int diff --git a/customiwmserver/main.py b/customiwmserver/main.py index 395e431..57cb814 100644 --- a/customiwmserver/main.py +++ b/customiwmserver/main.py @@ -1,3 +1,4 @@ +from datetime import datetime from fastapi import FastAPI, Form, File, UploadFile, Header, HTTPException, Body from fastapi.responses import PlainTextResponse from fastapi.exceptions import RequestValidationError @@ -114,16 +115,46 @@ async def search_for_maps( author: str = "", author_id: Optional[int] = None, last_x_hours: Optional[int] = None, + required_tags: str = "", + disallowed_tags: str = "", + code: Optional[str] = None, + admin_show_unlisted: Optional[int] = 0, ): """Search for maps.""" # query = db.maps_collection.find({ "CreatorId": author_id }).limit(limit) - query = db.maps_collection.find({}).limit(limit) + if code: + query = list(db.maps_collection.find({"MapCode": code}).skip(start).limit(limit))[0] + del query["_id"] + del query["MapData"] + return [query] + + query = db.maps_collection.find({}).skip(start).limit(limit) entries = [] + + # Convert required_tags and disallowed_tags to a list. + required_tag_list = required_tags.split(",") if required_tags != "" else [] + disallowed_tag_list = disallowed_tags.split(",") if disallowed_tags != "" else [] for i in query: del i["_id"] del i["MapData"] - entries.append(i) + + if not i["Listed"] and admin_show_unlisted != 1: + continue + + level_tags = i['TagIDs'].split(",") + CreatedAt = datetime.strptime(i["CreatedAt"], "%Y-%m-%dT%H:%M:%SZ") + + # TODO: Improve tag filtering + required_tags_included = False if len(required_tag_list) != 0 else True + disallowed_tags_included = False + for tag in level_tags: + if tag in disallowed_tag_list and len(disallowed_tag_list) != 0: disallowed_tags_included = True + elif tag in required_tag_list and len(required_tag_list) != 0: required_tags_included = True + else: + if required_tags_included and not disallowed_tags_included: + if not last_x_hours or CreatedAt.hour < last_x_hours: + entries.append(i) return entries @@ -135,7 +166,7 @@ async def getMap(mapID: int): @app.post("/api/v1/map/{mapID}/start") -async def getMap(mapID: int): +async def startMap(mapID: int): query = db.maps_collection.find_one({"ID": mapID}) del query["_id"] @@ -232,7 +263,6 @@ async def stopMapPlay( SaveEffect=userData.SaveEffect, TextSnd=userData.TextSnd, BestPlaytime=playtime, - BestPlaytimeTime="2020-02-13T15:19:33Z", BestReplay=replayData, CreatorName=userData.Username, UserID=userData.ID, @@ -327,7 +357,6 @@ async def upload_map( Leaderboard=[ types.MapLeaderboard( BestPlaytime=playtime, - BestPlaytimeTime="2020-02-13T15:19:33Z", BestReplay=mapReplay, CreatorName=userData.Username, UserID=userData.ID, @@ -341,7 +370,7 @@ async def upload_map( @app.get("/api/v1/map/{mapID}/besttimes/{maxEntries}") -async def getMapLeaderboard(mapID, maxEntries): +async def getMapLeaderboard(mapID: int, maxEntries: int = 5): """Returns maxEntries records for the specified level""" query = db.maps_collection.find_one({"ID": int(mapID)}) if not query: @@ -349,7 +378,7 @@ async def getMapLeaderboard(mapID, maxEntries): del query["_id"] leaderboard = query["Leaderboard"] - return sorted(leaderboard, key=lambda sort: sort["BestPlaytime"])[0:5] + return sorted(leaderboard, key=lambda sort: sort["BestPlaytime"])[0:maxEntries] @app.get("/api/v1/map/{mapID}/userbesttime/{userID}") @@ -473,7 +502,8 @@ async def featuredlist(): @app.get("/api/v1/followcheck") async def followcheck(): - # FIXME Find the purpouse of this endpoint + """Check, if creators that the user follows uploaded new levels.""" + # FIXME: Stub return 1