paper-dynasty-database/app/routers_v2/paperdex.py
Cal Corum 87c200d62b feat: add limit/pagination to paperdex endpoint (#143)
Closes #143

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 07:02:47 -05:00

207 lines
6.7 KiB
Python

from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException, Response
from typing import Optional
import logging
import pydantic
from pandas import DataFrame
from ..db_engine import Paperdex, model_to_dict, Player, Cardset, Team, DoesNotExist
from ..dependencies import oauth2_scheme, valid_token
router = APIRouter(prefix="/api/v2/paperdex", tags=["paperdex"])
class PaperdexModel(pydantic.BaseModel):
team_id: int
player_id: int
created: Optional[int] = int(datetime.timestamp(datetime.now()) * 1000)
@router.get("")
async def get_paperdex(
team_id: Optional[int] = None,
player_id: Optional[int] = None,
created_after: Optional[int] = None,
cardset_id: Optional[int] = None,
created_before: Optional[int] = None,
flat: Optional[bool] = False,
csv: Optional[bool] = None,
limit: int = 100,
):
all_dex = Paperdex.select().join(Player).join(Cardset).order_by(Paperdex.id)
if all_dex.count() == 0:
raise HTTPException(status_code=404, detail="There are no paperdex to filter")
if team_id is not None:
all_dex = all_dex.where(Paperdex.team_id == team_id)
if player_id is not None:
all_dex = all_dex.where(Paperdex.player_id == player_id)
if cardset_id is not None:
all_dex = all_dex.where(Paperdex.player.cardset.id == cardset_id)
if created_after is not None:
# Convert milliseconds timestamp to datetime for PostgreSQL comparison
created_after_dt = datetime.fromtimestamp(created_after / 1000)
all_dex = all_dex.where(Paperdex.created >= created_after_dt)
if created_before is not None:
# Convert milliseconds timestamp to datetime for PostgreSQL comparison
created_before_dt = datetime.fromtimestamp(created_before / 1000)
all_dex = all_dex.where(Paperdex.created <= created_before_dt)
# if all_dex.count() == 0:
# db.close()
# raise HTTPException(status_code=404, detail=f'No paperdex found')
limit = max(0, min(limit, 500))
all_dex = all_dex.limit(limit)
if csv:
data_list = [["id", "team_id", "player_id", "created"]]
for line in all_dex:
data_list.append(
[line.id, line.team.id, line.player.player_id, line.created]
)
return_val = DataFrame(data_list).to_csv(header=False, index=False)
return Response(content=return_val, media_type="text/csv")
else:
return_val = {"count": all_dex.count(), "paperdex": []}
for x in all_dex:
return_val["paperdex"].append(model_to_dict(x, recurse=not flat))
return return_val
@router.get("/{paperdex_id}")
async def get_one_paperdex(paperdex_id, csv: Optional[bool] = False):
try:
this_dex = Paperdex.get_by_id(paperdex_id)
except DoesNotExist:
raise HTTPException(
status_code=404, detail=f"No paperdex found with id {paperdex_id}"
)
if csv:
data_list = [
["id", "team_id", "player_id", "created"],
[this_dex.id, this_dex.team.id, this_dex.player.id, this_dex.created],
]
return_val = DataFrame(data_list).to_csv(header=False, index=False)
return Response(content=return_val, media_type="text/csv")
else:
return_val = model_to_dict(this_dex)
return return_val
@router.post("")
async def post_paperdex(paperdex: PaperdexModel, token: str = Depends(oauth2_scheme)):
if not valid_token(token):
logging.warning("Bad Token: [REDACTED]")
raise HTTPException(
status_code=401,
detail="You are not authorized to post paperdex. This event has been logged.",
)
dupe_dex = Paperdex.get_or_none(
Paperdex.team_id == paperdex.team_id, Paperdex.player_id == paperdex.player_id
)
if dupe_dex:
return_val = model_to_dict(dupe_dex)
return return_val
this_dex = Paperdex(
team_id=paperdex.team_id,
player_id=paperdex.player_id,
created=datetime.fromtimestamp(paperdex.created / 1000),
)
saved = this_dex.save()
if saved == 1:
return_val = model_to_dict(this_dex)
return return_val
else:
raise HTTPException(
status_code=418,
detail="Well slap my ass and call me a teapot; I could not save that dex",
)
@router.patch("/{paperdex_id}")
async def patch_paperdex(
paperdex_id,
team_id: Optional[int] = None,
player_id: Optional[int] = None,
created: Optional[int] = None,
token: str = Depends(oauth2_scheme),
):
if not valid_token(token):
logging.warning("Bad Token: [REDACTED]")
raise HTTPException(
status_code=401,
detail="You are not authorized to patch paperdex. This event has been logged.",
)
try:
this_dex = Paperdex.get_by_id(paperdex_id)
except DoesNotExist:
raise HTTPException(
status_code=404, detail=f"No paperdex found with id {paperdex_id}"
)
if team_id is not None:
this_dex.team_id = team_id
if player_id is not None:
this_dex.player_id = player_id
if created is not None:
this_dex.created = datetime.fromtimestamp(created / 1000)
if this_dex.save() == 1:
return_val = model_to_dict(this_dex)
return return_val
else:
raise HTTPException(
status_code=418,
detail="Well slap my ass and call me a teapot; I could not save that rarity",
)
@router.delete("/{paperdex_id}")
async def delete_paperdex(paperdex_id, token: str = Depends(oauth2_scheme)):
if not valid_token(token):
logging.warning("Bad Token: [REDACTED]")
raise HTTPException(
status_code=401,
detail="You are not authorized to delete rewards. This event has been logged.",
)
try:
this_dex = Paperdex.get_by_id(paperdex_id)
except DoesNotExist:
raise HTTPException(
status_code=404, detail=f"No paperdex found with id {paperdex_id}"
)
count = this_dex.delete_instance()
if count == 1:
raise HTTPException(
status_code=200, detail=f"Paperdex {this_dex} has been deleted"
)
else:
raise HTTPException(
status_code=500, detail=f"Paperdex {this_dex} was not deleted"
)
@router.post("/wipe-ai")
async def wipe_ai_paperdex(token: str = Depends(oauth2_scheme)):
if not valid_token(token):
logging.warning("Bad Token: [REDACTED]")
raise HTTPException(status_code=401, detail="Unauthorized")
g_teams = Team.select().where(Team.abbrev.contains("Gauntlet"))
count = Paperdex.delete().where(Paperdex.team << g_teams).execute()
return f"Deleted {count} records"