- Add db_helpers.py with cross-database upsert functions for SQLite/PostgreSQL - Replace 12 on_conflict_replace() calls with PostgreSQL-compatible upserts - Add unique indexes: StratPlay(game, play_num), Decision(game, pitcher) - Add max_length to Team model fields (abbrev, sname, lname) - Fix boolean comparison in teams.py (== 0/1 to == False/True) - Create migrate_to_postgres.py with ID-preserving migration logic - Create audit_sqlite.py for pre-migration data integrity checks - Add PROJECT_PLAN.json for migration tracking - Add .secrets/ to .gitignore for credentials Audit results: 658,963 records across 29 tables, 2,390 orphaned stats (expected) Based on Major Domo migration lessons learned (33 issues resolved there)
6364 lines
200 KiB
Python
6364 lines
200 KiB
Python
from datetime import datetime
|
|
import logging
|
|
import os
|
|
|
|
from db_engine import *
|
|
from app.db_helpers import upsert_players, upsert_gauntlet_rewards
|
|
from typing import Optional, List, Union, Literal
|
|
from fastapi import FastAPI, HTTPException, Depends, Response, Query
|
|
from fastapi.security import OAuth2PasswordBearer
|
|
import pydantic
|
|
import pygsheets
|
|
import sheets
|
|
|
|
from playhouse.shortcuts import model_to_dict
|
|
from pandas import DataFrame
|
|
|
|
raw_log_level = os.getenv("LOG_LEVEL")
|
|
if raw_log_level == "INFO":
|
|
log_level = logging.INFO
|
|
elif raw_log_level == "WARN":
|
|
log_level = logging.WARN
|
|
else:
|
|
log_level = logging.ERROR
|
|
|
|
date = f"{datetime.now().year}-{datetime.now().month}-{datetime.now().day}"
|
|
logging.basicConfig(
|
|
filename=f"logs/database/{date}.log",
|
|
format="%(asctime)s - %(levelname)s - %(message)s",
|
|
level=log_level,
|
|
)
|
|
|
|
app = FastAPI()
|
|
|
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
|
DEFAULT_SEASON = 5
|
|
|
|
# Franchise normalization: Convert city+team names to city-agnostic team names
|
|
# This enables cross-era player matching (e.g., 'Oakland Athletics' -> 'Athletics')
|
|
FRANCHISE_NORMALIZE = {
|
|
"Arizona Diamondbacks": "Diamondbacks",
|
|
"Atlanta Braves": "Braves",
|
|
"Baltimore Orioles": "Orioles",
|
|
"Boston Red Sox": "Red Sox",
|
|
"Chicago Cubs": "Cubs",
|
|
"Chicago White Sox": "White Sox",
|
|
"Cincinnati Reds": "Reds",
|
|
"Cleveland Guardians": "Guardians",
|
|
"Colorado Rockies": "Rockies",
|
|
"Detroit Tigers": "Tigers",
|
|
"Houston Astros": "Astros",
|
|
"Kansas City Royals": "Royals",
|
|
"Los Angeles Angels": "Angels",
|
|
"Los Angeles Dodgers": "Dodgers",
|
|
"Miami Marlins": "Marlins",
|
|
"Milwaukee Brewers": "Brewers",
|
|
"Minnesota Twins": "Twins",
|
|
"New York Mets": "Mets",
|
|
"New York Yankees": "Yankees",
|
|
"Oakland Athletics": "Athletics",
|
|
"Philadelphia Phillies": "Phillies",
|
|
"Pittsburgh Pirates": "Pirates",
|
|
"San Diego Padres": "Padres",
|
|
"San Francisco Giants": "Giants",
|
|
"Seattle Mariners": "Mariners",
|
|
"St Louis Cardinals": "Cardinals",
|
|
"St. Louis Cardinals": "Cardinals",
|
|
"Tampa Bay Rays": "Rays",
|
|
"Texas Rangers": "Rangers",
|
|
"Toronto Blue Jays": "Blue Jays",
|
|
"Washington Nationals": "Nationals",
|
|
}
|
|
|
|
|
|
def normalize_franchise(franchise: str) -> str:
|
|
"""Convert city+team name to team-only (e.g., 'Oakland Athletics' -> 'Athletics')"""
|
|
titled = franchise.title()
|
|
return FRANCHISE_NORMALIZE.get(titled, titled)
|
|
|
|
|
|
SHEETS_AUTH = pygsheets.authorize(
|
|
service_file="storage/paper-dynasty-service-creds.json", retries=1
|
|
)
|
|
|
|
|
|
def valid_token(token):
|
|
if token == os.environ.get("API_TOKEN"):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def int_timestamp(datetime_obj: datetime) -> int:
|
|
return int(datetime.timestamp(datetime_obj) * 1000)
|
|
|
|
|
|
"""
|
|
CURRENT ENDPOINTS
|
|
"""
|
|
|
|
|
|
class CurrentModel(pydantic.BaseModel):
|
|
season: int
|
|
week: int
|
|
gsheet_template: str
|
|
gsheet_version: str
|
|
|
|
|
|
@app.get("/api/v1/current")
|
|
async def v1_current_get(season: Optional[int] = None, csv: Optional[bool] = False):
|
|
if season:
|
|
current = Current.get_or_none(season=season)
|
|
else:
|
|
current = Current.latest()
|
|
|
|
if csv:
|
|
current_list = [
|
|
["id", "season", "week"],
|
|
[current.id, current.season, current.week],
|
|
]
|
|
return_val = DataFrame(current_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
else:
|
|
return_val = model_to_dict(current)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/current/{current_id}")
|
|
async def v1_current_get_one(current_id, csv: Optional[bool] = False):
|
|
try:
|
|
current = Current.get_by_id(current_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No current found with id {current_id}"
|
|
)
|
|
|
|
if csv:
|
|
current_list = [
|
|
["id", "season", "week"],
|
|
[current.id, current.season, current.week],
|
|
]
|
|
return_val = DataFrame(current_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
else:
|
|
return_val = model_to_dict(current)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/current")
|
|
async def v1_current_post(current: CurrentModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post current. This event has been logged.",
|
|
)
|
|
|
|
dupe_curr = Current.get_or_none(Current.season == current.season)
|
|
if dupe_curr:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail=f"There is already a current for season {current.season}",
|
|
)
|
|
|
|
this_curr = Current(
|
|
season=current.season,
|
|
week=current.week,
|
|
gsheet_template=current.gsheet_template,
|
|
gsheet_version=current.gsheet_version,
|
|
)
|
|
|
|
saved = this_curr.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_curr)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that team",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/current/{current_id}")
|
|
async def v1_current_patch(
|
|
current_id: int,
|
|
season: Optional[int] = None,
|
|
week: Optional[int] = None,
|
|
gsheet_template: Optional[str] = None,
|
|
gsheet_version: Optional[str] = None,
|
|
live_scoreboard: Optional[int] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch current. This event has been logged.",
|
|
)
|
|
try:
|
|
current = Current.get_by_id(current_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No current found with id {current_id}"
|
|
)
|
|
|
|
if season is not None:
|
|
current.season = season
|
|
if week is not None:
|
|
current.week = week
|
|
if gsheet_template is not None:
|
|
current.gsheet_template = gsheet_template
|
|
if gsheet_version is not None:
|
|
current.gsheet_version = gsheet_version
|
|
if live_scoreboard is not None:
|
|
current.live_scoreboard = live_scoreboard
|
|
|
|
if current.save() == 1:
|
|
return_val = model_to_dict(current)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that current",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/current/{current_id}")
|
|
async def v1_current_delete(current_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete current. This event has been logged.",
|
|
)
|
|
try:
|
|
this_curr = Current.get_by_id(current_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No current found with id {current_id}"
|
|
)
|
|
|
|
count = this_curr.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Current {current_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=500, detail=f"Current {current_id} was not deleted"
|
|
)
|
|
|
|
|
|
"""
|
|
TEAMS ENDPOINTS
|
|
"""
|
|
|
|
|
|
class TeamModel(pydantic.BaseModel):
|
|
abbrev: str
|
|
sname: str
|
|
lname: str
|
|
gmid: int
|
|
gmname: str
|
|
wallet: int = 0
|
|
gsheet: str
|
|
team_value: int = 0
|
|
collection_value: int = 0
|
|
logo: Optional[str] = None
|
|
color: Optional[str] = None
|
|
season: int
|
|
ps_shiny: Optional[int] = 0
|
|
ranking: Optional[int] = 1000
|
|
has_guide: Optional[bool] = False
|
|
is_ai: Optional[bool] = False
|
|
|
|
|
|
@app.get("/api/v1/teams")
|
|
async def v1_teams_get(
|
|
season: Optional[int] = None,
|
|
gm_id: Optional[int] = None,
|
|
abbrev: Optional[str] = None,
|
|
tv_min: Optional[int] = None,
|
|
tv_max: Optional[int] = None,
|
|
cv_min: Optional[int] = None,
|
|
cv_max: Optional[int] = None,
|
|
ps_shiny_min: Optional[int] = None,
|
|
ps_shiny_max: Optional[int] = None,
|
|
ranking_min: Optional[int] = None,
|
|
ranking_max: Optional[int] = None,
|
|
has_guide: Optional[bool] = None,
|
|
sname: Optional[str] = None,
|
|
lname: Optional[str] = None,
|
|
is_ai: Optional[bool] = None,
|
|
event_id: Optional[int] = None,
|
|
limit: Optional[int] = None,
|
|
csv: Optional[bool] = False,
|
|
):
|
|
"""
|
|
Param: season: int
|
|
Param: team_abbrev: string
|
|
Param: owner_id: int
|
|
"""
|
|
if season:
|
|
all_teams = Team.select_season(season)
|
|
else:
|
|
all_teams = Team.select()
|
|
|
|
# if all_teams.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'There are no teams to filter')
|
|
|
|
if gm_id is not None:
|
|
all_teams = all_teams.where(Team.gmid == gm_id)
|
|
|
|
if abbrev is not None:
|
|
all_teams = all_teams.where(fn.Lower(Team.abbrev) == abbrev.lower())
|
|
|
|
if sname is not None:
|
|
all_teams = all_teams.where(fn.Lower(Team.sname) == sname.lower())
|
|
|
|
if lname is not None:
|
|
all_teams = all_teams.where(fn.Lower(Team.lname) == lname.lower())
|
|
|
|
if tv_min is not None:
|
|
all_teams = all_teams.where(Team.team_value >= tv_min)
|
|
|
|
if tv_max is not None:
|
|
all_teams = all_teams.where(Team.team_value <= tv_max)
|
|
|
|
if cv_min is not None:
|
|
all_teams = all_teams.where(Team.collection_value >= cv_min)
|
|
|
|
if cv_max is not None:
|
|
all_teams = all_teams.where(Team.collection_value <= cv_max)
|
|
|
|
if ps_shiny_min is not None:
|
|
all_teams = all_teams.where(Team.career >= ps_shiny_min)
|
|
|
|
if ps_shiny_max is not None:
|
|
all_teams = all_teams.where(Team.career <= ps_shiny_max)
|
|
|
|
if ranking_min is not None:
|
|
all_teams = all_teams.where(Team.ranking >= ranking_min)
|
|
|
|
if ranking_max is not None:
|
|
all_teams = all_teams.where(Team.ranking <= ranking_max)
|
|
|
|
if ranking_max is not None:
|
|
all_teams = all_teams.where(Team.ranking <= ranking_max)
|
|
|
|
if has_guide is not None:
|
|
if not has_guide:
|
|
all_teams = all_teams.where(Team.has_guide == 0)
|
|
else:
|
|
all_teams = all_teams.where(Team.has_guide == 1)
|
|
|
|
if is_ai is not None:
|
|
all_teams = all_teams.where(Team.is_ai)
|
|
|
|
if event_id is not None:
|
|
all_teams = all_teams.where(Team.event_id == event_id)
|
|
|
|
if limit is not None:
|
|
all_teams = all_teams.limit(limit)
|
|
|
|
# if all_teams.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'No teams found')
|
|
|
|
if csv:
|
|
data_list = [
|
|
[
|
|
"id",
|
|
"abbrev",
|
|
"sname",
|
|
"lname",
|
|
"gmid",
|
|
"gmname",
|
|
"wallet",
|
|
"gsheet",
|
|
"team_value",
|
|
"collection_value",
|
|
"logo",
|
|
"color",
|
|
"season",
|
|
"ranking",
|
|
]
|
|
]
|
|
for line in all_teams:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.abbrev,
|
|
line.sname,
|
|
line.lname,
|
|
line.gmid,
|
|
line.gmname,
|
|
line.wallet,
|
|
line.gsheet,
|
|
line.team_value,
|
|
line.collection_value,
|
|
line.logo,
|
|
f"'{line.color}",
|
|
line.season,
|
|
line.ranking,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_teams = {"count": all_teams.count(), "teams": []}
|
|
for x in all_teams:
|
|
return_teams["teams"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_teams
|
|
|
|
|
|
@app.get("/api/v1/teams/{team_id}")
|
|
async def v1_teams_get_one(team_id, csv: Optional[bool] = False):
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No team found with id {team_id}")
|
|
|
|
if csv:
|
|
team_packs = Pack.select().where(
|
|
(Pack.team == this_team) & (Pack.open_time.is_null(True))
|
|
)
|
|
data_list = [
|
|
[
|
|
"id",
|
|
"abbrev",
|
|
"sname",
|
|
"lname",
|
|
"gmid",
|
|
"gmname",
|
|
"wallet",
|
|
"ranking",
|
|
"gsheet",
|
|
"sealed_packs",
|
|
"collection_value",
|
|
"logo",
|
|
"color",
|
|
"season",
|
|
],
|
|
[
|
|
this_team.id,
|
|
this_team.abbrev,
|
|
this_team.sname,
|
|
this_team.lname,
|
|
this_team.gmid,
|
|
this_team.gmname,
|
|
this_team.wallet,
|
|
this_team.ranking,
|
|
this_team.gsheet,
|
|
team_packs.count(),
|
|
this_team.collection_value,
|
|
this_team.logo,
|
|
this_team.color,
|
|
this_team.season,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
else:
|
|
return_val = model_to_dict(this_team)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/teams/{team_id}/buy/players")
|
|
async def v1_team_cards_buy(team_id: int, ids: str, ts: str):
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No team found with id {team_id}")
|
|
|
|
if ts != this_team.team_hash():
|
|
logging.warning(f"Bad Team Secret: {ts} ({this_team.team_hash()})")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail=f"You are not authorized to buy {this_team.abbrev} cards. This event has been logged.",
|
|
)
|
|
|
|
last_card = Card.select(Card.id).order_by(-Card.id).limit(1)
|
|
lc_id = last_card[0].id
|
|
|
|
all_ids = ids.split(",")
|
|
conf_message = ""
|
|
total_cost = 0
|
|
for player_id in all_ids:
|
|
if player_id != "":
|
|
try:
|
|
this_player = Player.get_by_id(player_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404,
|
|
detail=f"No player found with id {player_id} /// "
|
|
f"{conf_message} purchased",
|
|
)
|
|
|
|
# check wallet balance
|
|
if this_team.wallet < this_player.cost:
|
|
logging.info(
|
|
f"{this_player} was not purchased. {this_team.lname} only has {this_team.wallet}₼, but "
|
|
f"{this_player} costs {this_player.cost}₼."
|
|
)
|
|
db.close()
|
|
raise HTTPException(
|
|
200,
|
|
detail=f"{this_player} was not purchased. {this_team.lname} only has {this_team.wallet}₼, but "
|
|
f"{this_player} costs {this_player.cost}₼. /// {conf_message} purchased",
|
|
)
|
|
|
|
# Create player card and update cost
|
|
buy_price = this_player.cost
|
|
total_cost += buy_price
|
|
this_card = Card(
|
|
player_id=this_player.player_id, team_id=this_team.id, value=buy_price
|
|
)
|
|
Paperdex.get_or_create(team_id=team_id, player_id=this_player.player_id)
|
|
this_card.save()
|
|
this_player.change_on_buy()
|
|
|
|
# Deduct card cost from team
|
|
logging.info(f"{this_team.abbrev} starting wallet: {this_team.wallet}")
|
|
this_team.wallet -= buy_price
|
|
this_team.save()
|
|
logging.info(f"{this_team.abbrev} ending wallet: {this_team.wallet}")
|
|
|
|
# Post a notification
|
|
if this_player.rarity.value >= 2:
|
|
new_notif = Notification(
|
|
created=int_timestamp(datetime.now()),
|
|
title=f"Price Change",
|
|
desc="Modified by buying and selling",
|
|
field_name=f"{this_player.description}",
|
|
message=f"From {buy_price}₼ 📈 to **{this_player.cost}**₼",
|
|
about=f"Player-{this_player.player_id}",
|
|
)
|
|
new_notif.save()
|
|
|
|
conf_message += (
|
|
f"{buy_price}₼ for {this_player.rarity.name} {this_player.p_name} "
|
|
f"({this_player.cardset.name}), "
|
|
)
|
|
|
|
# sheets.post_new_cards(SHEETS_AUTH, lc_id)
|
|
|
|
raise HTTPException(
|
|
status_code=200,
|
|
detail=f"{conf_message} purchased. /// Total Cost: {total_cost}₼ /// "
|
|
f"Final Wallet: {this_team.wallet}",
|
|
)
|
|
|
|
|
|
@app.get("/api/v1/teams/{team_id}/buy/pack/{packtype_id}")
|
|
async def v1_team_pack_buy(
|
|
team_id: int, packtype_id: int, ts: str, quantity: Optional[int] = 1
|
|
):
|
|
try:
|
|
this_packtype = PackType.get_by_id(packtype_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No pack type found with id {packtype_id}"
|
|
)
|
|
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No team found with id {team_id}")
|
|
|
|
if ts != this_team.team_hash():
|
|
logging.warning(f"Bad Team Secret: {ts} ({this_team.team_hash()})")
|
|
db.close()
|
|
logging.warning(
|
|
f"team: {this_team} / pack_type: {this_packtype} / secret: {ts} / "
|
|
f"actual: {this_team.team_hash()}"
|
|
)
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail=f"You are not authorized to buy {this_team.abbrev} packs. This event has been logged.",
|
|
)
|
|
|
|
# check wallet balance
|
|
total_cost = this_packtype.cost * quantity
|
|
if this_team.wallet < total_cost:
|
|
db.close()
|
|
raise HTTPException(
|
|
200,
|
|
detail=f"{this_packtype} was not purchased. {this_team.lname} only has {this_team.wallet} bucks, but "
|
|
f"{this_packtype} costs {this_packtype.cost}.",
|
|
)
|
|
|
|
all_packs = []
|
|
for i in range(quantity):
|
|
all_packs.append(Pack(team_id=this_team.id, pack_type_id=this_packtype.id))
|
|
|
|
# Deduct card cost from team
|
|
logging.info(f"{this_team.abbrev} starting wallet: {this_team.wallet}")
|
|
this_team.wallet -= total_cost
|
|
this_team.save()
|
|
logging.info(f"{this_team.abbrev} ending wallet: {this_team.wallet}")
|
|
|
|
with db.atomic():
|
|
Pack.bulk_create(all_packs, batch_size=15)
|
|
db.close()
|
|
|
|
raise HTTPException(
|
|
status_code=200,
|
|
detail=f"Quantity {quantity} {this_packtype.name} pack{'s' if quantity > 1 else ''} have been purchased by "
|
|
f"{this_team.lname} for {total_cost} bucks. You may close this window.",
|
|
)
|
|
|
|
|
|
@app.get("/api/v1/teams/{team_id}/sell/cards")
|
|
async def v1_team_cards_sell(team_id: int, ids: str, ts: str):
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No team found with id {team_id}")
|
|
|
|
if ts != this_team.team_hash():
|
|
logging.warning(f"Bad Team Secret: {ts} ({this_team.team_hash()})")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail=f"You are not authorized to sell {this_team.abbrev} cards. This event has been logged.",
|
|
)
|
|
|
|
all_ids = ids.split(",")
|
|
del_ids = []
|
|
conf_message = ""
|
|
total_cost = 0
|
|
for card_id in all_ids:
|
|
if card_id != "":
|
|
try:
|
|
this_card = Card.get_by_id(card_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No card found with id {card_id}"
|
|
)
|
|
|
|
del_ids.append(card_id)
|
|
this_player = this_card.player
|
|
|
|
if this_card.team != this_team:
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail=f"Card id {card_id} ({this_player.p_name}) belongs to "
|
|
f"{this_card.team.abbrev} and cannot be sold. /// {conf_message} sold",
|
|
)
|
|
|
|
orig_price = this_player.cost
|
|
sell_price = round(this_player.cost * 0.5)
|
|
total_cost += sell_price
|
|
|
|
# credit selling team's wallet
|
|
if this_team.wallet is None:
|
|
this_team.wallet = sell_price
|
|
else:
|
|
this_team.wallet += sell_price
|
|
this_team.save()
|
|
|
|
# decrease price of player
|
|
this_player.change_on_sell()
|
|
this_card.delete_instance()
|
|
|
|
# post a notification
|
|
if this_player.rarity.value >= 2:
|
|
new_notif = Notification(
|
|
created=int_timestamp(datetime.now()),
|
|
title=f"Price Change",
|
|
desc="Modified by buying and selling",
|
|
field_name=f"{this_player.description}",
|
|
message=f"From {orig_price}₼ 📉 to **{this_player.cost}**₼",
|
|
about=f"Player-{this_player.id}",
|
|
)
|
|
new_notif.save()
|
|
|
|
conf_message += (
|
|
f"{sell_price}₼ for {this_player.rarity.name} {this_player.p_name} "
|
|
f"({this_player.cardset.name}), "
|
|
)
|
|
|
|
# sheets.post_deletion(SHEETS_AUTH, del_ids)
|
|
raise HTTPException(
|
|
status_code=200,
|
|
detail=f"{conf_message} sold. /// Total Earned: {total_cost}₼ /// "
|
|
f"Final Wallet: {this_team.wallet}",
|
|
)
|
|
|
|
|
|
@app.get("/api/v1/teams/{team_id}/cards")
|
|
async def v1_teams_cards_get(team_id, csv: Optional[bool] = True):
|
|
"""
|
|
CSV output specifically targeting team roster sheet
|
|
|
|
Parameters
|
|
----------
|
|
team_id
|
|
csv
|
|
"""
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No team found with id {team_id}")
|
|
|
|
if not csv:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail="The /teams/{team_id}/cards endpoint only supports csv output.",
|
|
)
|
|
|
|
all_cards = (
|
|
Card.select()
|
|
.join(Player)
|
|
.join(Rarity)
|
|
.where(Card.team == this_team)
|
|
.order_by(-Card.player.rarity.value, Card.player.p_name)
|
|
)
|
|
if all_cards.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No cards found")
|
|
|
|
data_list = [
|
|
[
|
|
"cardset",
|
|
"player",
|
|
"rarity",
|
|
"image",
|
|
"image2",
|
|
"pos_1",
|
|
"pos_2",
|
|
"pos_3",
|
|
"pos_4",
|
|
"pos_5",
|
|
"pos_6",
|
|
"pos_7",
|
|
"pos_8",
|
|
"cost",
|
|
"mlbclub",
|
|
"franchise",
|
|
"set_num",
|
|
"bbref_id",
|
|
"player_id",
|
|
"card_id",
|
|
]
|
|
]
|
|
for line in all_cards:
|
|
data_list.append(
|
|
[
|
|
line.player.cardset,
|
|
line.player.p_name,
|
|
line.player.rarity,
|
|
line.player.image,
|
|
line.player.image2,
|
|
line.player.pos_1,
|
|
line.player.pos_2,
|
|
line.player.pos_3,
|
|
line.player.pos_4,
|
|
line.player.pos_5,
|
|
line.player.pos_6,
|
|
line.player.pos_7,
|
|
line.player.pos_8,
|
|
line.player.cost,
|
|
line.player.mlbclub,
|
|
line.player.franchise,
|
|
line.player.set_num,
|
|
line.player.bbref_id,
|
|
line.player.player_id,
|
|
line.id,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
|
|
@app.post("/api/v1/teams")
|
|
async def v1_teams_post(team: TeamModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post teams. This event has been logged.",
|
|
)
|
|
|
|
dupe_team = Team.get_or_none(Team.season == team.season, Team.abbrev == team.abbrev)
|
|
if dupe_team:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail=f"There is already a season {team.season} team using {team.abbrev}",
|
|
)
|
|
|
|
this_team = Team(
|
|
abbrev=team.abbrev,
|
|
sname=team.sname,
|
|
lname=team.lname,
|
|
gmid=team.gmid,
|
|
gmname=team.gmname,
|
|
wallet=team.wallet,
|
|
gsheet=team.gsheet,
|
|
team_value=team.team_value,
|
|
collection_value=team.collection_value,
|
|
logo=team.logo,
|
|
color=team.color,
|
|
ranking=team.ranking,
|
|
season=team.season,
|
|
career=team.ps_shiny,
|
|
has_guide=team.has_guide,
|
|
is_ai=team.is_ai,
|
|
)
|
|
|
|
saved = this_team.save()
|
|
if saved == 1:
|
|
return_team = model_to_dict(this_team)
|
|
db.close()
|
|
return return_team
|
|
else:
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that team",
|
|
)
|
|
|
|
|
|
@app.post("/api/v1/teams/new-season/{new_season}")
|
|
async def v1_teams_new_season(new_season: int, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post teams. This event has been logged.",
|
|
)
|
|
|
|
r_query = Team.update(
|
|
ranking=1000, season=new_season, wallet=Team.wallet + 250
|
|
).execute()
|
|
current = Current.latest()
|
|
current.season = new_season
|
|
current.save()
|
|
db.close()
|
|
|
|
return {
|
|
"detail": f"Team rankings, season, and wallet updated for season {new_season}"
|
|
}
|
|
|
|
|
|
@app.post("/api/v1/teams/{team_id}/money/{delta}")
|
|
async def v1_teams_money_delta(
|
|
team_id: int, delta: int, token: str = Depends(oauth2_scheme)
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to adjust wallets. This event has been logged.",
|
|
)
|
|
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No team found with id {team_id}")
|
|
|
|
this_team.wallet += delta
|
|
|
|
if this_team.save() == 1:
|
|
return_team = model_to_dict(this_team)
|
|
db.close()
|
|
return return_team
|
|
else:
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that team",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/teams/{team_id}")
|
|
async def v1_teams_patch(
|
|
team_id,
|
|
sname: Optional[str] = None,
|
|
lname: Optional[str] = None,
|
|
gmid: Optional[int] = None,
|
|
gmname: Optional[str] = None,
|
|
gsheet: Optional[str] = None,
|
|
team_value: Optional[int] = None,
|
|
collection_value: Optional[int] = None,
|
|
logo: Optional[str] = None,
|
|
color: Optional[str] = None,
|
|
season: Optional[int] = None,
|
|
ps_shiny: Optional[int] = None,
|
|
wallet_delta: Optional[int] = None,
|
|
has_guide: Optional[bool] = None,
|
|
is_ai: Optional[bool] = None,
|
|
ranking: Optional[int] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete teams. This event has been logged.",
|
|
)
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No team found with id {team_id}")
|
|
|
|
if sname is not None:
|
|
this_team.sname = sname
|
|
if lname is not None:
|
|
this_team.lname = lname
|
|
if gmid is not None:
|
|
this_team.gmid = gmid
|
|
if gmname is not None:
|
|
this_team.gmname = gmname
|
|
if gsheet is not None:
|
|
this_team.gsheet = gsheet
|
|
if team_value is not None:
|
|
this_team.team_value = team_value
|
|
if collection_value is not None:
|
|
this_team.collection_value = collection_value
|
|
if logo is not None:
|
|
this_team.logo = logo
|
|
if color is not None:
|
|
this_team.color = color
|
|
if season is not None:
|
|
this_team.season = season
|
|
if ps_shiny is not None:
|
|
this_team.career = ps_shiny
|
|
if ranking is not None:
|
|
this_team.ranking = ranking
|
|
if wallet_delta is not None:
|
|
this_team.wallet += wallet_delta
|
|
if has_guide is not None:
|
|
if has_guide:
|
|
this_team.has_guide = 1
|
|
else:
|
|
this_team.has_guide = 0
|
|
if is_ai is not None:
|
|
if is_ai:
|
|
this_team.is_ai = 1
|
|
else:
|
|
this_team.is_ai = 0
|
|
|
|
if this_team.save() == 1:
|
|
return_team = model_to_dict(this_team)
|
|
db.close()
|
|
return return_team
|
|
else:
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that team",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/teams/{team_id}")
|
|
async def v1_teams_delete(team_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete teams. This event has been logged.",
|
|
)
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No team found with id {team_id}")
|
|
|
|
count = this_team.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(status_code=200, detail=f"Team {team_id} has been deleted")
|
|
else:
|
|
raise HTTPException(status_code=500, detail=f"Team {team_id} was not deleted")
|
|
|
|
|
|
"""
|
|
RARITY ENDPOINTS
|
|
"""
|
|
|
|
|
|
class RarityModel(pydantic.BaseModel):
|
|
value: int
|
|
name: str
|
|
color: str
|
|
|
|
|
|
@app.get("/api/v1/rarities")
|
|
async def v1_rarities_get(
|
|
value: Optional[int] = None,
|
|
name: Optional[str] = None,
|
|
min_value: Optional[int] = None,
|
|
max_value: Optional[int] = None,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_rarities = Rarity.select()
|
|
|
|
if all_rarities.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"There are no rarities to filter")
|
|
|
|
if value is not None:
|
|
all_rarities = all_rarities.where(Rarity.value == value)
|
|
if name is not None:
|
|
all_rarities = all_rarities.where(fn.Lower(Rarity.name) == name.lower())
|
|
if min_value is not None:
|
|
all_rarities = all_rarities.where(Rarity.value >= min_value)
|
|
if max_value is not None:
|
|
all_rarities = all_rarities.where(Rarity.value <= max_value)
|
|
|
|
if all_rarities.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No rarities found")
|
|
|
|
if csv:
|
|
data_list = [["id", "value", "name"]]
|
|
for line in all_rarities:
|
|
data_list.append([line.id, line.value, line.name])
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_rarities.count(), "rarities": []}
|
|
for x in all_rarities:
|
|
return_val["rarities"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/rarities/{rarity_id}")
|
|
async def v1_rarities_get_one(rarity_id, csv: Optional[bool] = False):
|
|
try:
|
|
this_rarity = Rarity.get_by_id(rarity_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No rarity found with id {rarity_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [["id", "value", "name"]]
|
|
for line in this_rarity:
|
|
data_list.append([line.id, line.value, line.name])
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
else:
|
|
return_val = model_to_dict(this_rarity)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/rarities")
|
|
async def v1_rarities_post(rarity: RarityModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post rarities. This event has been logged.",
|
|
)
|
|
|
|
dupe_team = Rarity.get_or_none(Rarity.name)
|
|
if dupe_team:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=400, detail=f"There is already a rarity using {rarity.name}"
|
|
)
|
|
|
|
this_rarity = Rarity(value=rarity.value, name=rarity.name, color=rarity.color)
|
|
|
|
saved = this_rarity.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_rarity)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/rarities/{rarity_id}")
|
|
async def v1_rarities_patch(
|
|
rarity_id,
|
|
value: Optional[int] = None,
|
|
name: Optional[str] = None,
|
|
color: Optional[str] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch rarities. This event has been logged.",
|
|
)
|
|
try:
|
|
this_rarity = Rarity.get_by_id(rarity_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No rarity found with id {rarity_id}"
|
|
)
|
|
|
|
if value is not None:
|
|
this_rarity.value = value
|
|
if name is not None:
|
|
this_rarity.name = name
|
|
if color is not None:
|
|
this_rarity.color = color
|
|
|
|
if this_rarity.save() == 1:
|
|
return_val = model_to_dict(this_rarity)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/rarities/{rarity_id}")
|
|
async def v1_rarities_delete(rarity_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete rarities. This event has been logged.",
|
|
)
|
|
try:
|
|
this_rarity = Rarity.get_by_id(rarity_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No rarity found with id {rarity_id}"
|
|
)
|
|
|
|
count = this_rarity.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Rarity {rarity_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=500, detail=f"Rarity {rarity_id} was not deleted"
|
|
)
|
|
|
|
|
|
"""
|
|
CARDSET ENDPOINTS
|
|
"""
|
|
|
|
|
|
class CardsetModel(pydantic.BaseModel):
|
|
name: str
|
|
description: str
|
|
event_id: Optional[int] = None
|
|
in_packs: Optional[bool] = True
|
|
total_cards: int = 0
|
|
for_purchase: Optional[bool] = True
|
|
ranked_legal: Optional[bool] = True
|
|
|
|
|
|
@app.get("/api/v1/cardsets")
|
|
async def v1_cardsets_get(
|
|
name: Optional[str] = None,
|
|
in_desc: Optional[str] = None,
|
|
event_id: Optional[int] = None,
|
|
in_packs: Optional[bool] = None,
|
|
ranked_legal: Optional[bool] = None,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_cardsets = Cardset.select()
|
|
|
|
if all_cardsets.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"There are no cardsets to filter")
|
|
|
|
if name is not None:
|
|
all_cardsets = all_cardsets.where(fn.Lower(Cardset.name) == name.lower())
|
|
if in_desc is not None:
|
|
all_cardsets = all_cardsets.where(
|
|
fn.Lower(Cardset.description).contains(in_desc.lower())
|
|
)
|
|
if event_id is not None:
|
|
try:
|
|
this_event = Event.get_by_id(event_id)
|
|
all_cardsets = all_cardsets.where(Cardset.event == this_event)
|
|
except Exception as e:
|
|
logging.error(f"Failed to find event {event_id}: {e}")
|
|
raise HTTPException(
|
|
status_code=404, detail=f"Event id {event_id} not found"
|
|
)
|
|
if in_packs is not None:
|
|
all_cardsets = all_cardsets.where(Cardset.in_packs == in_packs)
|
|
if ranked_legal is not None:
|
|
all_cardsets = all_cardsets.where(Cardset.ranked_legal == ranked_legal)
|
|
|
|
if all_cardsets.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No cardsets found")
|
|
|
|
if csv:
|
|
data_list = [
|
|
[
|
|
"id",
|
|
"name",
|
|
"description",
|
|
"event_id",
|
|
"in_packs",
|
|
"for_purchase",
|
|
"total_cards",
|
|
"ranked_legal",
|
|
]
|
|
]
|
|
for line in all_cardsets:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.name,
|
|
line.description,
|
|
line.event.id if line.event else "",
|
|
line.in_packs,
|
|
line.for_purchase,
|
|
line.total_cards,
|
|
line.ranked_legal,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_cardsets.count(), "cardsets": []}
|
|
for x in all_cardsets:
|
|
return_val["cardsets"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/cardsets/{cardset_id}")
|
|
async def v1_cardsets_get_one(cardset_id, csv: Optional[bool] = False):
|
|
try:
|
|
this_cardset = Cardset.get_by_id(cardset_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No cardset found with id {cardset_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "name", "description"],
|
|
[this_cardset.id, this_cardset.name, this_cardset.description],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
else:
|
|
return_val = model_to_dict(this_cardset)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/cardsets")
|
|
async def v1_cardsets_post(cardset: CardsetModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post cardsets. This event has been logged.",
|
|
)
|
|
|
|
dupe_set = Cardset.get_or_none(Cardset.name == cardset.name)
|
|
if dupe_set:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=400, detail=f"There is already a cardset using {cardset.name}"
|
|
)
|
|
|
|
this_cardset = Cardset(**cardset.__dict__)
|
|
|
|
saved = this_cardset.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_cardset)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/cardsets/{cardset_id}")
|
|
async def v1_cardsets_patch(
|
|
cardset_id,
|
|
name: Optional[str] = None,
|
|
description: Optional[str] = None,
|
|
in_packs: Optional[bool] = None,
|
|
for_purchase: Optional[bool] = None,
|
|
total_cards: Optional[int] = None,
|
|
ranked_legal: Optional[bool] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch cardsets. This event has been logged.",
|
|
)
|
|
try:
|
|
this_cardset = Cardset.get_by_id(cardset_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No cardset found with id {cardset_id}"
|
|
)
|
|
|
|
if name is not None:
|
|
this_cardset.name = name
|
|
if description is not None:
|
|
this_cardset.description = description
|
|
if in_packs is not None:
|
|
this_cardset.in_packs = in_packs
|
|
if for_purchase is not None:
|
|
this_cardset.for_purchase = for_purchase
|
|
if total_cards is not None:
|
|
this_cardset.total_cards = total_cards
|
|
if ranked_legal is not None:
|
|
this_cardset.ranked_legal = ranked_legal
|
|
|
|
if this_cardset.save() == 1:
|
|
return_val = model_to_dict(this_cardset)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/cardsets/{cardset_id}")
|
|
async def v1_cardsets_delete(cardset_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete cardsets. This event has been logged.",
|
|
)
|
|
try:
|
|
this_cardset = Cardset.get_by_id(cardset_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No cardset found with id {cardset_id}"
|
|
)
|
|
|
|
count = this_cardset.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Cardset {cardset_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=500, detail=f"Cardset {cardset_id} was not deleted"
|
|
)
|
|
|
|
|
|
"""
|
|
PLAYER ENDPOINTS
|
|
"""
|
|
|
|
|
|
class PlayerPydantic(pydantic.BaseModel):
|
|
player_id: int
|
|
p_name: str
|
|
cost: int
|
|
image: str
|
|
image2: Optional[str] = None
|
|
mlbclub: str
|
|
franchise: str
|
|
cardset_id: int
|
|
set_num: int
|
|
rarity_id: int
|
|
pos_1: str
|
|
pos_2: Optional[str] = None
|
|
pos_3: Optional[str] = None
|
|
pos_4: Optional[str] = None
|
|
pos_5: Optional[str] = None
|
|
pos_6: Optional[str] = None
|
|
pos_7: Optional[str] = None
|
|
pos_8: Optional[str] = None
|
|
headshot: Optional[str] = None
|
|
vanity_card: Optional[str] = None
|
|
strat_code: Optional[str] = None
|
|
bbref_id: Optional[str] = None
|
|
fangr_id: Optional[str] = None
|
|
description: str
|
|
quantity: Optional[int] = 999
|
|
|
|
|
|
class PlayerModel(pydantic.BaseModel):
|
|
players: List[PlayerPydantic]
|
|
|
|
|
|
# NOT A TEMPLATE - BROKE MOLD FOR pos_exclude
|
|
@app.get("/api/v1/players")
|
|
async def v1_players_get(
|
|
name: Optional[str] = None,
|
|
value: Optional[int] = None,
|
|
min_cost: Optional[int] = None,
|
|
max_cost: Optional[int] = None,
|
|
has_image2: Optional[bool] = None,
|
|
mlbclub: Optional[str] = None,
|
|
franchise: Optional[str] = None,
|
|
cardset_id: list = Query(default=None),
|
|
rarity_id: list = Query(default=None),
|
|
pos_include: list = Query(default=None),
|
|
pos_exclude: list = Query(default=None),
|
|
has_headshot: Optional[bool] = None,
|
|
has_vanity_card: Optional[bool] = None,
|
|
strat_code: Optional[str] = None,
|
|
bbref_id: Optional[str] = None,
|
|
fangr_id: Optional[str] = None,
|
|
inc_dex: Optional[bool] = True,
|
|
in_desc: Optional[str] = None,
|
|
flat: Optional[bool] = False,
|
|
sort_by: Optional[str] = False,
|
|
cardset_id_exclude: list = Query(default=None),
|
|
limit: Optional[int] = None,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_players = Player.select()
|
|
if all_players.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"There are no players to filter")
|
|
|
|
if name is not None:
|
|
all_players = all_players.where(fn.Lower(Player.p_name) == name.lower())
|
|
if value is not None:
|
|
all_players = all_players.where(Player.cost == value)
|
|
if min_cost is not None:
|
|
all_players = all_players.where(Player.cost >= min_cost)
|
|
if max_cost is not None:
|
|
all_players = all_players.where(Player.cost <= max_cost)
|
|
if has_image2 is not None:
|
|
all_players = all_players.where(Player.image2.is_null(not has_image2))
|
|
if mlbclub is not None:
|
|
all_players = all_players.where(fn.Lower(Player.mlbclub) == mlbclub.lower())
|
|
if franchise is not None:
|
|
all_players = all_players.where(fn.Lower(Player.franchise) == franchise.lower())
|
|
if cardset_id is not None:
|
|
all_players = all_players.where(Player.cardset_id << cardset_id)
|
|
if cardset_id_exclude is not None:
|
|
all_players = all_players.where(Player.cardset_id.not_in(cardset_id_exclude))
|
|
if rarity_id is not None:
|
|
all_players = all_players.where(Player.rarity_id << rarity_id)
|
|
if pos_include is not None:
|
|
p_list = [x.upper() for x in pos_include]
|
|
all_players = all_players.where(
|
|
(Player.pos_1 << p_list)
|
|
| (Player.pos_2 << p_list)
|
|
| (Player.pos_3 << p_list)
|
|
| (Player.pos_4 << p_list)
|
|
| (Player.pos_5 << p_list)
|
|
| (Player.pos_6 << p_list)
|
|
| (Player.pos_7 << p_list)
|
|
| (Player.pos_8 << p_list)
|
|
)
|
|
if has_headshot is not None:
|
|
all_players = all_players.where(Player.headshot.is_null(not has_headshot))
|
|
if has_vanity_card is not None:
|
|
all_players = all_players.where(Player.vanity_card.is_null(not has_vanity_card))
|
|
if strat_code is not None:
|
|
all_players = all_players.where(Player.strat_code == strat_code)
|
|
if bbref_id is not None:
|
|
all_players = all_players.where(Player.bbref_id == bbref_id)
|
|
if fangr_id is not None:
|
|
all_players = all_players.where(Player.fangr_id == fangr_id)
|
|
if in_desc is not None:
|
|
all_players = all_players.where(
|
|
fn.Lower(Player.description).contains(in_desc.lower())
|
|
)
|
|
|
|
if sort_by is not None:
|
|
if sort_by == "cost-desc":
|
|
all_players = all_players.order_by(-Player.cost)
|
|
elif sort_by == "cost-asc":
|
|
all_players = all_players.order_by(Player.cost)
|
|
elif sort_by == "name-asc":
|
|
all_players = all_players.order_by(Player.p_name)
|
|
elif sort_by == "name-desc":
|
|
all_players = all_players.order_by(-Player.p_name)
|
|
elif sort_by == "rarity-desc":
|
|
all_players = all_players.order_by(Player.rarity)
|
|
elif sort_by == "rarity-asc":
|
|
all_players = all_players.order_by(-Player.rarity)
|
|
|
|
final_players = []
|
|
# logging.info(f'pos_exclude: {type(pos_exclude)} - {pos_exclude} - is None: {pos_exclude is None}')
|
|
for x in all_players:
|
|
if pos_exclude is not None and set(
|
|
[x.upper() for x in pos_exclude]
|
|
).intersection(x.get_all_pos()):
|
|
pass
|
|
else:
|
|
final_players.append(x)
|
|
|
|
if limit is not None and len(final_players) >= limit:
|
|
break
|
|
|
|
# if len(final_players) == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'No players found')
|
|
|
|
if csv:
|
|
all_players.order_by(-Player.rarity.value, Player.p_name)
|
|
data_list = [
|
|
[
|
|
"id",
|
|
"name",
|
|
"value",
|
|
"image",
|
|
"image2",
|
|
"mlbclub",
|
|
"franchise",
|
|
"cardset",
|
|
"rarity",
|
|
"pos_1",
|
|
"pos_2",
|
|
"pos_3",
|
|
"pos_4",
|
|
"pos_5",
|
|
"pos_6",
|
|
"pos_7",
|
|
"pos_8",
|
|
"headshot",
|
|
"vanity_card",
|
|
"strat_code",
|
|
"bbref_id",
|
|
"description",
|
|
"for_purchase",
|
|
"ranked_legal",
|
|
]
|
|
]
|
|
for line in final_players:
|
|
data_list.append(
|
|
[
|
|
line.player_id,
|
|
line.p_name,
|
|
line.cost,
|
|
line.image,
|
|
line.image2,
|
|
line.mlbclub,
|
|
line.franchise,
|
|
line.cardset,
|
|
line.rarity,
|
|
line.pos_1,
|
|
line.pos_2,
|
|
line.pos_3,
|
|
line.pos_4,
|
|
line.pos_5,
|
|
line.pos_6,
|
|
line.pos_7,
|
|
line.pos_8,
|
|
line.headshot,
|
|
line.vanity_card,
|
|
line.strat_code,
|
|
line.bbref_id,
|
|
line.description,
|
|
line.cardset.for_purchase,
|
|
line.cardset.ranked_legal,
|
|
# line.description, line.cardset.in_packs, line.quantity
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": len(final_players), "players": []}
|
|
for x in final_players:
|
|
this_record = model_to_dict(x, recurse=not flat)
|
|
|
|
if inc_dex:
|
|
this_dex = Paperdex.select().where(Paperdex.player == x)
|
|
this_record["paperdex"] = {"count": this_dex.count(), "paperdex": []}
|
|
for y in this_dex:
|
|
this_record["paperdex"]["paperdex"].append(
|
|
model_to_dict(y, recurse=False)
|
|
)
|
|
|
|
return_val["players"].append(this_record)
|
|
|
|
# return_val['players'].append(model_to_dict(x, recurse=not flat))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/players/random")
|
|
async def v1_players_get_random(
|
|
min_cost: Optional[int] = None,
|
|
max_cost: Optional[int] = None,
|
|
in_packs: Optional[bool] = None,
|
|
min_rarity: Optional[int] = None,
|
|
max_rarity: Optional[int] = None,
|
|
limit: Optional[int] = None,
|
|
pos_include: Optional[str] = None,
|
|
pos_exclude: Optional[str] = None,
|
|
franchise: Optional[str] = None,
|
|
mlbclub: Optional[str] = None,
|
|
cardset_id: list = Query(default=None),
|
|
pos_inc: list = Query(default=None),
|
|
pos_exc: list = Query(default=None),
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_players = (
|
|
Player.select().join(Cardset).switch(Player).join(Rarity).order_by(fn.Random())
|
|
)
|
|
|
|
if min_cost is not None:
|
|
all_players = all_players.where(Player.cost >= min_cost)
|
|
if max_cost is not None:
|
|
all_players = all_players.where(Player.cost <= max_cost)
|
|
if in_packs is not None:
|
|
if in_packs:
|
|
all_players = all_players.where(Player.cardset.in_packs)
|
|
if min_rarity is not None:
|
|
all_players = all_players.where(Player.rarity.value >= min_rarity)
|
|
if max_rarity is not None:
|
|
all_players = all_players.where(Player.rarity.value <= max_rarity)
|
|
if pos_include is not None:
|
|
all_players = all_players.where(
|
|
(fn.lower(Player.pos_1) == pos_include.lower())
|
|
| (fn.lower(Player.pos_2) == pos_include.lower())
|
|
| (fn.lower(Player.pos_3) == pos_include.lower())
|
|
| (fn.lower(Player.pos_4) == pos_include.lower())
|
|
| (fn.lower(Player.pos_5) == pos_include.lower())
|
|
| (fn.lower(Player.pos_6) == pos_include.lower())
|
|
| (fn.lower(Player.pos_7) == pos_include.lower())
|
|
| (fn.lower(Player.pos_8) == pos_include.lower())
|
|
)
|
|
if franchise is not None:
|
|
all_players = all_players.where(fn.Lower(Player.franchise) == franchise.lower())
|
|
if mlbclub is not None:
|
|
all_players = all_players.where(fn.Lower(Player.mlbclub) == mlbclub.lower())
|
|
if cardset_id is not None:
|
|
all_players = all_players.where(Player.cardset_id << cardset_id)
|
|
if pos_inc is not None:
|
|
p_list = [x.upper() for x in pos_inc]
|
|
all_players = all_players.where(
|
|
(Player.pos_1 << p_list)
|
|
| (Player.pos_2 << p_list)
|
|
| (Player.pos_3 << p_list)
|
|
| (Player.pos_4 << p_list)
|
|
| (Player.pos_5 << p_list)
|
|
| (Player.pos_6 << p_list)
|
|
| (Player.pos_7 << p_list)
|
|
| (Player.pos_8 << p_list)
|
|
)
|
|
# if pos_exc is not None:
|
|
# p_list = [x.upper() for x in pos_exc]
|
|
# logging.info(f'starting query: {all_players}\n\np_list: {p_list}\n\n')
|
|
# all_players = all_players.where(
|
|
# Player.pos_1.not_in(p_list) & Player.pos_2.not_in(p_list) & Player.pos_3.not_in(p_list) &
|
|
# Player.pos_4.not_in(p_list) & Player.pos_5.not_in(p_list) & Player.pos_6.not_in(p_list) &
|
|
# Player.pos_7.not_in(p_list) & Player.pos_8.not_in(p_list)
|
|
# )
|
|
# logging.info(f'post pos query: {all_players}')
|
|
|
|
if pos_exclude is not None and pos_exc is None:
|
|
final_players = [x for x in all_players if pos_exclude not in x.get_all_pos()]
|
|
elif pos_exc is not None and pos_exclude is None:
|
|
final_players = []
|
|
p_list = [x.upper() for x in pos_exc]
|
|
for x in all_players:
|
|
if limit is not None and len(final_players) >= limit:
|
|
break
|
|
if not set(p_list).intersection(x.get_all_pos()):
|
|
final_players.append(x)
|
|
else:
|
|
final_players = all_players
|
|
|
|
if limit is not None:
|
|
final_players = final_players[:limit]
|
|
|
|
# if len(final_players) == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'No players found')
|
|
|
|
if csv:
|
|
data_list = [
|
|
[
|
|
"id",
|
|
"name",
|
|
"cost",
|
|
"image",
|
|
"image2",
|
|
"mlbclub",
|
|
"franchise",
|
|
"cardset",
|
|
"rarity",
|
|
"pos_1",
|
|
"pos_2",
|
|
"pos_3",
|
|
"pos_4",
|
|
"pos_5",
|
|
"pos_6",
|
|
"pos_7",
|
|
"pos_8",
|
|
"headshot",
|
|
"vanity_card",
|
|
"strat_code",
|
|
"bbref_id",
|
|
"description",
|
|
]
|
|
]
|
|
for line in final_players:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.p_name,
|
|
line.cost,
|
|
line.image,
|
|
line.image2,
|
|
line.mlbclub,
|
|
line.franchise,
|
|
line.cardset.name,
|
|
line.rarity.name,
|
|
line.pos_1,
|
|
line.pos_2,
|
|
line.pos_3,
|
|
line.pos_4,
|
|
line.pos_5,
|
|
line.pos_6,
|
|
line.pos_7,
|
|
line.pos_8,
|
|
line.headshot,
|
|
line.vanity_card,
|
|
line.strat_code,
|
|
line.bbref_id,
|
|
line.description,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": len(final_players), "players": []}
|
|
for x in final_players:
|
|
this_record = model_to_dict(x)
|
|
|
|
this_dex = Paperdex.select().where(Paperdex.player == x)
|
|
this_record["paperdex"] = {"count": this_dex.count(), "paperdex": []}
|
|
for y in this_dex:
|
|
this_record["paperdex"]["paperdex"].append(
|
|
model_to_dict(y, recurse=False)
|
|
)
|
|
|
|
return_val["players"].append(this_record)
|
|
# return_val['players'].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/players/{player_id}")
|
|
async def v1_players_get_one(player_id, csv: Optional[bool] = False):
|
|
try:
|
|
this_player = Player.get_by_id(player_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No player found with id {player_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [
|
|
[
|
|
"id",
|
|
"name",
|
|
"cost",
|
|
"image",
|
|
"image2",
|
|
"mlbclub",
|
|
"franchise",
|
|
"cardset",
|
|
"rarity",
|
|
"pos_1",
|
|
"pos_2",
|
|
"pos_3",
|
|
"pos_4",
|
|
"pos_5",
|
|
"pos_6",
|
|
"pos_7",
|
|
"pos_8",
|
|
"headshot",
|
|
"vanity_card",
|
|
"strat_code",
|
|
"bbref_id",
|
|
"description",
|
|
]
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
data_list.append(
|
|
[
|
|
this_player.id,
|
|
this_player.p_name,
|
|
this_player.cost,
|
|
this_player.image,
|
|
this_player.image2,
|
|
this_player.mlbclub,
|
|
this_player.franchise,
|
|
this_player.cardset.name,
|
|
this_player.rarity.name,
|
|
this_player.pos_1,
|
|
this_player.pos_2,
|
|
this_player.pos_3,
|
|
this_player.pos_4,
|
|
this_player.pos_5,
|
|
this_player.pos_6,
|
|
this_player.pos_7,
|
|
this_player.pos_8,
|
|
this_player.headshot,
|
|
this_player.vanity_card,
|
|
this_player.strat_code,
|
|
this_player.bbref_id,
|
|
this_player.description,
|
|
]
|
|
)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
else:
|
|
return_val = model_to_dict(this_player)
|
|
this_dex = Paperdex.select().where(Paperdex.player == this_player)
|
|
return_val["paperdex"] = {"count": this_dex.count(), "paperdex": []}
|
|
for x in this_dex:
|
|
return_val["paperdex"]["paperdex"].append(model_to_dict(x, recurse=False))
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.patch("/api/v1/players/{player_id}")
|
|
async def v1_players_patch(
|
|
player_id,
|
|
name: Optional[str] = None,
|
|
image: Optional[str] = None,
|
|
image2: Optional[str] = None,
|
|
mlbclub: Optional[str] = None,
|
|
franchise: Optional[str] = None,
|
|
cardset_id: Optional[int] = None,
|
|
rarity_id: Optional[int] = None,
|
|
pos_1: Optional[str] = None,
|
|
pos_2: Optional[str] = None,
|
|
pos_3: Optional[str] = None,
|
|
pos_4: Optional[str] = None,
|
|
pos_5: Optional[str] = None,
|
|
pos_6: Optional[str] = None,
|
|
pos_7: Optional[str] = None,
|
|
pos_8: Optional[str] = None,
|
|
headshot: Optional[str] = None,
|
|
vanity_card: Optional[str] = None,
|
|
strat_code: Optional[str] = None,
|
|
bbref_id: Optional[str] = None,
|
|
description: Optional[str] = None,
|
|
cost: Optional[int] = None,
|
|
fangr_id: Optional[str] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch players. This event has been logged.",
|
|
)
|
|
|
|
try:
|
|
this_player = Player.get_by_id(player_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No player found with id {player_id}"
|
|
)
|
|
|
|
if cost is not None:
|
|
this_player.cost = cost
|
|
if name is not None:
|
|
this_player.p_name = name
|
|
if image is not None:
|
|
this_player.image = image
|
|
if image2 is not None:
|
|
if image2.lower() == "false":
|
|
this_player.image2 = None
|
|
else:
|
|
this_player.image2 = image2
|
|
if mlbclub is not None:
|
|
this_player.mlbclub = mlbclub
|
|
if franchise is not None:
|
|
this_player.franchise = franchise
|
|
if cardset_id is not None:
|
|
try:
|
|
this_cardset = Cardset.get_by_id(cardset_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No cardset found with id {cardset_id}"
|
|
)
|
|
this_player.cardset = this_cardset
|
|
if rarity_id is not None:
|
|
try:
|
|
this_rarity = Rarity.get_by_id(rarity_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No rarity found with id {rarity_id}"
|
|
)
|
|
this_player.rarity = this_rarity
|
|
if pos_1 is not None:
|
|
if pos_1 == "False":
|
|
this_player.pos_1 = None
|
|
else:
|
|
this_player.pos_1 = pos_1
|
|
if pos_2 is not None:
|
|
if pos_2 == "False":
|
|
this_player.pos_2 = None
|
|
else:
|
|
this_player.pos_2 = pos_2
|
|
if pos_3 is not None:
|
|
if pos_3 == "False":
|
|
this_player.pos_3 = None
|
|
else:
|
|
this_player.pos_3 = pos_3
|
|
if pos_4 is not None:
|
|
if pos_4 == "False":
|
|
this_player.pos_4 = None
|
|
else:
|
|
this_player.pos_4 = pos_4
|
|
if pos_5 is not None:
|
|
if pos_5 == "False":
|
|
this_player.pos_5 = None
|
|
else:
|
|
this_player.pos_5 = pos_5
|
|
if pos_6 is not None:
|
|
if pos_6 == "False":
|
|
this_player.pos_6 = None
|
|
else:
|
|
this_player.pos_6 = pos_6
|
|
if pos_7 is not None:
|
|
if pos_7 == "False":
|
|
this_player.pos_7 = None
|
|
else:
|
|
this_player.pos_7 = pos_7
|
|
if pos_8 is not None:
|
|
if pos_8 == "False":
|
|
this_player.pos_8 = None
|
|
else:
|
|
this_player.pos_8 = pos_8
|
|
if headshot is not None:
|
|
this_player.headshot = headshot
|
|
if vanity_card is not None:
|
|
this_player.vanity_card = vanity_card
|
|
if strat_code is not None:
|
|
this_player.strat_code = strat_code
|
|
if bbref_id is not None:
|
|
this_player.bbref_id = bbref_id
|
|
if fangr_id is not None:
|
|
this_player.fangr_id = fangr_id
|
|
if description is not None:
|
|
this_player.description = description
|
|
|
|
if this_player.save() == 1:
|
|
return_val = model_to_dict(this_player)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.put("/api/v1/players")
|
|
async def v1_players_put(players: PlayerModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post players. This event has been logged.",
|
|
)
|
|
|
|
new_players = []
|
|
for x in players.players:
|
|
# this_player = Player(
|
|
# player_id=x.player_id,
|
|
# p_name=x.p_name,
|
|
# cost=x.cost,
|
|
# image=x.image,
|
|
# image2=x.image2,
|
|
# mlbclub=x.mlbclub,
|
|
# franchise=x.franchise,
|
|
# cardset_id=x.cardset_id,
|
|
# rarity_id=x.rarity_id,
|
|
# set_num=x.set_num,
|
|
# pos_1=x.pos_1,
|
|
# pos_2=x.pos_2,
|
|
# pos_3=x.pos_3,
|
|
# pos_4=x.pos_4,
|
|
# pos_5=x.pos_5,
|
|
# pos_6=x.pos_6,
|
|
# pos_7=x.pos_7,
|
|
# pos_8=x.pos_8,
|
|
# headshot=x.headshot,
|
|
# vanity_card=x.vanity_card,
|
|
# strat_code=x.strat_code,
|
|
# fangr_id=x.fangr_id,
|
|
# bbref_id=x.bbref_id,
|
|
# description=x.description
|
|
# )
|
|
# new_players.append(this_player)
|
|
new_players.append(
|
|
{
|
|
"player_id": x.player_id,
|
|
"p_name": x.p_name,
|
|
"cost": x.cost,
|
|
"image": x.image,
|
|
"image2": x.image2,
|
|
"mlbclub": x.mlbclub.title(),
|
|
"franchise": normalize_franchise(x.franchise),
|
|
"cardset_id": x.cardset_id,
|
|
"rarity_id": x.rarity_id,
|
|
"set_num": x.set_num,
|
|
"pos_1": x.pos_1,
|
|
"pos_2": x.pos_2,
|
|
"pos_3": x.pos_3,
|
|
"pos_4": x.pos_4,
|
|
"pos_5": x.pos_5,
|
|
"pos_6": x.pos_6,
|
|
"pos_7": x.pos_7,
|
|
"pos_8": x.pos_8,
|
|
"headshot": x.headshot,
|
|
"vanity_card": x.vanity_card,
|
|
"strat_code": x.strat_code,
|
|
"fangr_id": x.fangr_id,
|
|
"bbref_id": x.bbref_id,
|
|
"description": x.description,
|
|
}
|
|
)
|
|
|
|
logging.info(f"new_players: {new_players}")
|
|
|
|
with db.atomic():
|
|
# Use PostgreSQL-compatible upsert helper
|
|
upsert_players(new_players, batch_size=15)
|
|
db.close()
|
|
|
|
# sheets.update_all_players(SHEETS_AUTH)
|
|
raise HTTPException(
|
|
status_code=200, detail=f"{len(new_players)} players have been added"
|
|
)
|
|
|
|
|
|
# @app.put('/api/v1/players')
|
|
# async def v1_players_put(players: PlayerModel, token: str = Depends(oauth2_scheme)):
|
|
# if not valid_token(token):
|
|
# logging.warning(f'Bad Token: {token}')
|
|
# db.close()
|
|
# raise HTTPException(
|
|
# status_code=401,
|
|
# detail='You are not authorized to post players. This event has been logged.'
|
|
# )
|
|
#
|
|
# new_players = []
|
|
# for x in players.players:
|
|
# try:
|
|
# this_player = Player.get_by_id(x.player_id)
|
|
# except Exception as e:
|
|
# new_players.append({
|
|
# 'player_id': x.player_id,
|
|
# 'p_name': x.p_name,
|
|
# 'cost': x.cost,
|
|
# 'image': x.image,
|
|
# 'image2': x.image2,
|
|
# 'mlbclub': x.mlbclub.title(),
|
|
# 'franchise': x.franchise.title(),
|
|
# 'cardset_id': x.cardset_id,
|
|
# 'rarity_id': x.rarity_id,
|
|
# 'set_num': x.set_num,
|
|
# 'pos_1': x.pos_1,
|
|
# 'pos_2': x.pos_2,
|
|
# 'pos_3': x.pos_3,
|
|
# 'pos_4': x.pos_4,
|
|
# 'pos_5': x.pos_5,
|
|
# 'pos_6': x.pos_6,
|
|
# 'pos_7': x.pos_7,
|
|
# 'pos_8': x.pos_8,
|
|
# 'headshot': x.headshot,
|
|
# 'vanity_card': x.vanity_card,
|
|
# 'strat_code': x.strat_code,
|
|
# 'fangr_id': x.fangr_id,
|
|
# 'bbref_id': x.bbref_id,
|
|
# 'description': x.description
|
|
# })
|
|
# finally:
|
|
#
|
|
|
|
|
|
# @app.patch('/api/v1/players')
|
|
# async def v1_players_put(players: PlayerModel, token: str = Depends(oauth2_scheme)):
|
|
# if not valid_token(token):
|
|
# logging.warning(f'Bad Token: {token}')
|
|
# db.close()
|
|
# raise HTTPException(
|
|
# status_code=401,
|
|
# detail='You are not authorized to post players. This event has been logged.'
|
|
# )
|
|
#
|
|
# new_players = []
|
|
# for x in players.players:
|
|
|
|
|
|
@app.delete("/api/v1/players/{player_id}")
|
|
async def v1_players_delete(player_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete players. This event has been logged.",
|
|
)
|
|
|
|
try:
|
|
this_player = Player.get_by_id(player_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No player found with id {player_id}"
|
|
)
|
|
|
|
count = this_player.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Player {player_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=500, detail=f"Player {player_id} was not deleted"
|
|
)
|
|
|
|
|
|
"""
|
|
PACKTYPE ENDPOINTS
|
|
"""
|
|
|
|
|
|
class PacktypeModel(pydantic.BaseModel):
|
|
name: str
|
|
card_count: int
|
|
description: str
|
|
cost: int
|
|
available: Optional[bool] = True
|
|
|
|
|
|
@app.get("/api/v1/packtypes")
|
|
async def v1_packtypes_get(
|
|
name: Optional[str] = None,
|
|
card_count: Optional[int] = None,
|
|
in_desc: Optional[str] = None,
|
|
available: Optional[bool] = None,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_packtypes = PackType.select()
|
|
|
|
if all_packtypes.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"There are no packtypes to filter")
|
|
|
|
if name is not None:
|
|
all_packtypes = all_packtypes.where(fn.Lower(PackType.name) == name.lower())
|
|
if card_count is not None:
|
|
all_packtypes = all_packtypes.where(PackType.card_count == card_count)
|
|
if in_desc is not None:
|
|
all_packtypes = all_packtypes.where(
|
|
fn.Lower(PackType.description).contains(in_desc.lower())
|
|
)
|
|
if available is not None:
|
|
all_packtypes = all_packtypes.where(PackType.available == available)
|
|
|
|
# if all_packtypes.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'No packtypes found')
|
|
|
|
if csv:
|
|
data_list = [["id", "name", "card_count", "description"]]
|
|
for line in all_packtypes:
|
|
data_list.append([line.id, line.name, line.card_count, line.description])
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_packtypes.count(), "packtypes": []}
|
|
for x in all_packtypes:
|
|
return_val["packtypes"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/packtypes/{packtype_id}")
|
|
async def v1_packtypes_get_one(packtype_id, csv: Optional[bool] = False):
|
|
try:
|
|
this_packtype = PackType.get_by_id(packtype_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No packtype found with id {packtype_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "name", "card_count", "description"],
|
|
[
|
|
this_packtype.id,
|
|
this_packtype.name,
|
|
this_packtype.card_count,
|
|
this_packtype.description,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_packtype)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/packtypes")
|
|
async def v1_packtypes_post(
|
|
packtype: PacktypeModel, token: str = Depends(oauth2_scheme)
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post packtypes. This event has been logged.",
|
|
)
|
|
|
|
dupe_packtype = PackType.get_or_none(PackType.name == packtype.name)
|
|
if dupe_packtype:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=400, detail=f"There is already a packtype using {packtype.name}"
|
|
)
|
|
|
|
this_packtype = PackType(
|
|
name=packtype.name,
|
|
card_count=packtype.card_count,
|
|
description=packtype.description,
|
|
cost=packtype.cost,
|
|
available=packtype.available,
|
|
)
|
|
|
|
saved = this_packtype.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_packtype)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/packtypes/{packtype_id}")
|
|
async def v1_packtypes_patch(
|
|
packtype_id,
|
|
name: Optional[str] = None,
|
|
card_count: Optional[int] = None,
|
|
description: Optional[str] = None,
|
|
cost: Optional[int] = None,
|
|
available: Optional[bool] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch packtypes. This event has been logged.",
|
|
)
|
|
try:
|
|
this_packtype = PackType.get_by_id(packtype_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No packtype found with id {packtype_id}"
|
|
)
|
|
|
|
if name is not None:
|
|
this_packtype.name = name
|
|
if card_count is not None:
|
|
this_packtype.card_count = card_count
|
|
if description is not None:
|
|
this_packtype.description = description
|
|
if cost is not None:
|
|
this_packtype.cost = cost
|
|
if available is not None:
|
|
this_packtype.available = available
|
|
|
|
if this_packtype.save() == 1:
|
|
return_val = model_to_dict(this_packtype)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/packtypes/{packtype_id}")
|
|
async def v1_packtypes_delete(packtype_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete packtypes. This event has been logged.",
|
|
)
|
|
try:
|
|
this_packtype = PackType.get_by_id(packtype_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No packtype found with id {packtype_id}"
|
|
)
|
|
|
|
count = this_packtype.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Packtype {packtype_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=500, detail=f"Packtype {packtype_id} was not deleted"
|
|
)
|
|
|
|
|
|
"""
|
|
PACK ENDPOINTS
|
|
"""
|
|
|
|
|
|
class PackPydantic(pydantic.BaseModel):
|
|
team_id: int
|
|
pack_type_id: int
|
|
pack_team_id: Optional[int] = None
|
|
pack_cardset_id: Optional[int] = None
|
|
open_time: Optional[str] = None
|
|
|
|
|
|
class PackModel(pydantic.BaseModel):
|
|
packs: List[PackPydantic]
|
|
|
|
|
|
@app.get("/api/v1/packs")
|
|
async def v1_packs_get(
|
|
team_id: Optional[int] = None,
|
|
pack_type_id: Optional[int] = None,
|
|
opened: Optional[bool] = None,
|
|
limit: Optional[int] = None,
|
|
new_to_old: Optional[bool] = None,
|
|
pack_team_id: Optional[int] = None,
|
|
pack_cardset_id: Optional[int] = None,
|
|
exact_match: Optional[bool] = False,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_packs = Pack.select()
|
|
|
|
if all_packs.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"There are no packs to filter")
|
|
|
|
if team_id is not None:
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No team found with id {team_id}"
|
|
)
|
|
all_packs = all_packs.where(Pack.team == this_team)
|
|
if pack_type_id is not None:
|
|
try:
|
|
this_pack_type = PackType.get_by_id(pack_type_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No pack type found with id {pack_type_id}"
|
|
)
|
|
all_packs = all_packs.where(Pack.pack_type == this_pack_type)
|
|
|
|
if pack_team_id is not None:
|
|
try:
|
|
this_pack_team = Team.get_by_id(pack_team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No team found with id {pack_team_id}"
|
|
)
|
|
all_packs = all_packs.where(Pack.pack_team == this_pack_team)
|
|
elif exact_match:
|
|
all_packs = all_packs.where(Pack.pack_team == None)
|
|
|
|
if pack_cardset_id is not None:
|
|
try:
|
|
this_pack_cardset = Cardset.get_by_id(pack_cardset_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No cardset found with id {pack_cardset_id}"
|
|
)
|
|
all_packs = all_packs.where(Pack.pack_cardset == this_pack_cardset)
|
|
elif exact_match:
|
|
all_packs = all_packs.where(Pack.pack_cardset == None)
|
|
|
|
if opened is not None:
|
|
all_packs = all_packs.where(Pack.open_time.is_null(not opened))
|
|
if limit is not None:
|
|
all_packs = all_packs.limit(limit)
|
|
if new_to_old is not None:
|
|
all_packs = all_packs.order_by(-Pack.id)
|
|
|
|
# if all_packs.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'No packs found')
|
|
|
|
if csv:
|
|
data_list = [["id", "team", "pack_type", "open_time"]]
|
|
for line in all_packs:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.team.abbrev,
|
|
line.pack_type.name,
|
|
datetime.fromtimestamp(line.open_time) if line.open_time else None,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_packs.count(), "packs": []}
|
|
for x in all_packs:
|
|
return_val["packs"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/packs/{pack_id}")
|
|
async def v1_packs_get_one(pack_id, csv: Optional[bool] = False):
|
|
try:
|
|
this_pack = Pack.get_by_id(pack_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No pack found with id {pack_id}")
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "team", "pack_type", "open_time"],
|
|
[
|
|
this_pack.id,
|
|
this_pack.team.abbrev,
|
|
this_pack.pack_type.name,
|
|
datetime.fromtimestamp(this_pack.open_time)
|
|
if this_pack.open_time
|
|
else None,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_pack)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/packs")
|
|
async def v1_packs_post(packs: PackModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post packs. This event has been logged.",
|
|
)
|
|
|
|
new_packs = []
|
|
for x in packs.packs:
|
|
this_player = Pack(
|
|
team_id=x.team_id,
|
|
pack_type_id=x.pack_type_id,
|
|
pack_team_id=x.pack_team_id,
|
|
pack_cardset_id=x.pack_cardset_id,
|
|
open_time=x.open_time if x.open_time != "" else None,
|
|
)
|
|
new_packs.append(this_player)
|
|
|
|
with db.atomic():
|
|
Pack.bulk_create(new_packs, batch_size=15)
|
|
db.close()
|
|
|
|
raise HTTPException(
|
|
status_code=200, detail=f"{len(new_packs)} packs have been added"
|
|
)
|
|
|
|
|
|
@app.post("/api/v1/packs/one")
|
|
async def v1_packs_post_one(pack: PackPydantic, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post packs. This event has been logged.",
|
|
)
|
|
|
|
this_pack = Pack(
|
|
team_id=pack.team_id,
|
|
pack_type_id=pack.pack_type_id,
|
|
pack_team_id=pack.pack_team_id,
|
|
pack_cardset_id=pack.pack_cardset_id,
|
|
open_time=pack.open_time,
|
|
)
|
|
|
|
saved = this_pack.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_pack)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/packs/{pack_id}")
|
|
async def v1_packs_patch(
|
|
pack_id,
|
|
team_id: Optional[int] = None,
|
|
pack_type_id: Optional[int] = None,
|
|
open_time: Optional[int] = None,
|
|
pack_team_id: Optional[int] = None,
|
|
pack_cardset_id: Optional[int] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch packs. This event has been logged.",
|
|
)
|
|
try:
|
|
this_pack = Pack.get_by_id(pack_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No pack found with id {pack_id}")
|
|
|
|
if team_id is not None:
|
|
this_pack.team_id = team_id
|
|
if pack_type_id is not None:
|
|
this_pack.pack_type_id = pack_type_id
|
|
if pack_team_id is not None:
|
|
this_pack.pack_team_id = pack_team_id
|
|
if pack_cardset_id is not None:
|
|
this_pack.pack_cardset_id = pack_cardset_id
|
|
if open_time is not None:
|
|
this_pack.open_time = open_time
|
|
|
|
if this_pack.save() == 1:
|
|
return_val = model_to_dict(this_pack)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/packs/{pack_id}")
|
|
async def v1_packs_delete(pack_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete packs. This event has been logged.",
|
|
)
|
|
try:
|
|
this_pack = Pack.get_by_id(pack_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No packs found with id {pack_id}")
|
|
|
|
count = this_pack.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(status_code=200, detail=f"Pack {pack_id} has been deleted")
|
|
else:
|
|
raise HTTPException(status_code=500, detail=f"Pack {pack_id} was not deleted")
|
|
|
|
|
|
"""
|
|
CARD ENDPOINTS
|
|
"""
|
|
|
|
|
|
class CardPydantic(pydantic.BaseModel):
|
|
player_id: int
|
|
team_id: int
|
|
pack_id: int
|
|
value: Optional[int] = 0
|
|
|
|
|
|
class CardModel(pydantic.BaseModel):
|
|
cards: List[CardPydantic]
|
|
|
|
|
|
@app.get("/api/v1/cards")
|
|
async def v1_cards_get(
|
|
player_id: Optional[int] = None,
|
|
team_id: Optional[int] = None,
|
|
pack_id: Optional[int] = None,
|
|
value: Optional[int] = None,
|
|
min_value: Optional[int] = None,
|
|
max_value: Optional[int] = None,
|
|
order_by: Optional[str] = None,
|
|
limit: Optional[int] = None,
|
|
dupes: Optional[bool] = None,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_cards = Card.select()
|
|
|
|
# if all_cards.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'There are no cards to filter')
|
|
|
|
if team_id is not None:
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No team found with id {team_id}"
|
|
)
|
|
all_cards = all_cards.where(Card.team == this_team)
|
|
if player_id is not None:
|
|
try:
|
|
this_player = Player.get_by_id(player_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No player found with id {player_id}"
|
|
)
|
|
all_cards = all_cards.where(Card.player == this_player)
|
|
if pack_id is not None:
|
|
try:
|
|
this_pack = Pack.get_by_id(pack_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No pack found with id {pack_id}"
|
|
)
|
|
all_cards = all_cards.where(Card.pack == this_pack)
|
|
if value is not None:
|
|
all_cards = all_cards.where(Card.value == value)
|
|
if min_value is not None:
|
|
all_cards = all_cards.where(Card.value >= min_value)
|
|
if max_value is not None:
|
|
all_cards = all_cards.where(Card.value <= max_value)
|
|
if order_by is not None:
|
|
if order_by.lower() == "new":
|
|
all_cards = all_cards.order_by(-Card.id)
|
|
if limit is not None:
|
|
all_cards = all_cards.limit(limit)
|
|
if dupes:
|
|
if team_id is None:
|
|
raise HTTPException(
|
|
status_code=400, detail="Dupe checking must include a team_id"
|
|
)
|
|
logging.info(f"dupe check")
|
|
p_query = Card.select(Card.player).where(Card.team_id == team_id)
|
|
seen = set()
|
|
dupes = []
|
|
for x in p_query:
|
|
if x.player.player_id in seen:
|
|
dupes.append(x.player_id)
|
|
else:
|
|
seen.add(x.player_id)
|
|
all_cards = all_cards.where(Card.player_id << dupes)
|
|
|
|
# if all_cards.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'No cards found')
|
|
|
|
if csv:
|
|
data_list = [["id", "player", "cardset", "rarity", "team", "pack", "value"]]
|
|
for line in all_cards:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.player.p_name,
|
|
line.player.cardset,
|
|
line.player.rarity,
|
|
line.team.abbrev,
|
|
line.pack,
|
|
line.value,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_cards.count(), "cards": []}
|
|
for x in all_cards:
|
|
this_record = model_to_dict(x)
|
|
logging.debug(f"this_record: {this_record}")
|
|
|
|
this_dex = Paperdex.select().where(Paperdex.player == x)
|
|
this_record["player"]["paperdex"] = {
|
|
"count": this_dex.count(),
|
|
"paperdex": [],
|
|
}
|
|
for y in this_dex:
|
|
this_record["player"]["paperdex"]["paperdex"].append(
|
|
model_to_dict(y, recurse=False)
|
|
)
|
|
|
|
return_val["cards"].append(this_record)
|
|
|
|
# return_val['cards'].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/cards/{card_id}")
|
|
async def v1_cards_get_one(card_id, csv: Optional[bool] = False):
|
|
try:
|
|
this_card = Card.get_by_id(card_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No card found with id {card_id}")
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "player", "team", "pack", "value", "roster1", "roster2", "roster3"],
|
|
[
|
|
this_card.id,
|
|
this_card.player,
|
|
this_card.team.abbrev,
|
|
this_card.pack,
|
|
this_card.value,
|
|
this_card.roster1.name,
|
|
this_card.roster2.name,
|
|
this_card.roster3.name,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_card)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/cards")
|
|
async def v1_cards_post(cards: CardModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post cards. This event has been logged.",
|
|
)
|
|
last_card = Card.select(Card.id).order_by(-Card.id).limit(1)
|
|
lc_id = last_card[0].id
|
|
|
|
new_cards = []
|
|
player_ids = []
|
|
inc_dex = True
|
|
this_team = Team.get_by_id(cards.cards[0].team_id)
|
|
if this_team.is_ai or "Gauntlet" in this_team.abbrev:
|
|
inc_dex = False
|
|
|
|
# new_dex = []
|
|
# now = int(datetime.timestamp(datetime.now()) * 1000)
|
|
for x in cards.cards:
|
|
this_card = Card(
|
|
player_id=x.player_id, team_id=x.team_id, pack_id=x.pack_id, value=x.value
|
|
)
|
|
if inc_dex:
|
|
Paperdex.get_or_create(team_id=x.team_id, player_id=x.player_id)
|
|
player_ids.append(x.player_id)
|
|
new_cards.append(this_card)
|
|
|
|
with db.atomic():
|
|
Card.bulk_create(new_cards, batch_size=15)
|
|
cost_query = Player.update(cost=Player.cost + 1).where(
|
|
Player.player_id << player_ids
|
|
)
|
|
cost_query.execute()
|
|
# sheets.post_new_cards(SHEETS_AUTH, lc_id)
|
|
db.close()
|
|
|
|
raise HTTPException(
|
|
status_code=200, detail=f"{len(new_cards)} cards have been added"
|
|
)
|
|
|
|
|
|
@app.post("/api/v1/cards/ai-update")
|
|
async def v1_cards_ai_update(token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to update AI cards. This event has been logged.",
|
|
)
|
|
|
|
sheets.send_ai_cards(SHEETS_AUTH)
|
|
raise HTTPException(status_code=200, detail=f"Just sent AI cards to sheets")
|
|
|
|
|
|
@app.post("/api/v1/cards/legal-check/{rarity_name}")
|
|
async def v1_cards_legal_check(
|
|
rarity_name: str,
|
|
card_id: list = Query(default=None),
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(status_code=401, detail="Unauthorized")
|
|
if rarity_name not in ["ranked"]:
|
|
return f"Rarity name {rarity_name} not a valid check"
|
|
|
|
bad_cards = []
|
|
all_cards = Card.select().where(Card.id << card_id)
|
|
|
|
for x in all_cards:
|
|
if x.player.cardset_id not in [3, 4, 9, 10]:
|
|
bad_cards.append(x.player.description)
|
|
|
|
return {"count": len(bad_cards), "bad_cards": bad_cards}
|
|
|
|
|
|
@app.post("/api/v1/cards/post-update/{starting_id}")
|
|
async def v1_cards_post_update(starting_id: int, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to update card lists. This event has been logged.",
|
|
)
|
|
|
|
# sheets.post_new_cards(SHEETS_AUTH, starting_id)
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=200,
|
|
detail=f"Just sent cards to sheets starting at ID {starting_id}",
|
|
)
|
|
|
|
|
|
@app.post("/api/v1/cards/post-delete")
|
|
async def v1_cards_post_delete(del_ids: str, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete card lists. This event has been logged.",
|
|
)
|
|
|
|
logging.info(f"del_ids: {del_ids} / type: {type(del_ids)}")
|
|
# sheets.post_deletion(SHEETS_AUTH, del_ids.split(','))
|
|
|
|
|
|
@app.post("/api/v1/cards/wipe-team/{team_id}")
|
|
async def v1_cards_wipe_team(team_id: int, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to wipe teams. This event has been logged.",
|
|
)
|
|
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception as e:
|
|
logging.error(f"/cards/wipe-team/{team_id} - could not find team")
|
|
raise HTTPException(status_code=404, detail=f"Team {team_id} not found")
|
|
|
|
t_query = Card.update(team=None).where(Card.team == this_team).execute()
|
|
db.close()
|
|
return f"Wiped {t_query} cards"
|
|
|
|
|
|
# @app.get('/api/v1/cards/{card_id}/sell')
|
|
# async def v1_cards_sell(card_id, ts: int = None):
|
|
# try:
|
|
# this_card = Card.get_by_id(card_id)
|
|
# except Exception:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'No card found with id {card_id}')
|
|
#
|
|
# this_team = this_card.team
|
|
# if ts != this_team.team_hash():
|
|
# logging.warning(f'Bad Team Secret: {ts} ({this_team.team_hash()})')
|
|
# db.close()
|
|
# raise HTTPException(
|
|
# status_code=401,
|
|
# detail=f'You are not authorized to sell {this_team.abbrev} cards. This event has been logged.'
|
|
# )
|
|
#
|
|
# this_player = this_card.player
|
|
# orig_price = this_player.cost
|
|
# sell_price = round(this_player.cost * .5)
|
|
#
|
|
# # credit selling team's wallet
|
|
# if this_team.wallet is None:
|
|
# this_team.wallet = sell_price
|
|
# else:
|
|
# this_team.wallet += sell_price
|
|
# this_team.save()
|
|
#
|
|
# # decrease price of player
|
|
# this_player.change_on_sell()
|
|
# this_card.delete_instance()
|
|
#
|
|
# # post a notification
|
|
# new_notif = Notification(
|
|
# created=int_timestamp(datetime.now()),
|
|
# title=f'Price Change',
|
|
# desc='Modified by buying and selling',
|
|
# field_name=f'{this_player.p_name}',
|
|
# message=f'From {orig_price}₼ to **{this_player.cost}**₼',
|
|
# about=f'Player-{this_player.id}'
|
|
# )
|
|
# new_notif.save()
|
|
#
|
|
# raise HTTPException(status_code=200, detail=f'Card {card_id} has been sold for {sell_price} bucks')
|
|
|
|
|
|
@app.patch("/api/v1/cards/{card_id}")
|
|
async def v1_cards_patch(
|
|
card_id,
|
|
player_id: Optional[int] = None,
|
|
team_id: Optional[int] = None,
|
|
pack_id: Optional[int] = None,
|
|
value: Optional[int] = None,
|
|
roster1_id: Optional[int] = None,
|
|
roster2_id: Optional[int] = None,
|
|
roster3_id: Optional[int] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch cards. This event has been logged.",
|
|
)
|
|
try:
|
|
this_card = Card.get_by_id(card_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No card found with id {card_id}")
|
|
|
|
if player_id is not None:
|
|
this_card.player_id = player_id
|
|
if team_id is not None:
|
|
if team_id == 0:
|
|
this_card.team_id = None
|
|
else:
|
|
this_card.team_id = team_id
|
|
if pack_id is not None:
|
|
this_card.pack_id = pack_id
|
|
if value is not None:
|
|
this_card.value = value
|
|
if roster1_id is not None:
|
|
this_card.roster1_id = roster1_id
|
|
if roster2_id is not None:
|
|
this_card.roster2_id = roster2_id
|
|
if roster3_id is not None:
|
|
this_card.roster3_id = roster3_id
|
|
|
|
if this_card.save() == 1:
|
|
return_val = model_to_dict(this_card)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that rarity",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/cards/{card_id}")
|
|
async def v1_cards_delete(card_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete packs. This event has been logged.",
|
|
)
|
|
try:
|
|
this_card = Card.get_by_id(card_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No cards found with id {card_id}")
|
|
|
|
count = this_card.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(status_code=200, detail=f"Card {card_id} has been deleted")
|
|
else:
|
|
raise HTTPException(status_code=500, detail=f"Card {card_id} was not deleted")
|
|
|
|
|
|
"""
|
|
EVENTS ENDPOINTS
|
|
"""
|
|
|
|
|
|
class EventModel(pydantic.BaseModel):
|
|
name: str
|
|
short_desc: str
|
|
long_desc: str
|
|
url: Optional[str] = None
|
|
thumbnail: Optional[str] = None
|
|
active: Optional[bool] = False
|
|
|
|
|
|
@app.get("/api/v1/events")
|
|
async def v1_events_get(
|
|
name: Optional[str] = None,
|
|
in_desc: Optional[str] = None,
|
|
active: Optional[bool] = None,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_events = Event.select()
|
|
|
|
if name is not None:
|
|
all_events = all_events.where(fn.Lower(Event.name) == name.lower())
|
|
if in_desc is not None:
|
|
all_events = all_events.where(
|
|
(fn.Lower(Event.short_desc).contains(in_desc.lower()))
|
|
| (fn.Lower(Event.long_desc).contains(in_desc.lower()))
|
|
)
|
|
if active is not None:
|
|
all_events = all_events.where(Event.active == active)
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "name", "short_desc", "long_desc", "url", "thumbnail", "active"]
|
|
]
|
|
for line in all_events:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.name,
|
|
line.short_desc,
|
|
line.long_desc,
|
|
line.url,
|
|
line.thumbnail,
|
|
line.active,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_events.count(), "events": []}
|
|
for x in all_events:
|
|
return_val["events"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/events/{event_id}")
|
|
async def v1_events_get_one(event_id, csv: Optional[bool] = False):
|
|
try:
|
|
this_event = Event.get_by_id(event_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No event found with id {event_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "name", "short_desc", "long_desc", "url", "thumbnail", "active"],
|
|
[
|
|
this_event.id,
|
|
this_event.name,
|
|
this_event.short_desc,
|
|
this_event.long_desc,
|
|
this_event.url,
|
|
this_event.thumbnail,
|
|
this_event.active,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_event)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/events")
|
|
async def v1_events_post(event: EventModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post events. This event has been logged.",
|
|
)
|
|
|
|
dupe_event = Event.get_or_none(Event.name == event.name)
|
|
if dupe_event:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=400, detail=f"There is already an event using {event.name}"
|
|
)
|
|
|
|
this_event = Event(
|
|
name=event.name,
|
|
short_desc=event.short_desc,
|
|
long_desc=event.long_desc,
|
|
url=event.url,
|
|
thumbnail=event.thumbnail,
|
|
active=event.active,
|
|
)
|
|
|
|
saved = this_event.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_event)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that cardset",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/events/{event_id}")
|
|
async def v1_events_patch(
|
|
event_id,
|
|
name: Optional[str] = None,
|
|
short_desc: Optional[str] = None,
|
|
long_desc: Optional[str] = None,
|
|
url: Optional[str] = None,
|
|
thumbnail: Optional[str] = None,
|
|
active: Optional[bool] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch events. This event has been logged.",
|
|
)
|
|
try:
|
|
this_event = Event.get_by_id(event_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No event found with id {event_id}"
|
|
)
|
|
|
|
if name is not None:
|
|
this_event.name = name
|
|
if short_desc is not None:
|
|
this_event.short_desc = short_desc
|
|
if long_desc is not None:
|
|
this_event.long_desc = long_desc
|
|
if url is not None:
|
|
this_event.url = url
|
|
if thumbnail is not None:
|
|
this_event.thumbnail = thumbnail
|
|
if active is not None:
|
|
this_event.active = active
|
|
|
|
if this_event.save() == 1:
|
|
return_val = model_to_dict(this_event)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that event",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/events/{event_id}")
|
|
async def v1_events_delete(event_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete events. This event has been logged.",
|
|
)
|
|
try:
|
|
this_event = Event.get_by_id(event_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No event found with id {event_id}"
|
|
)
|
|
|
|
count = this_event.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Event {event_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(status_code=500, detail=f"Event {event_id} was not deleted")
|
|
|
|
|
|
"""
|
|
ROSTERS ENDPOINTS
|
|
"""
|
|
|
|
|
|
class RosterModel(pydantic.BaseModel):
|
|
team_id: int
|
|
name: Optional[str] = "My Roster"
|
|
roster_num: int
|
|
card_ids: list
|
|
|
|
|
|
@app.get("/api/v1/rosters")
|
|
async def v1_rosters_get(team_id: Optional[int] = None, csv: Optional[bool] = None):
|
|
all_rosters = Roster.select()
|
|
|
|
# if all_rosters.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'There are no rosters to filter')
|
|
|
|
if team_id:
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
all_rosters = all_rosters.where(Roster.team == this_team)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No team found with id {team_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [["id", "roster", "team_id", "team_abbrev"]]
|
|
for line in all_rosters:
|
|
data_list.append([line.id, line.name, line.team, line.team.abbrev])
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_rosters.count(), "rosters": []}
|
|
for x in all_rosters:
|
|
return_val["rosters"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/rosters/{roster_id}")
|
|
async def v1_rosters_get_one(roster_id, csv: Optional[bool] = None):
|
|
try:
|
|
this_roster = Roster.get_by_id(roster_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No roster found with id {roster_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "roster", "team_id", "team_abbrev"],
|
|
[
|
|
this_roster.id,
|
|
this_roster.name,
|
|
this_roster.team,
|
|
this_roster.team.abbrev,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_roster)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/rosters")
|
|
async def v1_rosters_post(roster: RosterModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post rosters. This event has been logged.",
|
|
)
|
|
|
|
c_query = Card.select().where(Card.id << roster.card_ids)
|
|
logging.debug(f"c_query: {c_query}")
|
|
for card in c_query:
|
|
if card.team_id != roster.team_id:
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail=f"Card ID {card.id} ({card.player.rarity.name} {card.player.p_name}) belongs to "
|
|
f"{card.team.abbrev} and cannot be added to your roster.",
|
|
)
|
|
|
|
r_query = Roster.delete().where(
|
|
Roster.team_id == roster.team_id, Roster.roster_num == roster.roster_num
|
|
)
|
|
logging.debug(f"r_query: {r_query}")
|
|
r_query.execute()
|
|
|
|
this_roster = Roster(
|
|
team_id=roster.team_id,
|
|
name=roster.name,
|
|
roster_num=roster.roster_num,
|
|
card_1_id=roster.card_ids[0],
|
|
card_2_id=roster.card_ids[1],
|
|
card_3_id=roster.card_ids[2],
|
|
card_4_id=roster.card_ids[3],
|
|
card_5_id=roster.card_ids[4],
|
|
card_6_id=roster.card_ids[5],
|
|
card_7_id=roster.card_ids[6],
|
|
card_8_id=roster.card_ids[7],
|
|
card_9_id=roster.card_ids[8],
|
|
card_10_id=roster.card_ids[9],
|
|
card_11_id=roster.card_ids[10],
|
|
card_12_id=roster.card_ids[11],
|
|
card_13_id=roster.card_ids[12],
|
|
card_14_id=roster.card_ids[13],
|
|
card_15_id=roster.card_ids[14],
|
|
card_16_id=roster.card_ids[15],
|
|
card_17_id=roster.card_ids[16],
|
|
card_18_id=roster.card_ids[17],
|
|
card_19_id=roster.card_ids[18],
|
|
card_20_id=roster.card_ids[19],
|
|
card_21_id=roster.card_ids[20],
|
|
card_22_id=roster.card_ids[21],
|
|
card_23_id=roster.card_ids[22],
|
|
card_24_id=roster.card_ids[23],
|
|
card_25_id=roster.card_ids[24],
|
|
card_26_id=roster.card_ids[25],
|
|
)
|
|
|
|
saved = this_roster.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_roster, recurse=False)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that roster",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/rosters/{roster_id}")
|
|
async def v1_rosters_patch(
|
|
roster_id,
|
|
team_id: Optional[int] = None,
|
|
name: Optional[str] = None,
|
|
roster_num: Optional[int] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch rosters. This event has been logged.",
|
|
)
|
|
try:
|
|
this_roster = Roster.get_by_id(roster_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No roster found with id {roster_id}"
|
|
)
|
|
|
|
if team_id is not None:
|
|
this_roster.team_id = team_id
|
|
if name is not None:
|
|
this_roster.name = name
|
|
if roster_num is not None:
|
|
this_roster.roster_num = roster_num
|
|
|
|
if this_roster.save() == 1:
|
|
return_val = model_to_dict(this_roster)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that event",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/rosters/{roster_id}")
|
|
async def v1_rosters_delete(roster_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete rosters. This event has been logged.",
|
|
)
|
|
try:
|
|
this_roster = Roster.get_by_id(roster_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No roster found with id {roster_id}"
|
|
)
|
|
|
|
count = this_roster.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Roster {roster_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=500, detail=f"Roster {roster_id} was not deleted"
|
|
)
|
|
|
|
|
|
"""
|
|
RESULTS ENDPOINTS
|
|
"""
|
|
|
|
|
|
class ResultModel(pydantic.BaseModel):
|
|
away_team_id: int
|
|
home_team_id: int
|
|
away_score: int
|
|
home_score: int
|
|
away_team_value: Optional[int] = None
|
|
home_team_value: Optional[int] = None
|
|
away_team_ranking: Optional[int] = None
|
|
home_team_ranking: Optional[int] = None
|
|
scorecard: str
|
|
week: int
|
|
season: int
|
|
ranked: bool
|
|
short_game: bool
|
|
game_type: str
|
|
|
|
|
|
@app.get("/api/v1/results")
|
|
async def v1_results_get(
|
|
away_team_id: Optional[int] = None,
|
|
home_team_id: Optional[int] = None,
|
|
team_one_id: Optional[int] = None,
|
|
team_two_id: Optional[int] = None,
|
|
away_score_min: Optional[int] = None,
|
|
away_score_max: Optional[int] = None,
|
|
home_score_min: Optional[int] = None,
|
|
home_score_max: Optional[int] = None,
|
|
bothscore_min: Optional[int] = None,
|
|
bothscore_max: Optional[int] = None,
|
|
season: Optional[int] = None,
|
|
week: Optional[int] = None,
|
|
week_start: Optional[int] = None,
|
|
week_end: Optional[int] = None,
|
|
ranked: Optional[bool] = None,
|
|
short_game: Optional[bool] = None,
|
|
game_type: Optional[str] = None,
|
|
vs_ai: Optional[bool] = None,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_results = Result.select()
|
|
|
|
# if all_results.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'There are no results to filter')
|
|
|
|
if away_team_id is not None:
|
|
try:
|
|
this_team = Team.get_by_id(away_team_id)
|
|
all_results = all_results.where(Result.away_team == this_team)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No team found with id {away_team_id}"
|
|
)
|
|
|
|
if home_team_id is not None:
|
|
try:
|
|
this_team = Team.get_by_id(home_team_id)
|
|
all_results = all_results.where(Result.home_team == this_team)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No team found with id {home_team_id}"
|
|
)
|
|
|
|
if team_one_id is not None:
|
|
try:
|
|
this_team = Team.get_by_id(team_one_id)
|
|
all_results = all_results.where(
|
|
(Result.home_team == this_team) | (Result.away_team == this_team)
|
|
)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No team found with id {team_one_id}"
|
|
)
|
|
|
|
if team_two_id is not None:
|
|
try:
|
|
this_team = Team.get_by_id(team_two_id)
|
|
all_results = all_results.where(
|
|
(Result.home_team == this_team) | (Result.away_team == this_team)
|
|
)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No team found with id {team_two_id}"
|
|
)
|
|
|
|
if away_score_min is not None:
|
|
all_results = all_results.where(Result.away_score >= away_score_min)
|
|
|
|
if away_score_max is not None:
|
|
all_results = all_results.where(Result.away_score <= away_score_max)
|
|
|
|
if home_score_min is not None:
|
|
all_results = all_results.where(Result.home_score >= home_score_min)
|
|
|
|
if home_score_max is not None:
|
|
all_results = all_results.where(Result.home_score <= home_score_max)
|
|
|
|
if bothscore_min is not None:
|
|
all_results = all_results.where(
|
|
(Result.home_score >= bothscore_min) & (Result.away_score >= bothscore_min)
|
|
)
|
|
|
|
if bothscore_max is not None:
|
|
all_results = all_results.where(
|
|
(Result.home_score <= bothscore_max) & (Result.away_score <= bothscore_max)
|
|
)
|
|
|
|
if season is not None:
|
|
all_results = all_results.where(Result.season == season)
|
|
|
|
if week is not None:
|
|
all_results = all_results.where(Result.week == week)
|
|
|
|
if ranked is not None:
|
|
all_results = all_results.where(Result.ranked == ranked)
|
|
|
|
if short_game is not None:
|
|
all_results = all_results.where(Result.short_game == short_game)
|
|
|
|
if week_start is not None:
|
|
all_results = all_results.where(Result.week >= week_start)
|
|
|
|
if week_end is not None:
|
|
all_results = all_results.where(Result.week <= week_end)
|
|
|
|
if game_type is not None:
|
|
all_results = all_results.where(Result.game_type == game_type)
|
|
|
|
all_results = all_results.order_by(Result.id)
|
|
# Not functional
|
|
# if vs_ai is not None:
|
|
# AwayTeam = Team.alias()
|
|
# all_results = all_results.join(
|
|
# Team, on=Result.home_team
|
|
# ).switch(Result).join(
|
|
# Team, on=(AwayTeam.id == Result.away_team).alias('a_team')
|
|
# )
|
|
#
|
|
# if vs_ai:
|
|
# all_results = all_results.where(
|
|
# (Result.home_team.is_ai == 1) | (Result.a_team.is_ai == 1)
|
|
# )
|
|
# else:
|
|
# all_results = all_results.where(
|
|
# (Result.home_team.is_ai == 0) & (Result.a_team.is_ai == 0)
|
|
# )
|
|
# logging.info(f'Result Query:\n\n{all_results}')
|
|
|
|
if csv:
|
|
data_list = [
|
|
[
|
|
"id",
|
|
"away_abbrev",
|
|
"home_abbrev",
|
|
"away_score",
|
|
"home_score",
|
|
"away_tv",
|
|
"home_tv",
|
|
"game_type",
|
|
"season",
|
|
"week",
|
|
"short_game",
|
|
"ranked",
|
|
]
|
|
]
|
|
for line in all_results:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.away_team.abbrev,
|
|
line.home_team.abbrev,
|
|
line.away_score,
|
|
line.home_score,
|
|
line.away_team_value,
|
|
line.home_team_value,
|
|
line.game_type if line.game_type else "minor-league",
|
|
line.season,
|
|
line.week,
|
|
line.short_game,
|
|
line.ranked,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_results.count(), "results": []}
|
|
for x in all_results:
|
|
return_val["results"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/results/{result_id}")
|
|
async def v1_results_get_one(result_id, csv: Optional[bool] = None):
|
|
try:
|
|
this_result = Result.get_by_id(result_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No result found with id {result_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [
|
|
[
|
|
"id",
|
|
"away_abbrev",
|
|
"home_abbrev",
|
|
"away_score",
|
|
"home_score",
|
|
"away_tv",
|
|
"home_tv",
|
|
"game_type",
|
|
"season",
|
|
"week",
|
|
"game_type",
|
|
],
|
|
[
|
|
this_result.id,
|
|
this_result.away_team.abbrev,
|
|
this_result.away_team.abbrev,
|
|
this_result.away_score,
|
|
this_result.home_score,
|
|
this_result.away_team_value,
|
|
this_result.home_team_value,
|
|
this_result.game_type if this_result.game_type else "minor-league",
|
|
this_result.season,
|
|
this_result.week,
|
|
this_result.game_type,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_result)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/results/team/{team_id}")
|
|
async def v1_results_team_get(
|
|
team_id: int,
|
|
season: Optional[int] = None,
|
|
week: Optional[int] = None,
|
|
csv: Optional[bool] = False,
|
|
):
|
|
all_results = Result.select().where(
|
|
(Result.away_team_id == team_id) | (Result.home_team_id == team_id)
|
|
)
|
|
try:
|
|
this_team = Team.get_by_id(team_id)
|
|
except Exception as e:
|
|
logging.error(f"Unknown team id {team_id} trying to pull team results")
|
|
raise HTTPException(404, f"Team id {team_id} not found")
|
|
|
|
if season is not None:
|
|
all_results = all_results.where(Result.season == season)
|
|
else:
|
|
all_results = all_results.where(Result.season == this_team.season)
|
|
|
|
if week is not None:
|
|
all_results = all_results.where(Result.week == week)
|
|
|
|
r_wins, r_loss, c_wins, c_loss = 0, 0, 0, 0
|
|
for x in all_results:
|
|
if x.away_team_id == team_id:
|
|
if x.away_score > x.home_score:
|
|
if x.ranked:
|
|
r_wins += 1
|
|
else:
|
|
c_wins += 1
|
|
else:
|
|
if x.ranked:
|
|
r_loss += 1
|
|
else:
|
|
c_loss += 1
|
|
elif x.home_team_id == team_id:
|
|
if x.away_score > x.home_score:
|
|
if x.ranked:
|
|
r_loss += 1
|
|
else:
|
|
c_loss += 1
|
|
else:
|
|
if x.ranked:
|
|
r_wins += 1
|
|
else:
|
|
c_wins += 1
|
|
|
|
if csv:
|
|
data_list = [
|
|
[
|
|
"team_id",
|
|
"ranked_wins",
|
|
"ranked_losses",
|
|
"casual_wins",
|
|
"casual_losses",
|
|
"team_ranking",
|
|
],
|
|
[team_id, r_wins, r_loss, c_wins, c_loss, this_team.ranking],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {
|
|
"team": model_to_dict(this_team),
|
|
"ranked_wins": r_wins,
|
|
"ranked_losses": r_loss,
|
|
"casual_wins": c_wins,
|
|
"casual_losses": c_loss,
|
|
}
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/results")
|
|
async def v1_results_post(result: ResultModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post results. This event has been logged.",
|
|
)
|
|
|
|
this_result = Result(**result.__dict__)
|
|
saved = this_result.save()
|
|
|
|
if result.ranked:
|
|
if not result.away_team_ranking:
|
|
db.close()
|
|
error = f"Ranked game did not include away team ({result.away_team_id}) ranking."
|
|
logging.error(error)
|
|
raise DataError(error)
|
|
if not result.home_team_ranking:
|
|
db.close()
|
|
error = f"Ranked game did not include home team ({result.home_team_id}) ranking."
|
|
logging.error(error)
|
|
raise DataError(error)
|
|
|
|
k_value = 20 if result.short_game else 60
|
|
ratio = (result.home_team_ranking - result.away_team_ranking) / 400
|
|
exp_score = 1 / (1 + (10**ratio))
|
|
away_win = True if result.away_score > result.home_score else False
|
|
total_delta = k_value * exp_score
|
|
high_delta = (
|
|
total_delta * exp_score
|
|
if exp_score > 0.5
|
|
else total_delta * (1 - exp_score)
|
|
)
|
|
low_delta = total_delta - high_delta
|
|
|
|
# exp_score > .5 means away team is favorite
|
|
if exp_score > 0.5 and away_win:
|
|
final_delta = low_delta
|
|
away_delta = low_delta * 3
|
|
home_delta = -low_delta
|
|
elif away_win:
|
|
final_delta = high_delta
|
|
away_delta = high_delta * 3
|
|
home_delta = -high_delta
|
|
elif exp_score <= 0.5 and not away_win:
|
|
final_delta = low_delta
|
|
away_delta = -low_delta
|
|
home_delta = low_delta * 3
|
|
elif not away_win:
|
|
final_delta = high_delta
|
|
away_delta = -high_delta
|
|
home_delta = high_delta * 3
|
|
else:
|
|
final_delta = 0
|
|
away_delta = 0
|
|
home_delta = 0
|
|
|
|
logging.debug(
|
|
f"/results ranking deltas\n\nk_value: {k_value} / ratio: {ratio} / "
|
|
f"exp_score: {exp_score} / away_win: {away_win} / total_delta: {total_delta} / "
|
|
f"high_delta: {high_delta} / low_delta: {low_delta} / final_delta: {final_delta} / "
|
|
)
|
|
|
|
away_team = Team.get_by_id(result.away_team_id)
|
|
away_team.ranking += away_delta
|
|
away_team.save()
|
|
logging.info(f"Just updated {away_team.abbrev} ranking to {away_team.ranking}")
|
|
home_team = Team.get_by_id(result.home_team_id)
|
|
home_team.ranking += home_delta
|
|
home_team.save()
|
|
logging.info(f"Just updated {home_team.abbrev} ranking to {home_team.ranking}")
|
|
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_result)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that roster",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/results/{result_id}")
|
|
async def v1_results_patch(
|
|
result_id,
|
|
away_team_id: Optional[int] = None,
|
|
home_team_id: Optional[int] = None,
|
|
away_score: Optional[int] = None,
|
|
home_score: Optional[int] = None,
|
|
away_team_value: Optional[int] = None,
|
|
home_team_value: Optional[int] = None,
|
|
scorecard: Optional[str] = None,
|
|
week: Optional[int] = None,
|
|
season: Optional[int] = None,
|
|
short_game: Optional[bool] = None,
|
|
game_type: Optional[str] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch results. This event has been logged.",
|
|
)
|
|
try:
|
|
this_result = Result.get_by_id(result_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No result found with id {result_id}"
|
|
)
|
|
|
|
if away_team_id is not None:
|
|
this_result.away_team_id = away_team_id
|
|
|
|
if home_team_id is not None:
|
|
this_result.home_team_id = home_team_id
|
|
|
|
if away_score is not None:
|
|
this_result.away_score = away_score
|
|
|
|
if home_score is not None:
|
|
this_result.home_score = home_score
|
|
|
|
if away_team_value is not None:
|
|
this_result.away_team_value = away_team_value
|
|
|
|
if home_team_value is not None:
|
|
this_result.home_team_value = home_team_value
|
|
|
|
if scorecard is not None:
|
|
this_result.scorecard = scorecard
|
|
|
|
if week is not None:
|
|
this_result.week = week
|
|
|
|
if season is not None:
|
|
this_result.season = season
|
|
|
|
if game_type is not None:
|
|
this_result.game_type = game_type
|
|
|
|
if short_game is not None:
|
|
if not short_game:
|
|
this_result.short_game = None
|
|
else:
|
|
this_result.short_game = short_game
|
|
|
|
if this_result.save() == 1:
|
|
return_val = model_to_dict(this_result)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that event",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/results/{result_id}")
|
|
async def v1_results_delete(result_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post results. This event has been logged.",
|
|
)
|
|
try:
|
|
this_result = Result.get_by_id(result_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No result found with id {result_id}"
|
|
)
|
|
|
|
count = this_result.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Result {result_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=500, detail=f"Result {result_id} was not deleted"
|
|
)
|
|
|
|
|
|
"""
|
|
AWARDS ENDPOINTS
|
|
"""
|
|
|
|
|
|
class AwardModel(pydantic.BaseModel):
|
|
name: str
|
|
season: int
|
|
timing: str = "In-Season"
|
|
card_id: Optional[int] = None
|
|
team_id: Optional[int] = None
|
|
image: Optional[str] = None
|
|
|
|
|
|
@app.get("/api/v1/awards")
|
|
async def v1_awards_get(
|
|
name: Optional[str] = None,
|
|
season: Optional[int] = None,
|
|
timing: Optional[str] = None,
|
|
card_id: Optional[int] = None,
|
|
team_id: Optional[int] = None,
|
|
image: Optional[str] = None,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_awards = Award.select()
|
|
|
|
if all_awards.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"There are no awards to filter")
|
|
|
|
if name is not None:
|
|
all_awards = all_awards.where(Award.name == name)
|
|
if season is not None:
|
|
all_awards = all_awards.where(Award.season == season)
|
|
if timing is not None:
|
|
all_awards = all_awards.where(Award.timing == timing)
|
|
if card_id is not None:
|
|
all_awards = all_awards.where(Award.card_id == card_id)
|
|
if team_id is not None:
|
|
all_awards = all_awards.where(Award.team_id == team_id)
|
|
if image is not None:
|
|
all_awards = all_awards.where(Award.image == image)
|
|
|
|
if csv:
|
|
data_list = [["id", "name", "season", "timing", "card", "team", "image"]]
|
|
for line in all_awards:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.name,
|
|
line.season,
|
|
line.timing,
|
|
line.card,
|
|
line.team,
|
|
line.image,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_awards.count(), "awards": []}
|
|
for x in all_awards:
|
|
return_val["awards"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/awards/{award_id}")
|
|
async def v1_awards_get_one(award_id, csv: Optional[bool] = None):
|
|
try:
|
|
this_award = Award.get_by_id(award_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No award found with id {award_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "name", "season", "timing", "card", "team", "image"],
|
|
[
|
|
this_award.id,
|
|
this_award.name,
|
|
this_award.season,
|
|
this_award.timing,
|
|
this_award.card,
|
|
this_award.team,
|
|
this_award.image,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_award)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/awards")
|
|
async def v1_awards_post(award: AwardModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post awards. This event has been logged.",
|
|
)
|
|
|
|
this_award = Award(
|
|
name=award.name,
|
|
season=award.season,
|
|
timing=award.season,
|
|
card_id=award.card_id,
|
|
team_id=award.team_id,
|
|
image=award.image,
|
|
)
|
|
|
|
saved = this_award.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_award)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that roster",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/awards/{award_id}")
|
|
async def v1_awards_delete(award_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete awards. This event has been logged.",
|
|
)
|
|
try:
|
|
this_award = Award.get_by_id(award_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No award found with id {award_id}"
|
|
)
|
|
|
|
count = this_award.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Award {award_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(status_code=500, detail=f"Award {award_id} was not deleted")
|
|
|
|
|
|
"""
|
|
REWARD ENDPOINTS
|
|
"""
|
|
|
|
|
|
class RewardModel(pydantic.BaseModel):
|
|
name: str
|
|
season: int
|
|
week: int
|
|
team_id: int
|
|
created: Optional[int] = int(datetime.timestamp(datetime.now()) * 1000)
|
|
|
|
|
|
@app.get("/api/v1/rewards")
|
|
async def v1_rewards_get(
|
|
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,
|
|
):
|
|
all_rewards = Reward.select()
|
|
|
|
if all_rewards.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"There are no rewards to filter")
|
|
|
|
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:
|
|
all_rewards = all_rewards.where(Reward.created >= created_after)
|
|
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)
|
|
|
|
if all_rewards.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No rewards found")
|
|
|
|
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)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_rewards.count(), "rewards": []}
|
|
for x in all_rewards:
|
|
return_val["rewards"].append(model_to_dict(x, recurse=not flat))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/rewards/{reward_id}")
|
|
async def v1_rewards_get_one(reward_id, csv: Optional[bool] = False):
|
|
try:
|
|
this_reward = Reward.get_by_id(reward_id)
|
|
except Exception:
|
|
db.close()
|
|
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)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_reward)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/rewards")
|
|
async def v1_rewards_post(reward: RewardModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post rewards. This event has been logged.",
|
|
)
|
|
|
|
this_reward = Reward(**reward.dict())
|
|
|
|
saved = this_reward.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_reward)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/rewards/{reward_id}")
|
|
async def v1_rewards_patch(
|
|
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(f"Bad Token: {token}")
|
|
db.close()
|
|
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 Exception:
|
|
db.close()
|
|
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:
|
|
this_reward.created = created
|
|
|
|
if this_reward.save() == 1:
|
|
return_val = model_to_dict(this_reward)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/rewards/{reward_id}")
|
|
async def v1_rewards_delete(reward_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
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 Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No reward found with id {reward_id}"
|
|
)
|
|
|
|
count = this_reward.delete_instance()
|
|
db.close()
|
|
|
|
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"
|
|
)
|
|
|
|
|
|
"""
|
|
BATTING STATS ENDPOINTS
|
|
"""
|
|
|
|
|
|
class BatStat(pydantic.BaseModel):
|
|
card_id: int
|
|
team_id: int
|
|
roster_num: int
|
|
vs_team_id: int
|
|
pos: str
|
|
pa: Optional[int] = 0
|
|
ab: Optional[int] = 0
|
|
run: Optional[int] = 0
|
|
hit: Optional[int] = 0
|
|
rbi: Optional[int] = 0
|
|
double: Optional[int] = 0
|
|
triple: Optional[int] = 0
|
|
hr: Optional[int] = 0
|
|
bb: Optional[int] = 0
|
|
so: Optional[int] = 0
|
|
hbp: Optional[int] = 0
|
|
sac: Optional[int] = 0
|
|
ibb: Optional[int] = 0
|
|
gidp: Optional[int] = 0
|
|
sb: Optional[int] = 0
|
|
cs: Optional[int] = 0
|
|
bphr: Optional[int] = 0
|
|
bpfo: Optional[int] = 0
|
|
bp1b: Optional[int] = 0
|
|
bplo: Optional[int] = 0
|
|
xch: Optional[int] = 0
|
|
xhit: Optional[int] = 0
|
|
error: Optional[int] = 0
|
|
pb: Optional[int] = 0
|
|
sbc: Optional[int] = 0
|
|
csc: Optional[int] = 0
|
|
week: int
|
|
season: int
|
|
created: Optional[int] = int(datetime.timestamp(datetime.now()) * 100000)
|
|
game_id: int
|
|
|
|
|
|
class BattingStatModel(pydantic.BaseModel):
|
|
stats: List[BatStat]
|
|
|
|
|
|
@app.get("/api/v1/batstats")
|
|
async def v1_batstats_get(
|
|
card_id: int = None,
|
|
player_id: int = None,
|
|
team_id: int = None,
|
|
vs_team_id: int = None,
|
|
week: int = None,
|
|
season: int = None,
|
|
week_start: int = None,
|
|
week_end: int = None,
|
|
created: int = None,
|
|
csv: bool = None,
|
|
):
|
|
all_stats = BattingStat.select().join(Card).join(Player)
|
|
|
|
if card_id is not None:
|
|
all_stats = all_stats.where(BattingStat.card_id == card_id)
|
|
if player_id is not None:
|
|
all_stats = all_stats.where(BattingStat.card.player.player_id == player_id)
|
|
if team_id is not None:
|
|
all_stats = all_stats.where(BattingStat.team_id == team_id)
|
|
if vs_team_id is not None:
|
|
all_stats = all_stats.where(BattingStat.vs_team_id == vs_team_id)
|
|
if week is not None:
|
|
all_stats = all_stats.where(BattingStat.week == week)
|
|
if season is not None:
|
|
all_stats = all_stats.where(BattingStat.season == season)
|
|
if week_start is not None:
|
|
all_stats = all_stats.where(BattingStat.week >= week_start)
|
|
if week_end is not None:
|
|
all_stats = all_stats.where(BattingStat.week <= week_end)
|
|
if created is not None:
|
|
all_stats = all_stats.where(BattingStat.created == created)
|
|
|
|
# if all_stats.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'No batting stats found')
|
|
|
|
if csv:
|
|
data_list = [
|
|
[
|
|
"id",
|
|
"card_id",
|
|
"player_id",
|
|
"cardset",
|
|
"team",
|
|
"vs_team",
|
|
"pos",
|
|
"pa",
|
|
"ab",
|
|
"run",
|
|
"hit",
|
|
"rbi",
|
|
"double",
|
|
"triple",
|
|
"hr",
|
|
"bb",
|
|
"so",
|
|
"hbp",
|
|
"sac",
|
|
"ibb",
|
|
"gidp",
|
|
"sb",
|
|
"cs",
|
|
"bphr",
|
|
"bpfo",
|
|
"bp1b",
|
|
"bplo",
|
|
"xch",
|
|
"xhit",
|
|
"error",
|
|
"pb",
|
|
"sbc",
|
|
"csc",
|
|
"week",
|
|
"season",
|
|
"created",
|
|
"game_id",
|
|
"roster_num",
|
|
]
|
|
]
|
|
for line in all_stats:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.card.id,
|
|
line.card.player.player_id,
|
|
line.card.player.cardset.name,
|
|
line.team.abbrev,
|
|
line.vs_team.abbrev,
|
|
line.pos,
|
|
line.pa,
|
|
line.ab,
|
|
line.run,
|
|
line.hit,
|
|
line.rbi,
|
|
line.double,
|
|
line.triple,
|
|
line.hr,
|
|
line.bb,
|
|
line.so,
|
|
line.hbp,
|
|
line.sac,
|
|
line.ibb,
|
|
line.gidp,
|
|
line.sb,
|
|
line.cs,
|
|
line.bphr,
|
|
line.bpfo,
|
|
line.bp1b,
|
|
line.bplo,
|
|
line.xch,
|
|
line.xhit,
|
|
line.error,
|
|
line.pb,
|
|
line.sbc,
|
|
line.csc,
|
|
line.week,
|
|
line.season,
|
|
line.created,
|
|
line.game_id,
|
|
line.roster_num,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_stats.count(), "stats": []}
|
|
for x in all_stats:
|
|
return_val["stats"].append(model_to_dict(x, recurse=False))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/batstats/player/{player_id}")
|
|
async def v1_batstats_get_card(
|
|
player_id: int,
|
|
team_id: int = None,
|
|
vs_team_id: int = None,
|
|
week_start: int = None,
|
|
week_end: int = None,
|
|
csv: bool = None,
|
|
):
|
|
all_stats = (
|
|
BattingStat.select(fn.COUNT(BattingStat.created).alias("game_count"))
|
|
.join(Card)
|
|
.group_by(BattingStat.card)
|
|
.where(BattingStat.card.player == player_id)
|
|
).scalar()
|
|
|
|
if team_id is not None:
|
|
all_stats = all_stats.where(BattingStat.team_id == team_id)
|
|
if vs_team_id is not None:
|
|
all_stats = all_stats.where(BattingStat.vs_team_id == vs_team_id)
|
|
if week_start is not None:
|
|
all_stats = all_stats.where(BattingStat.week >= week_start)
|
|
if week_end is not None:
|
|
all_stats = all_stats.where(BattingStat.week <= week_end)
|
|
|
|
if csv:
|
|
data_list = [
|
|
[
|
|
"pa",
|
|
"ab",
|
|
"run",
|
|
"hit",
|
|
"rbi",
|
|
"double",
|
|
"triple",
|
|
"hr",
|
|
"bb",
|
|
"so",
|
|
"hbp",
|
|
"sac",
|
|
"ibb",
|
|
"gidp",
|
|
"sb",
|
|
"cs",
|
|
"bphr",
|
|
"bpfo",
|
|
"bp1b",
|
|
"bplo",
|
|
"xch",
|
|
"xhit",
|
|
"error",
|
|
"pb",
|
|
"sbc",
|
|
"csc",
|
|
],
|
|
[
|
|
all_stats.pa_sum,
|
|
all_stats.ab_sum,
|
|
all_stats.run,
|
|
all_stats.hit_sum,
|
|
all_stats.rbi_sum,
|
|
all_stats.double_sum,
|
|
all_stats.triple_sum,
|
|
all_stats.hr_sum,
|
|
all_stats.bb_sum,
|
|
all_stats.so_sum,
|
|
all_stats.hbp_sum,
|
|
all_stats.sac,
|
|
all_stats.ibb_sum,
|
|
all_stats.gidp_sum,
|
|
all_stats.sb_sum,
|
|
all_stats.cs_sum,
|
|
all_stats.bphr_sum,
|
|
all_stats.bpfo_sum,
|
|
all_stats.bp1b_sum,
|
|
all_stats.bplo_sum,
|
|
all_stats.xch,
|
|
all_stats.xhit_sum,
|
|
all_stats.error_sum,
|
|
all_stats.pb_sum,
|
|
all_stats.sbc_sum,
|
|
all_stats.csc_sum,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
logging.debug(f"stat pull query: {all_stats}\n")
|
|
# logging.debug(f'result 0: {all_stats[0]}\n')
|
|
for x in all_stats:
|
|
logging.debug(f"this_line: {model_to_dict(x)}")
|
|
return_val = model_to_dict(all_stats[0])
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/plays/batting")
|
|
async def get_batting_totals(
|
|
player_id: list = Query(default=None),
|
|
team_id: list = Query(default=None),
|
|
min_pa: Optional[int] = 1,
|
|
season: list = Query(default=None),
|
|
position: list = Query(default=None),
|
|
group_by: Literal[
|
|
"team", "player", "playerteam", "playergame", "teamgame", "league"
|
|
] = "player",
|
|
sort: Optional[str] = None,
|
|
limit: Optional[int] = None,
|
|
short_output: Optional[bool] = False,
|
|
):
|
|
all_stats = (
|
|
BattingStat.select(
|
|
BattingStat.card,
|
|
BattingStat.game_id,
|
|
BattingStat.team,
|
|
BattingStat.vs_team,
|
|
BattingStat.pos,
|
|
BattingStat.card.player.alias("player"),
|
|
fn.SUM(BattingStat.pa).alias("sum_pa"),
|
|
fn.SUM(BattingStat.ab).alias("sum_ab"),
|
|
fn.SUM(BattingStat.run).alias("sum_run"),
|
|
fn.SUM(BattingStat.so).alias("sum_so"),
|
|
fn.SUM(BattingStat.hit).alias("sum_hit"),
|
|
fn.SUM(BattingStat.rbi).alias("sum_rbi"),
|
|
fn.SUM(BattingStat.double).alias("sum_double"),
|
|
fn.SUM(BattingStat.triple).alias("sum_triple"),
|
|
fn.SUM(BattingStat.hr).alias("sum_hr"),
|
|
fn.SUM(BattingStat.bb).alias("sum_bb"),
|
|
fn.SUM(BattingStat.hbp).alias("sum_hbp"),
|
|
fn.SUM(BattingStat.sac).alias("sum_sac"),
|
|
fn.SUM(BattingStat.ibb).alias("sum_ibb"),
|
|
fn.SUM(BattingStat.gidp).alias("sum_gidp"),
|
|
fn.SUM(BattingStat.sb).alias("sum_sb"),
|
|
fn.SUM(BattingStat.cs).alias("sum_cs"),
|
|
fn.SUM(BattingStat.bphr).alias("sum_bphr"),
|
|
fn.SUM(BattingStat.bpfo).alias("sum_bpfo"),
|
|
fn.SUM(BattingStat.bp1b).alias("sum_bp1b"),
|
|
fn.SUM(BattingStat.bplo).alias("sum_bplo"),
|
|
)
|
|
.having(fn.SUM(BattingStat.pa) >= min_pa)
|
|
.join(Card)
|
|
)
|
|
|
|
if player_id is not None:
|
|
# all_players = Player.select().where(Player.id << player_id)
|
|
all_cards = Card.select().where(Card.player_id << player_id)
|
|
all_stats = all_stats.where(BattingStat.card << all_cards)
|
|
if team_id is not None:
|
|
all_teams = Team.select().where(Team.id << team_id)
|
|
all_stats = all_stats.where(BattingStat.team << all_teams)
|
|
if season is not None:
|
|
all_stats = all_stats.where(BattingStat.season << season)
|
|
if position is not None:
|
|
all_stats = all_stats.where(BattingStat.pos << position)
|
|
|
|
if group_by == "player":
|
|
all_stats = all_stats.group_by(SQL("player"))
|
|
elif group_by == "playerteam":
|
|
all_stats = all_stats.group_by(SQL("player"), BattingStat.team)
|
|
elif group_by == "playergame":
|
|
all_stats = all_stats.group_by(SQL("player"), BattingStat.game_id)
|
|
elif group_by == "team":
|
|
all_stats = all_stats.group_by(BattingStat.team)
|
|
elif group_by == "teamgame":
|
|
all_stats = all_stats.group_by(BattingStat.team, BattingStat.game_id)
|
|
elif group_by == "league":
|
|
all_stats = all_stats.group_by(BattingStat.season)
|
|
|
|
if sort == "pa-desc":
|
|
all_stats = all_stats.order_by(SQL("sum_pa").desc())
|
|
elif sort == "newest":
|
|
all_stats = all_stats.order_by(-BattingStat.game_id)
|
|
elif sort == "oldest":
|
|
all_stats = all_stats.order_by(BattingStat.game_id)
|
|
|
|
if limit is not None:
|
|
if limit < 1:
|
|
limit = 1
|
|
all_stats = all_stats.limit(limit)
|
|
|
|
logging.info(f"bat_plays query: {all_stats}")
|
|
|
|
return_stats = {
|
|
"count": all_stats.count(),
|
|
"stats": [
|
|
{
|
|
"player": x.card.player_id
|
|
if short_output
|
|
else model_to_dict(x.card.player, recurse=False),
|
|
"team": x.team_id
|
|
if short_output
|
|
else model_to_dict(x.team, recurse=False),
|
|
"pa": x.sum_pa,
|
|
"ab": x.sum_ab,
|
|
"run": x.sum_run,
|
|
"hit": x.sum_hit,
|
|
"rbi": x.sum_rbi,
|
|
"double": x.sum_double,
|
|
"triple": x.sum_triple,
|
|
"hr": x.sum_hr,
|
|
"bb": x.sum_bb,
|
|
"so": x.sum_so,
|
|
"hbp": x.sum_hbp,
|
|
"sac": x.sum_sac,
|
|
"ibb": x.sum_ibb,
|
|
"gidp": x.sum_gidp,
|
|
"sb": x.sum_sb,
|
|
"cs": x.sum_cs,
|
|
"bphr": x.sum_bphr,
|
|
"bpfo": x.sum_bpfo,
|
|
"bp1b": x.sum_bp1b,
|
|
"bplo": x.sum_bplo,
|
|
"avg": x.sum_hit / max(x.sum_ab, 1),
|
|
"obp": (x.sum_hit + x.sum_bb + x.sum_hbp + x.sum_ibb)
|
|
/ max(x.sum_pa, 1),
|
|
"slg": (
|
|
x.sum_hr * 4
|
|
+ x.sum_triple * 3
|
|
+ x.sum_double * 2
|
|
+ (x.sum_hit - x.sum_double - x.sum_triple - x.sum_hr)
|
|
)
|
|
/ max(x.sum_ab, 1),
|
|
"ops": (
|
|
(x.sum_hit + x.sum_bb + x.sum_hbp + x.sum_ibb) / max(x.sum_pa, 1)
|
|
)
|
|
+ (
|
|
(
|
|
x.sum_hr * 4
|
|
+ x.sum_triple * 3
|
|
+ x.sum_double * 2
|
|
+ (x.sum_hit - x.sum_double - x.sum_triple - x.sum_hr)
|
|
)
|
|
/ max(x.sum_ab, 1)
|
|
),
|
|
"woba": (
|
|
0.69 * x.sum_bb
|
|
+ 0.72 * x.sum_hbp
|
|
+ 0.89 * (x.sum_hit - x.sum_double - x.sum_triple - x.sum_hr)
|
|
+ 1.27 * x.sum_double
|
|
+ 1.62 * x.sum_triple
|
|
+ 2.1 * x.sum_hr
|
|
)
|
|
/ max(x.sum_pa - x.sum_ibb, 1),
|
|
"game": x.game_id,
|
|
}
|
|
for x in all_stats
|
|
],
|
|
}
|
|
|
|
db.close()
|
|
return return_stats
|
|
|
|
|
|
@app.get("/api/v1/plays/pitching")
|
|
async def get_pitching_totals(
|
|
player_id: list = Query(default=None),
|
|
team_id: list = Query(default=None),
|
|
season: list = Query(default=None),
|
|
group_by: Literal[
|
|
"team", "player", "playerteam", "playergame", "teamgame", "league"
|
|
] = "player",
|
|
min_pa: Optional[int] = 1,
|
|
sort: Optional[str] = None,
|
|
limit: Optional[int] = None,
|
|
short_output: Optional[bool] = False,
|
|
):
|
|
all_stats = (
|
|
PitchingStat.select(
|
|
PitchingStat.card,
|
|
PitchingStat.team,
|
|
PitchingStat.game_id,
|
|
PitchingStat.vs_team,
|
|
PitchingStat.card.player.alias("player"),
|
|
fn.SUM(PitchingStat.ip).alias("sum_ip"),
|
|
fn.SUM(PitchingStat.hit).alias("sum_hit"),
|
|
fn.SUM(PitchingStat.run).alias("sum_run"),
|
|
fn.SUM(PitchingStat.erun).alias("sum_erun"),
|
|
fn.SUM(PitchingStat.so).alias("sum_so"),
|
|
fn.SUM(PitchingStat.bb).alias("sum_bb"),
|
|
fn.SUM(PitchingStat.hbp).alias("sum_hbp"),
|
|
fn.SUM(PitchingStat.wp).alias("sum_wp"),
|
|
fn.SUM(PitchingStat.balk).alias("sum_balk"),
|
|
fn.SUM(PitchingStat.hr).alias("sum_hr"),
|
|
fn.SUM(PitchingStat.ir).alias("sum_ir"),
|
|
fn.SUM(PitchingStat.irs).alias("sum_irs"),
|
|
fn.SUM(PitchingStat.gs).alias("sum_gs"),
|
|
fn.SUM(PitchingStat.win).alias("sum_win"),
|
|
fn.SUM(PitchingStat.loss).alias("sum_loss"),
|
|
fn.SUM(PitchingStat.hold).alias("sum_hold"),
|
|
fn.SUM(PitchingStat.sv).alias("sum_sv"),
|
|
fn.SUM(PitchingStat.bsv).alias("sum_bsv"),
|
|
fn.COUNT(PitchingStat.game_id).alias("sum_games"),
|
|
)
|
|
.having(fn.SUM(PitchingStat.ip) >= max(min_pa / 3, 1))
|
|
.join(Card)
|
|
)
|
|
|
|
if player_id is not None:
|
|
all_cards = Card.select().where(Card.player_id << player_id)
|
|
all_stats = all_stats.where(PitchingStat.card << all_cards)
|
|
if team_id is not None:
|
|
all_teams = Team.select().where(Team.id << team_id)
|
|
all_stats = all_stats.where(PitchingStat.team << all_teams)
|
|
if season is not None:
|
|
all_stats = all_stats.where(PitchingStat.season << season)
|
|
|
|
if group_by == "player":
|
|
all_stats = all_stats.group_by(SQL("player"))
|
|
elif group_by == "playerteam":
|
|
all_stats = all_stats.group_by(SQL("player"), PitchingStat.team)
|
|
elif group_by == "playergame":
|
|
all_stats = all_stats.group_by(SQL("player"), PitchingStat.game_id)
|
|
elif group_by == "team":
|
|
all_stats = all_stats.group_by(PitchingStat.team)
|
|
elif group_by == "teamgame":
|
|
all_stats = all_stats.group_by(PitchingStat.team, PitchingStat.game_id)
|
|
elif group_by == "league":
|
|
all_stats = all_stats.group_by(PitchingStat.season)
|
|
|
|
if sort == "pa-desc":
|
|
all_stats = all_stats.order_by(SQL("sum_pa").desc())
|
|
elif sort == "newest":
|
|
all_stats = all_stats.order_by(-PitchingStat.game_id)
|
|
elif sort == "oldest":
|
|
all_stats = all_stats.order_by(PitchingStat.game_id)
|
|
|
|
if limit is not None:
|
|
if limit < 1:
|
|
limit = 1
|
|
all_stats = all_stats.limit(limit)
|
|
|
|
logging.info(f"bat_plays query: {all_stats}")
|
|
|
|
return_stats = {
|
|
"count": all_stats.count(),
|
|
"stats": [
|
|
{
|
|
"player": x.card.player_id
|
|
if short_output
|
|
else model_to_dict(x.card.player, recurse=False),
|
|
"team": x.team_id
|
|
if short_output
|
|
else model_to_dict(x.team, recurse=False),
|
|
"tbf": None,
|
|
"outs": round(x.sum_ip * 3),
|
|
"games": x.sum_games,
|
|
"gs": x.sum_gs,
|
|
"win": x.sum_win,
|
|
"loss": x.sum_loss,
|
|
"hold": x.sum_hold,
|
|
"save": x.sum_sv,
|
|
"bsave": x.sum_bsv,
|
|
"ir": x.sum_ir,
|
|
"ir_sc": x.sum_irs,
|
|
"runs": x.sum_run,
|
|
"e_runs": x.sum_erun,
|
|
"hits": x.sum_hit,
|
|
"hr": x.sum_hr,
|
|
"bb": x.sum_bb,
|
|
"so": x.sum_so,
|
|
"hbp": x.sum_hbp,
|
|
"wp": x.sum_wp,
|
|
"balk": x.sum_balk,
|
|
"era": (x.sum_erun * 27) / round(x.sum_ip * 3),
|
|
"whip": (x.sum_bb + x.sum_hit) / x.sum_ip,
|
|
"avg": None,
|
|
"obp": None,
|
|
"woba": None,
|
|
"k/9": x.sum_so * 9 / x.sum_ip,
|
|
"bb/9": x.sum_bb * 9 / x.sum_ip,
|
|
"k/bb": x.sum_so / max(x.sum_bb, 0.1),
|
|
"game": None,
|
|
"lob_2outs": None,
|
|
"rbi%": None,
|
|
}
|
|
for x in all_stats
|
|
],
|
|
}
|
|
db.close()
|
|
return return_stats
|
|
|
|
|
|
@app.post("/api/v1/batstats")
|
|
async def v1_batstats_post(
|
|
stats: BattingStatModel, token: str = Depends(oauth2_scheme)
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post stats. This event has been logged.",
|
|
)
|
|
|
|
new_stats = []
|
|
for x in stats.stats:
|
|
this_stat = BattingStat(
|
|
card_id=x.card_id,
|
|
team_id=x.team_id,
|
|
roster_num=x.roster_num,
|
|
vs_team_id=x.vs_team_id,
|
|
pos=x.pos,
|
|
pa=x.pa,
|
|
ab=x.ab,
|
|
run=x.run,
|
|
hit=x.hit,
|
|
rbi=x.rbi,
|
|
double=x.double,
|
|
triple=x.triple,
|
|
hr=x.hr,
|
|
bb=x.bb,
|
|
so=x.so,
|
|
hbp=x.hbp,
|
|
sac=x.sac,
|
|
ibb=x.ibb,
|
|
gidp=x.gidp,
|
|
sb=x.sb,
|
|
cs=x.cs,
|
|
bphr=x.bphr,
|
|
bpfo=x.bpfo,
|
|
bp1b=x.bp1b,
|
|
bplo=x.bplo,
|
|
xch=x.xch,
|
|
xhit=x.xhit,
|
|
error=x.error,
|
|
pb=x.pb,
|
|
sbc=x.sbc,
|
|
csc=x.csc,
|
|
week=x.week,
|
|
season=x.season,
|
|
created=x.created,
|
|
game_id=x.game_id,
|
|
)
|
|
new_stats.append(this_stat)
|
|
|
|
with db.atomic():
|
|
BattingStat.bulk_create(new_stats, batch_size=15)
|
|
db.close()
|
|
|
|
raise HTTPException(
|
|
status_code=200, detail=f"{len(new_stats)} batting lines have been added"
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/batstats/{stat_id}")
|
|
async def v1_rewards_delete(stat_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete stats. This event has been logged.",
|
|
)
|
|
try:
|
|
this_reward = Reward.get_by_id(stat_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No stat found with id {stat_id}")
|
|
|
|
count = this_reward.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(status_code=200, detail=f"Stat {stat_id} has been deleted")
|
|
else:
|
|
raise HTTPException(status_code=500, detail=f"Stat {stat_id} was not deleted")
|
|
|
|
|
|
"""
|
|
PITCHING STATS ENDPOINTS
|
|
"""
|
|
|
|
|
|
class PitStat(pydantic.BaseModel):
|
|
card_id: int
|
|
team_id: int
|
|
vs_team_id: int
|
|
roster_num: int
|
|
ip: float
|
|
hit: Optional[int] = 0
|
|
run: Optional[int] = 0
|
|
erun: Optional[int] = 0
|
|
so: Optional[int] = 0
|
|
bb: Optional[int] = 0
|
|
hbp: Optional[int] = 0
|
|
wp: Optional[int] = 0
|
|
balk: Optional[int] = 0
|
|
hr: Optional[int] = 0
|
|
ir: Optional[int] = 0
|
|
irs: Optional[int] = 0
|
|
gs: Optional[int] = 0
|
|
win: Optional[int] = 0
|
|
loss: Optional[int] = 0
|
|
hold: Optional[int] = 0
|
|
sv: Optional[int] = 0
|
|
bsv: Optional[int] = 0
|
|
week: int
|
|
season: int
|
|
created: Optional[int] = int(datetime.timestamp(datetime.now()) * 100000)
|
|
game_id: int
|
|
|
|
|
|
class PitchingStatModel(pydantic.BaseModel):
|
|
stats: List[PitStat]
|
|
|
|
|
|
@app.get("/api/v1/pitstats")
|
|
async def v1_pitstats_get(
|
|
card_id: int = None,
|
|
player_id: int = None,
|
|
team_id: int = None,
|
|
vs_team_id: int = None,
|
|
week: int = None,
|
|
season: int = None,
|
|
week_start: int = None,
|
|
week_end: int = None,
|
|
created: int = None,
|
|
gs: bool = None,
|
|
csv: bool = None,
|
|
):
|
|
all_stats = PitchingStat.select().join(Card).join(Player)
|
|
logging.debug(f"pit query:\n\n{all_stats}")
|
|
|
|
if card_id is not None:
|
|
all_stats = all_stats.where(PitchingStat.card_id == card_id)
|
|
if player_id is not None:
|
|
all_stats = all_stats.where(PitchingStat.card.player.player_id == player_id)
|
|
if team_id is not None:
|
|
all_stats = all_stats.where(PitchingStat.team_id == team_id)
|
|
if vs_team_id is not None:
|
|
all_stats = all_stats.where(PitchingStat.vs_team_id == vs_team_id)
|
|
if week is not None:
|
|
all_stats = all_stats.where(PitchingStat.week == week)
|
|
if season is not None:
|
|
all_stats = all_stats.where(PitchingStat.season == season)
|
|
if week_start is not None:
|
|
all_stats = all_stats.where(PitchingStat.week >= week_start)
|
|
if week_end is not None:
|
|
all_stats = all_stats.where(PitchingStat.week <= week_end)
|
|
if created is not None:
|
|
all_stats = all_stats.where(PitchingStat.created <= created)
|
|
if gs is not None:
|
|
all_stats = all_stats.where(PitchingStat.gs == 1 if gs else 0)
|
|
|
|
# if all_stats.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'No pitching stats found')
|
|
|
|
if csv:
|
|
data_list = [
|
|
[
|
|
"id",
|
|
"card_id",
|
|
"player_id",
|
|
"cardset",
|
|
"team",
|
|
"vs_team",
|
|
"ip",
|
|
"hit",
|
|
"run",
|
|
"erun",
|
|
"so",
|
|
"bb",
|
|
"hbp",
|
|
"wp",
|
|
"balk",
|
|
"hr",
|
|
"ir",
|
|
"irs",
|
|
"gs",
|
|
"win",
|
|
"loss",
|
|
"hold",
|
|
"sv",
|
|
"bsv",
|
|
"week",
|
|
"season",
|
|
"created",
|
|
"game_id",
|
|
"roster_num",
|
|
]
|
|
]
|
|
for line in all_stats:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.card.id,
|
|
line.card.player.player_id,
|
|
line.card.player.cardset.name,
|
|
line.team.abbrev,
|
|
line.vs_team.abbrev,
|
|
line.ip,
|
|
line.hit,
|
|
line.run,
|
|
line.erun,
|
|
line.so,
|
|
line.bb,
|
|
line.hbp,
|
|
line.wp,
|
|
line.balk,
|
|
line.hr,
|
|
line.ir,
|
|
line.irs,
|
|
line.gs,
|
|
line.win,
|
|
line.loss,
|
|
line.hold,
|
|
line.sv,
|
|
line.bsv,
|
|
line.week,
|
|
line.season,
|
|
line.created,
|
|
line.game_id,
|
|
line.roster_num,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_stats.count(), "stats": []}
|
|
for x in all_stats:
|
|
return_val["stats"].append(model_to_dict(x, recurse=False))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/pitstats")
|
|
async def v1_batstats_post(
|
|
stats: PitchingStatModel, token: str = Depends(oauth2_scheme)
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post stats. This event has been logged.",
|
|
)
|
|
|
|
new_stats = []
|
|
for x in stats.stats:
|
|
this_stat = PitchingStat(
|
|
card_id=x.card_id,
|
|
team_id=x.team_id,
|
|
vs_team_id=x.vs_team_id,
|
|
roster_num=x.roster_num,
|
|
ip=x.ip,
|
|
hit=x.hit,
|
|
run=x.run,
|
|
erun=x.erun,
|
|
so=x.so,
|
|
bb=x.bb,
|
|
hbp=x.hbp,
|
|
wp=x.wp,
|
|
balk=x.balk,
|
|
hr=x.hr,
|
|
ir=x.ir,
|
|
irs=x.irs,
|
|
gs=x.gs,
|
|
win=x.win,
|
|
loss=x.loss,
|
|
hold=x.hold,
|
|
sv=x.sv,
|
|
bsv=x.bsv,
|
|
week=x.week,
|
|
season=x.season,
|
|
created=x.created,
|
|
game_id=x.game_id,
|
|
)
|
|
new_stats.append(this_stat)
|
|
|
|
with db.atomic():
|
|
PitchingStat.bulk_create(new_stats, batch_size=15)
|
|
db.close()
|
|
|
|
raise HTTPException(
|
|
status_code=200, detail=f"{len(new_stats)} pitching lines have been added"
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/pitstats/{stat_id}")
|
|
async def v1_rewards_delete(stat_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete stats. This event has been logged.",
|
|
)
|
|
try:
|
|
this_reward = Reward.get_by_id(stat_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"No stat found with id {stat_id}")
|
|
|
|
count = this_reward.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(status_code=200, detail=f"Stat {stat_id} has been deleted")
|
|
else:
|
|
raise HTTPException(status_code=500, detail=f"Stat {stat_id} was not deleted")
|
|
|
|
|
|
"""
|
|
NOTIFICATIONS ENDPOINTS
|
|
"""
|
|
|
|
|
|
class NotifModel(pydantic.BaseModel):
|
|
created: int
|
|
title: str
|
|
desc: Optional[str] = None
|
|
field_name: str
|
|
message: str
|
|
about: Optional[str] = "blank"
|
|
ack: Optional[bool] = False
|
|
|
|
|
|
@app.get("/api/v1/notifs")
|
|
async def v1_notifs_get(
|
|
created_after: Optional[int] = None,
|
|
title: Optional[str] = None,
|
|
desc: Optional[str] = None,
|
|
field_name: Optional[str] = None,
|
|
in_desc: Optional[str] = None,
|
|
about: Optional[str] = None,
|
|
ack: Optional[bool] = None,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_notif = Notification.select()
|
|
|
|
if all_notif.count() == 0:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"There are no notifications to filter"
|
|
)
|
|
|
|
if created_after is not None:
|
|
all_notif = all_notif.where(Notification.created < created_after)
|
|
if title is not None:
|
|
all_notif = all_notif.where(Notification.title == title)
|
|
if desc is not None:
|
|
all_notif = all_notif.where(Notification.desc == desc)
|
|
if field_name is not None:
|
|
all_notif = all_notif.where(Notification.field_name == field_name)
|
|
if in_desc is not None:
|
|
all_notif = all_notif.where(
|
|
fn.Lower(Notification.desc).contains(in_desc.lower())
|
|
)
|
|
if about is not None:
|
|
all_notif = all_notif.where(Notification.about == about)
|
|
if ack is not None:
|
|
all_notif = all_notif.where(Notification.ack == ack)
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "created", "title", "desc", "field_name", "message", "about", "ack"]
|
|
]
|
|
for line in all_notif:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.created,
|
|
line.title,
|
|
line.desc,
|
|
line.field_name,
|
|
line.message,
|
|
line.about,
|
|
line.ack,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_notif.count(), "notifs": []}
|
|
for x in all_notif:
|
|
return_val["notifs"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/notifs/{notif_id}")
|
|
async def v1_notifs_get_one(notif_id, csv: Optional[bool] = None):
|
|
try:
|
|
this_notif = Notification.get_by_id(notif_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No notification found with id {notif_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "created", "title", "desc", "field_name", "message", "about", "ack"],
|
|
[
|
|
this_notif.id,
|
|
this_notif.created,
|
|
this_notif.title,
|
|
this_notif.desc,
|
|
this_notif.field_name,
|
|
this_notif.message,
|
|
this_notif.about,
|
|
this_notif.ack,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_notif)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/notifs")
|
|
async def v1_notifs_post(notif: NotifModel, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post notifications. This event has been logged.",
|
|
)
|
|
|
|
logging.info(f"new notif: {notif}")
|
|
this_notif = Notification(
|
|
created=notif.created,
|
|
title=notif.title,
|
|
desc=notif.desc,
|
|
field_name=notif.field_name,
|
|
message=notif.message,
|
|
about=notif.about,
|
|
)
|
|
|
|
saved = this_notif.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_notif)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that notification",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/notifs/{notif_id}")
|
|
async def v1_rewards_patch(
|
|
notif_id,
|
|
created: Optional[int] = None,
|
|
title: Optional[str] = None,
|
|
desc: Optional[str] = None,
|
|
field_name: Optional[str] = None,
|
|
message: Optional[str] = None,
|
|
about: Optional[str] = None,
|
|
ack: Optional[bool] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch notifications. This event has been logged.",
|
|
)
|
|
try:
|
|
this_notif = Notification.get_by_id(notif_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No notification found with id {notif_id}"
|
|
)
|
|
|
|
if title is not None:
|
|
this_notif.title = title
|
|
if desc is not None:
|
|
this_notif.desc = desc
|
|
if field_name is not None:
|
|
this_notif.field_name = field_name
|
|
if message is not None:
|
|
this_notif.message = message
|
|
if about is not None:
|
|
this_notif.about = about
|
|
if ack is not None:
|
|
this_notif.ack = ack
|
|
if created is not None:
|
|
this_notif.created = created
|
|
|
|
if this_notif.save() == 1:
|
|
return_val = model_to_dict(this_notif)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/notifs/{notif_id}")
|
|
async def v1_notifs_delete(notif_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete notifications. This event has been logged.",
|
|
)
|
|
try:
|
|
this_notif = Notification.get_by_id(notif_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No notification found with id {notif_id}"
|
|
)
|
|
|
|
count = this_notif.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Notification {notif_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=500, detail=f"Notification {notif_id} was not deleted"
|
|
)
|
|
|
|
|
|
"""
|
|
PAPERDEX ENDPOINTS
|
|
"""
|
|
|
|
|
|
class PaperdexModel(pydantic.BaseModel):
|
|
team_id: int
|
|
player_id: int
|
|
created: Optional[int] = int(datetime.timestamp(datetime.now()) * 1000)
|
|
|
|
|
|
@app.get("/api/v1/paperdex")
|
|
async def v1_paperdex_get(
|
|
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,
|
|
):
|
|
all_dex = Paperdex.select().join(Player).join(Cardset)
|
|
|
|
if all_dex.count() == 0:
|
|
db.close()
|
|
raise HTTPException(status_code=404, detail=f"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:
|
|
all_dex = all_dex.where(Paperdex.created >= created_after)
|
|
if created_before is not None:
|
|
all_dex = all_dex.where(Paperdex.created <= created_before)
|
|
|
|
# if all_dex.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'No paperdex found')
|
|
|
|
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)
|
|
|
|
db.close()
|
|
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))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/paperdex/{paperdex_id}")
|
|
async def v1_paperdex_get_one(paperdex_id, csv: Optional[bool] = False):
|
|
try:
|
|
this_dex = Paperdex.get_by_id(paperdex_id)
|
|
except Exception:
|
|
db.close()
|
|
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)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_dex)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/paperdex")
|
|
async def v1_paperdex_post(
|
|
paperdex: PaperdexModel, token: str = Depends(oauth2_scheme)
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
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)
|
|
db.close()
|
|
return return_val
|
|
|
|
this_dex = Paperdex(
|
|
team_id=paperdex.team_id, player_id=paperdex.player_id, created=paperdex.created
|
|
)
|
|
|
|
saved = this_dex.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_dex)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/paperdex/{paperdex_id}")
|
|
async def v1_paperdex_patch(
|
|
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(f"Bad Token: {token}")
|
|
db.close()
|
|
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 Exception:
|
|
db.close()
|
|
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 = created
|
|
|
|
if this_dex.save() == 1:
|
|
return_val = model_to_dict(this_dex)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/paperdex/{paperdex_id}")
|
|
async def v1_paperdex_delete(paperdex_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
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 Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No paperdex found with id {paperdex_id}"
|
|
)
|
|
|
|
count = this_dex.delete_instance()
|
|
db.close()
|
|
|
|
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"
|
|
)
|
|
|
|
|
|
@app.post("/api/v1/paperdex/wipe-ai")
|
|
async def v1_paperdex_wipeai(token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
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"
|
|
|
|
|
|
"""
|
|
GAMEREWARDS ENDPOINTS
|
|
"""
|
|
|
|
|
|
class GameRewardModel(pydantic.BaseModel):
|
|
name: str
|
|
pack_type_id: Optional[int] = None
|
|
player_id: Optional[int] = None
|
|
money: Optional[int] = None
|
|
|
|
|
|
@app.get("/api/v1/gamerewards")
|
|
async def v1_gamerewards_get(
|
|
name: Optional[str] = None,
|
|
pack_type_id: Optional[int] = None,
|
|
player_id: Optional[int] = None,
|
|
money: Optional[int] = None,
|
|
csv: Optional[bool] = None,
|
|
):
|
|
all_rewards = GameRewards.select()
|
|
|
|
# if all_rewards.count() == 0:
|
|
# db.close()
|
|
# raise HTTPException(status_code=404, detail=f'There are no awards to filter')
|
|
|
|
if name is not None:
|
|
all_rewards = all_rewards.where(GameRewards.name == name)
|
|
if pack_type_id is not None:
|
|
all_rewards = all_rewards.where(GameRewards.pack_type_id == pack_type_id)
|
|
if player_id is not None:
|
|
all_rewards = all_rewards.where(GameRewards.player_id == player_id)
|
|
if money is not None:
|
|
all_rewards = all_rewards.where(GameRewards.money == money)
|
|
|
|
if csv:
|
|
data_list = [["id", "pack_type_id", "player_id", "money"]]
|
|
for line in all_rewards:
|
|
data_list.append(
|
|
[
|
|
line.id,
|
|
line.pack_type_id if line.pack_type else None,
|
|
line.player_id if line.player else None,
|
|
line.money,
|
|
]
|
|
)
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = {"count": all_rewards.count(), "gamerewards": []}
|
|
for x in all_rewards:
|
|
return_val["gamerewards"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/gamerewards/{gameaward_id}")
|
|
async def v1_gamerewards_get_one(gamereward_id, csv: Optional[bool] = None):
|
|
try:
|
|
this_game_reward = GameRewards.get_by_id(gamereward_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No game reward found with id {gamereward_id}"
|
|
)
|
|
|
|
if csv:
|
|
data_list = [
|
|
["id", "pack_type_id", "player_id", "money"],
|
|
[
|
|
this_game_reward.id,
|
|
this_game_reward.pack_type_id if this_game_reward.pack_type else None,
|
|
this_game_reward.player_id if this_game_reward.player else None,
|
|
this_game_reward.money,
|
|
],
|
|
]
|
|
return_val = DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
db.close()
|
|
return Response(content=return_val, media_type="text/csv")
|
|
|
|
else:
|
|
return_val = model_to_dict(this_game_reward)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.post("/api/v1/gamerewards")
|
|
async def v1_gamerewards_post(
|
|
game_reward: GameRewardModel, token: str = Depends(oauth2_scheme)
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post game rewards. This event has been logged.",
|
|
)
|
|
|
|
this_award = GameRewards(
|
|
name=game_reward.name,
|
|
pack_type_id=game_reward.pack_type_id,
|
|
player_id=game_reward.player_id,
|
|
money=game_reward.money,
|
|
)
|
|
|
|
saved = this_award.save()
|
|
if saved == 1:
|
|
return_val = model_to_dict(this_award)
|
|
db.close()
|
|
return return_val
|
|
else:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=418,
|
|
detail="Well slap my ass and call me a teapot; I could not save that roster",
|
|
)
|
|
|
|
|
|
@app.patch("/api/v1/gamerewards/{game_reward_id}")
|
|
async def v1_gamerewards_patch(
|
|
game_reward_id: int,
|
|
name: Optional[str] = None,
|
|
pack_type_id: Optional[int] = None,
|
|
player_id: Optional[int] = None,
|
|
money: Optional[int] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch gamerewards. This event has been logged.",
|
|
)
|
|
try:
|
|
this_game_reward = GameRewards.get_by_id(game_reward_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No game reward found with id {game_reward_id}"
|
|
)
|
|
|
|
if name is not None:
|
|
this_game_reward.name = name
|
|
if pack_type_id is not None:
|
|
if not pack_type_id:
|
|
this_game_reward.pack_type_id = None
|
|
else:
|
|
this_game_reward.pack_type_id = pack_type_id
|
|
if player_id is not None:
|
|
if not player_id:
|
|
this_game_reward.player_id = None
|
|
else:
|
|
this_game_reward.player_id = player_id
|
|
if money is not None:
|
|
if not money:
|
|
this_game_reward.money = None
|
|
else:
|
|
this_game_reward.money = money
|
|
|
|
if this_game_reward.save() == 1:
|
|
return_val = model_to_dict(this_game_reward)
|
|
db.close()
|
|
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",
|
|
)
|
|
|
|
|
|
@app.delete("/api/v1/gamerewards/{gamereward_id}")
|
|
async def v1_gamerewards_delete(gamereward_id, token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to delete awards. This event has been logged.",
|
|
)
|
|
try:
|
|
this_award = GameRewards.get_by_id(gamereward_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No award found with id {gamereward_id}"
|
|
)
|
|
|
|
count = this_award.delete_instance()
|
|
db.close()
|
|
|
|
if count == 1:
|
|
raise HTTPException(
|
|
status_code=200, detail=f"Game Reward {gamereward_id} has been deleted"
|
|
)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=500, detail=f"Game Reward {gamereward_id} was not deleted"
|
|
)
|
|
|
|
|
|
"""
|
|
GAUNTLET REWARD ENDPOINTS
|
|
"""
|
|
|
|
|
|
class GauntletRewardModel(pydantic.BaseModel):
|
|
name: str
|
|
gauntlet_id: Optional[int] = 0
|
|
reward_id: Optional[int] = 0
|
|
win_num: Optional[int] = 0
|
|
loss_max: Optional[int] = 1
|
|
|
|
|
|
class GauntletRewardList(pydantic.BaseModel):
|
|
rewards: List[GauntletRewardModel]
|
|
|
|
|
|
@app.get("/api/v1/gauntletrewards")
|
|
async def v1_gauntletreward_get(
|
|
name: Optional[str] = None,
|
|
gauntlet_id: Optional[int] = None,
|
|
reward_id: list = Query(default=None),
|
|
win_num: Optional[int] = None,
|
|
loss_max: Optional[int] = None,
|
|
):
|
|
all_rewards = GauntletReward.select()
|
|
|
|
if name is not None:
|
|
all_rewards = all_rewards.where(GauntletReward.name == name)
|
|
if gauntlet_id is not None:
|
|
all_rewards = all_rewards.where(GauntletReward.gauntlet_id == gauntlet_id)
|
|
if reward_id is not None:
|
|
all_rewards = all_rewards.where(GauntletReward.reward_id << reward_id)
|
|
if win_num is not None:
|
|
all_rewards = all_rewards.where(GauntletReward.win_num == win_num)
|
|
if loss_max is not None:
|
|
all_rewards = all_rewards.where(GauntletReward.loss_max >= loss_max)
|
|
|
|
all_rewards = all_rewards.order_by(-GauntletReward.loss_max, GauntletReward.win_num)
|
|
|
|
return_val = {"count": all_rewards.count(), "rewards": []}
|
|
for x in all_rewards:
|
|
return_val["rewards"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/gauntletrewards/{gauntletreward_id}")
|
|
async def v1_gauntletreward_get_one(gauntletreward_id):
|
|
try:
|
|
this_reward = GauntletReward.get_by_id(gauntletreward_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404,
|
|
detail=f"No gauntlet reward found with id {gauntletreward_id}",
|
|
)
|
|
|
|
return_val = model_to_dict(this_reward)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.patch("/api/v1/gauntletrewards/{gauntletreward_id}")
|
|
async def v1_gauntletreward_patch(
|
|
gauntletreward_id,
|
|
name: Optional[str] = None,
|
|
gauntlet_id: Optional[int] = None,
|
|
reward_id: Optional[int] = None,
|
|
win_num: Optional[int] = None,
|
|
loss_max: Optional[int] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch gauntlet rewards. This event has been logged.",
|
|
)
|
|
|
|
this_reward = GauntletReward.get_or_none(GauntletReward.id == gauntletreward_id)
|
|
if this_reward is None:
|
|
db.close()
|
|
raise KeyError(f"Gauntlet Reward ID {gauntletreward_id} not found")
|
|
|
|
if gauntlet_id is not None:
|
|
this_reward.gauntlet_id = gauntlet_id
|
|
if reward_id is not None:
|
|
this_reward.reward_id = reward_id
|
|
if win_num is not None:
|
|
this_reward.win_num = win_num
|
|
if loss_max is not None:
|
|
this_reward.loss_max = loss_max
|
|
if name is not None:
|
|
this_reward.name = name
|
|
|
|
if this_reward.save():
|
|
r_curr = model_to_dict(this_reward)
|
|
db.close()
|
|
return r_curr
|
|
else:
|
|
db.close()
|
|
raise DatabaseError(f"Unable to patch gauntlet reward {gauntletreward_id}")
|
|
|
|
|
|
@app.post("/api/v1/gauntletrewards")
|
|
async def v1_gauntletreward_post(
|
|
gauntletreward: GauntletRewardList, token: str = Depends(oauth2_scheme)
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post gauntlets. This event has been logged.",
|
|
)
|
|
|
|
all_rewards = []
|
|
for x in gauntletreward.rewards:
|
|
all_rewards.append(x.dict())
|
|
|
|
with db.atomic():
|
|
# Use PostgreSQL-compatible upsert helper
|
|
upsert_gauntlet_rewards(all_rewards, batch_size=15)
|
|
db.close()
|
|
|
|
return f"Inserted {len(all_rewards)} gauntlet rewards"
|
|
|
|
|
|
@app.delete("/api/v1/gauntletrewards/{gauntletreward_id}")
|
|
async def v1_gauntletreward_delete(gauntletreward_id):
|
|
if GauntletReward.delete_by_id(gauntletreward_id) == 1:
|
|
return f"Deleted gauntlet reward ID {gauntletreward_id}"
|
|
|
|
raise DatabaseError(f"Unable to delete gauntlet run {gauntletreward_id}")
|
|
|
|
|
|
"""
|
|
GAUNTLET ENDPOINTS
|
|
"""
|
|
|
|
|
|
class GauntletRunModel(pydantic.BaseModel):
|
|
team_id: int
|
|
gauntlet_id: int
|
|
wins: Optional[int] = 0
|
|
losses: Optional[int] = 0
|
|
gsheet: Optional[str] = None
|
|
created: Optional[int] = int(datetime.timestamp(datetime.now()) * 1000)
|
|
ended: Optional[int] = 0
|
|
|
|
|
|
@app.get("/api/v1/gauntletruns")
|
|
async def v1_gauntletrun_get(
|
|
team_id: list = Query(default=None),
|
|
wins: Optional[int] = None,
|
|
wins_min: Optional[int] = None,
|
|
wins_max: Optional[int] = None,
|
|
losses: Optional[int] = None,
|
|
losses_min: Optional[int] = None,
|
|
losses_max: Optional[int] = None,
|
|
gsheet: Optional[str] = None,
|
|
created_after: Optional[int] = None,
|
|
created_before: Optional[int] = None,
|
|
ended_after: Optional[int] = None,
|
|
ended_before: Optional[int] = None,
|
|
is_active: Optional[bool] = None,
|
|
gauntlet_id: list = Query(default=None),
|
|
season: list = Query(default=None),
|
|
):
|
|
all_gauntlets = GauntletRun.select()
|
|
|
|
if team_id is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.team_id << team_id)
|
|
if wins is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.wins == wins)
|
|
if wins_min is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.wins >= wins_min)
|
|
if wins_max is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.wins <= wins_max)
|
|
if losses is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.losses == losses)
|
|
if losses_min is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.losses >= losses_min)
|
|
if losses_max is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.losses <= losses_max)
|
|
if gsheet is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.gsheet == gsheet)
|
|
if created_after is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.created >= created_after)
|
|
if created_before is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.created <= created_before)
|
|
if ended_after is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.ended >= ended_after)
|
|
if ended_before is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.ended <= ended_before)
|
|
if is_active is not None:
|
|
if is_active is True:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.ended == 0)
|
|
else:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.ended != 0)
|
|
if gauntlet_id is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.gauntlet_id << gauntlet_id)
|
|
if season is not None:
|
|
all_gauntlets = all_gauntlets.where(GauntletRun.team.season << season)
|
|
|
|
return_val = {"count": all_gauntlets.count(), "runs": []}
|
|
for x in all_gauntlets:
|
|
return_val["runs"].append(model_to_dict(x))
|
|
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.get("/api/v1/gauntletruns/{gauntletrun_id}")
|
|
async def v1_gauntletrun_get_one(gauntletrun_id):
|
|
try:
|
|
this_gauntlet = GauntletRun.get_by_id(gauntletrun_id)
|
|
except Exception:
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=404, detail=f"No gauntlet found with id {gauntletrun_id}"
|
|
)
|
|
|
|
return_val = model_to_dict(this_gauntlet)
|
|
db.close()
|
|
return return_val
|
|
|
|
|
|
@app.patch("/api/v1/gauntletruns/{gauntletrun_id}")
|
|
async def v1_gauntletrun_patch(
|
|
gauntletrun_id,
|
|
team_id: Optional[int] = None,
|
|
wins: Optional[int] = None,
|
|
losses: Optional[int] = None,
|
|
gsheet: Optional[str] = None,
|
|
created: Optional[bool] = None,
|
|
ended: Optional[bool] = None,
|
|
token: str = Depends(oauth2_scheme),
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to patch gauntlet runs. This event has been logged.",
|
|
)
|
|
|
|
this_run = GauntletRun.get_or_none(GauntletRun.id == gauntletrun_id)
|
|
if this_run is None:
|
|
db.close()
|
|
raise KeyError(f"Gauntlet Run ID {gauntletrun_id} not found")
|
|
|
|
if team_id is not None:
|
|
this_run.team_id = team_id
|
|
if wins is not None:
|
|
this_run.wins = wins
|
|
if losses is not None:
|
|
this_run.losses = losses
|
|
if gsheet is not None:
|
|
this_run.gsheet = gsheet
|
|
if created is not None:
|
|
if created is True:
|
|
this_run.created = int(datetime.timestamp(datetime.now()) * 1000)
|
|
else:
|
|
this_run.created = None
|
|
if ended is not None:
|
|
if ended is True:
|
|
this_run.ended = int(datetime.timestamp(datetime.now()) * 1000)
|
|
else:
|
|
this_run.ended = 0
|
|
|
|
if this_run.save():
|
|
r_curr = model_to_dict(this_run)
|
|
db.close()
|
|
return r_curr
|
|
else:
|
|
db.close()
|
|
raise DatabaseError(f"Unable to patch gauntlet run {gauntletrun_id}")
|
|
|
|
|
|
@app.post("/api/v1/gauntletruns")
|
|
async def v1_gauntletrun_post(
|
|
gauntletrun: GauntletRunModel, token: str = Depends(oauth2_scheme)
|
|
):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post gauntlets. This event has been logged.",
|
|
)
|
|
|
|
this_run = GauntletRun(**gauntletrun.dict())
|
|
|
|
if this_run.save():
|
|
r_run = model_to_dict(this_run)
|
|
db.close()
|
|
return r_run
|
|
else:
|
|
db.close()
|
|
raise DatabaseError(f"Unable to post gauntlet run")
|
|
|
|
|
|
@app.delete("/api/v1/gauntletruns/{gauntletrun_id}")
|
|
async def v1_gauntletrun_delete(gauntletrun_id):
|
|
if GauntletRun.delete_by_id(gauntletrun_id) == 1:
|
|
return f"Deleted gauntlet run ID {gauntletrun_id}"
|
|
|
|
raise DatabaseError(f"Unable to delete gauntlet run {gauntletrun_id}")
|
|
|
|
|
|
@app.post("/api/v1/stl-fix")
|
|
async def v1_stl_fix(token: str = Depends(oauth2_scheme)):
|
|
if not valid_token(token):
|
|
logging.warning(f"Bad Token: {token}")
|
|
db.close()
|
|
raise HTTPException(
|
|
status_code=401,
|
|
detail="You are not authorized to post. This event has been logged.",
|
|
)
|
|
|
|
p_query = (
|
|
Player.update(mlbclub="St Louis Cardinals", franchise="Cardinals")
|
|
.where(Player.mlbclub == "St. Louis Cardinals")
|
|
.execute()
|
|
)
|
|
db.close()
|
|
|
|
return {"detail": f"Removed the period from St Louis"}
|
|
|
|
|
|
@app.get("/api/v1/ratings/batter/{sba_id}")
|
|
async def v1_ratings_batter_get(
|
|
sba_id: int,
|
|
cardset_name: Optional[str] = None,
|
|
vs_hand: Literal["l", "r", "L", "R"] = None,
|
|
):
|
|
this_player = ScoutPlayer.get_or_none(ScoutPlayer.sba_id == sba_id)
|
|
logging.info(f"num players: {ScoutPlayer.select().count()}")
|
|
if this_player is None:
|
|
scout_db.close()
|
|
raise HTTPException(status_code=404, detail=f"SBa ID {sba_id} not found")
|
|
|
|
r_query = BatterRatings.select().where(
|
|
(BatterRatings.player == this_player) & (BatterRatings.is_prep == 0)
|
|
)
|
|
|
|
if cardset_name is not None:
|
|
this_cardset = ScoutCardset.get_or_none(
|
|
fn.Lower(ScoutCardset.set_title) == cardset_name.lower()
|
|
)
|
|
r_query = r_query.where(BatterRatings.cardset == this_cardset)
|
|
if vs_hand is not None:
|
|
r_query = r_query.where(
|
|
fn.Lower(BatterRatings.vs_hand) == f"v{vs_hand.lower()}"
|
|
)
|
|
|
|
return_val = {
|
|
"count": r_query.count(),
|
|
"ratings": [model_to_dict(x) for x in r_query],
|
|
}
|
|
|
|
scout_db.close()
|
|
return return_val
|