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 Reward, model_to_dict, fn, DoesNotExist from ..dependencies import oauth2_scheme, valid_token router = APIRouter(prefix="/api/v2/rewards", tags=["rewards"]) class RewardModel(pydantic.BaseModel): name: str season: int week: int team_id: int created: Optional[int] = int(datetime.timestamp(datetime.now()) * 1000) @router.get("") async def get_rewards( name: Optional[str] = None, in_name: Optional[str] = None, team_id: Optional[int] = None, season: Optional[int] = None, week: Optional[int] = None, created_after: Optional[int] = None, flat: Optional[bool] = False, csv: Optional[bool] = None, limit: Optional[int] = 100, ): all_rewards = Reward.select().order_by(Reward.id) if name is not None: all_rewards = all_rewards.where(fn.Lower(Reward.name) == name.lower()) if team_id is not None: all_rewards = all_rewards.where(Reward.team_id == team_id) if created_after is not None: # Convert milliseconds timestamp to datetime for PostgreSQL comparison created_after_dt = datetime.fromtimestamp(created_after / 1000) all_rewards = all_rewards.where(Reward.created >= created_after_dt) if in_name is not None: all_rewards = all_rewards.where(fn.Lower(Reward.name).contains(in_name.lower())) if season is not None: all_rewards = all_rewards.where(Reward.season == season) if week is not None: all_rewards = all_rewards.where(Reward.week == week) total_count = all_rewards.count() if total_count == 0: raise HTTPException(status_code=404, detail="No rewards found") limit = max(0, min(limit, 500)) all_rewards = all_rewards.limit(limit) if csv: data_list = [["id", "name", "team", "daily", "created"]] for line in all_rewards: data_list.append( [line.id, line.name, line.team.id, line.daily, 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": total_count, "rewards": []} for x in all_rewards: return_val["rewards"].append(model_to_dict(x, recurse=not flat)) return return_val @router.get("/{reward_id}") async def get_one_reward(reward_id, csv: Optional[bool] = False): try: this_reward = Reward.get_by_id(reward_id) except DoesNotExist: raise HTTPException( status_code=404, detail=f"No reward found with id {reward_id}" ) if csv: data_list = [ ["id", "name", "card_count", "description"], [ this_reward.id, this_reward.name, this_reward.team.id, this_reward.daily, this_reward.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_reward) return return_val @router.post("") async def post_rewards(reward: RewardModel, 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 rewards. This event has been logged.", ) reward_data = reward.dict() # Convert milliseconds timestamp to datetime for PostgreSQL if reward_data.get("created"): reward_data["created"] = datetime.fromtimestamp(reward_data["created"] / 1000) this_reward = Reward(**reward_data) saved = this_reward.save() if saved == 1: return_val = model_to_dict(this_reward) return return_val else: raise HTTPException( status_code=418, detail="Well slap my ass and call me a teapot; I could not save that cardset", ) @router.patch("/{reward_id}") async def patch_reward( reward_id, name: Optional[str] = None, team_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 rewards. This event has been logged.", ) try: this_reward = Reward.get_by_id(reward_id) except DoesNotExist: raise HTTPException( status_code=404, detail=f"No reward found with id {reward_id}" ) if name is not None: this_reward.name = name if team_id is not None: this_reward.team_id = team_id if created is not None: # Convert milliseconds timestamp to datetime for PostgreSQL this_reward.created = datetime.fromtimestamp(created / 1000) if this_reward.save() == 1: return_val = model_to_dict(this_reward) 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("/{reward_id}") async def delete_reward(reward_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_reward = Reward.get_by_id(reward_id) except DoesNotExist: raise HTTPException( status_code=404, detail=f"No reward found with id {reward_id}" ) count = this_reward.delete_instance() if count == 1: raise HTTPException( status_code=200, detail=f"Reward {reward_id} has been deleted" ) else: raise HTTPException( status_code=500, detail=f"Reward {reward_id} was not deleted" )