fix: standardize all collection POST routes to use trailing slash #61
@ -4,15 +4,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, Award, Team, Player, Manager, model_to_dict, chunked, fn
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/awards',
|
||||
tags=['awards']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/awards", tags=["awards"])
|
||||
|
||||
|
||||
class AwardModel(pydantic.BaseModel):
|
||||
name: str
|
||||
@ -30,13 +32,18 @@ class AwardList(pydantic.BaseModel):
|
||||
awards: List[AwardModel]
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_awards(
|
||||
name: list = Query(default=None), season: Optional[int] = None, timing: Optional[str] = None,
|
||||
manager_id: list = Query(default=None), player_id: list = Query(default=None),
|
||||
team_id: list = Query(default=None), short_output: Optional[bool] = False,
|
||||
player_name: list = Query(default=None)):
|
||||
name: list = Query(default=None),
|
||||
season: Optional[int] = None,
|
||||
timing: Optional[str] = None,
|
||||
manager_id: list = Query(default=None),
|
||||
player_id: list = Query(default=None),
|
||||
team_id: list = Query(default=None),
|
||||
short_output: Optional[bool] = False,
|
||||
player_name: list = Query(default=None),
|
||||
):
|
||||
all_awards = Award.select()
|
||||
|
||||
if name is not None:
|
||||
@ -61,39 +68,47 @@ async def get_awards(
|
||||
all_awards = all_awards.where(Award.player << all_players)
|
||||
|
||||
return_awards = {
|
||||
'count': all_awards.count(),
|
||||
'awards': [model_to_dict(x, recurse=not short_output) for x in all_awards]
|
||||
"count": all_awards.count(),
|
||||
"awards": [model_to_dict(x, recurse=not short_output) for x in all_awards],
|
||||
}
|
||||
db.close()
|
||||
return return_awards
|
||||
|
||||
|
||||
@router.get('/{award_id}')
|
||||
@router.get("/{award_id}")
|
||||
@handle_db_errors
|
||||
async def get_one_award(award_id: int, short_output: Optional[bool] = False):
|
||||
this_award = Award.get_or_none(Award.id == award_id)
|
||||
if this_award is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Award ID {award_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Award ID {award_id} not found")
|
||||
|
||||
db.close()
|
||||
return model_to_dict(this_award, recurse=not short_output)
|
||||
|
||||
|
||||
@router.patch('/{award_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{award_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_award(
|
||||
award_id: int, name: Optional[str] = None, season: Optional[int] = None, timing: Optional[str] = None,
|
||||
image: Optional[str] = None, manager1_id: Optional[int] = None, manager2_id: Optional[int] = None,
|
||||
player_id: Optional[int] = None, team_id: Optional[int] = None, token: str = Depends(oauth2_scheme)):
|
||||
award_id: int,
|
||||
name: Optional[str] = None,
|
||||
season: Optional[int] = None,
|
||||
timing: Optional[str] = None,
|
||||
image: Optional[str] = None,
|
||||
manager1_id: Optional[int] = None,
|
||||
manager2_id: Optional[int] = None,
|
||||
player_id: Optional[int] = None,
|
||||
team_id: Optional[int] = None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_player - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_player - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_award = Award.get_or_none(Award.id == award_id)
|
||||
if this_award is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Award ID {award_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Award ID {award_id} not found")
|
||||
|
||||
if name is not None:
|
||||
this_award.name = name
|
||||
@ -118,26 +133,43 @@ async def patch_award(
|
||||
return r_award
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to patch award {award_id}')
|
||||
raise HTTPException(status_code=500, detail=f"Unable to patch award {award_id}")
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_award(award_list: AwardList, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_player - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_player - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
new_awards = []
|
||||
for x in award_list.awards:
|
||||
if x.manager1_id is not None and Manager.get_or_none(Manager.id == x.manager1_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Manager ID {x.manager1_id} not found')
|
||||
if x.manager2_id is not None and Manager.get_or_none(Manager.id == x.manager2_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Manager ID {x.manager2_id} not found')
|
||||
if x.player_id is not None and Player.get_or_none(Player.id == x.player_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Player ID {x.player_id} not found')
|
||||
if (
|
||||
x.manager1_id is not None
|
||||
and Manager.get_or_none(Manager.id == x.manager1_id) is None
|
||||
):
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Manager ID {x.manager1_id} not found"
|
||||
)
|
||||
if (
|
||||
x.manager2_id is not None
|
||||
and Manager.get_or_none(Manager.id == x.manager2_id) is None
|
||||
):
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Manager ID {x.manager2_id} not found"
|
||||
)
|
||||
if (
|
||||
x.player_id is not None
|
||||
and Player.get_or_none(Player.id == x.player_id) is None
|
||||
):
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Player ID {x.player_id} not found"
|
||||
)
|
||||
if x.team_id is not None and Team.get_or_none(Team.id == x.team_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Team ID {x.team_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Team ID {x.team_id} not found"
|
||||
)
|
||||
|
||||
new_awards.append(x.dict())
|
||||
|
||||
@ -146,29 +178,27 @@ async def post_award(award_list: AwardList, token: str = Depends(oauth2_scheme))
|
||||
Award.insert_many(batch).on_conflict_ignore().execute()
|
||||
db.close()
|
||||
|
||||
return f'Inserted {len(new_awards)} awards'
|
||||
return f"Inserted {len(new_awards)} awards"
|
||||
|
||||
|
||||
@router.delete('/{award_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{award_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_award(award_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_player - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_player - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_award = Award.get_or_none(Award.id == award_id)
|
||||
if this_award is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Award ID {award_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Award ID {award_id} not found")
|
||||
|
||||
count = this_award.delete_instance()
|
||||
db.close()
|
||||
|
||||
if count == 1:
|
||||
return f'Award {award_id} has been deleted'
|
||||
return f"Award {award_id} has been deleted"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'Award {award_id} could not be deleted')
|
||||
|
||||
|
||||
|
||||
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Award {award_id} could not be deleted"
|
||||
)
|
||||
|
||||
@ -3,15 +3,27 @@ from typing import List, Optional, Literal
|
||||
import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, BattingStat, Team, Player, Current, model_to_dict, chunked, fn, per_season_weeks
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/battingstats',
|
||||
tags=['battingstats']
|
||||
from ..db_engine import (
|
||||
db,
|
||||
BattingStat,
|
||||
Team,
|
||||
Player,
|
||||
Current,
|
||||
model_to_dict,
|
||||
chunked,
|
||||
fn,
|
||||
per_season_weeks,
|
||||
)
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/battingstats", tags=["battingstats"])
|
||||
|
||||
|
||||
class BatStatModel(pydantic.BaseModel):
|
||||
@ -60,29 +72,37 @@ class BatStatList(pydantic.BaseModel):
|
||||
stats: List[BatStatModel]
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_batstats(
|
||||
season: int, s_type: Optional[str] = 'regular', team_abbrev: list = Query(default=None),
|
||||
player_name: list = Query(default=None), player_id: list = Query(default=None),
|
||||
week_start: Optional[int] = None, week_end: Optional[int] = None, game_num: list = Query(default=None),
|
||||
position: list = Query(default=None), limit: Optional[int] = None, sort: Optional[str] = None,
|
||||
short_output: Optional[bool] = True):
|
||||
if 'post' in s_type.lower():
|
||||
season: int,
|
||||
s_type: Optional[str] = "regular",
|
||||
team_abbrev: list = Query(default=None),
|
||||
player_name: list = Query(default=None),
|
||||
player_id: list = Query(default=None),
|
||||
week_start: Optional[int] = None,
|
||||
week_end: Optional[int] = None,
|
||||
game_num: list = Query(default=None),
|
||||
position: list = Query(default=None),
|
||||
limit: Optional[int] = None,
|
||||
sort: Optional[str] = None,
|
||||
short_output: Optional[bool] = True,
|
||||
):
|
||||
if "post" in s_type.lower():
|
||||
all_stats = BattingStat.post_season(season)
|
||||
if all_stats.count() == 0:
|
||||
db.close()
|
||||
return {'count': 0, 'stats': []}
|
||||
elif s_type.lower() in ['combined', 'total', 'all']:
|
||||
return {"count": 0, "stats": []}
|
||||
elif s_type.lower() in ["combined", "total", "all"]:
|
||||
all_stats = BattingStat.combined_season(season)
|
||||
if all_stats.count() == 0:
|
||||
db.close()
|
||||
return {'count': 0, 'stats': []}
|
||||
return {"count": 0, "stats": []}
|
||||
else:
|
||||
all_stats = BattingStat.regular_season(season)
|
||||
if all_stats.count() == 0:
|
||||
db.close()
|
||||
return {'count': 0, 'stats': []}
|
||||
return {"count": 0, "stats": []}
|
||||
|
||||
if position is not None:
|
||||
all_stats = all_stats.where(BattingStat.pos << [x.upper() for x in position])
|
||||
@ -93,7 +113,9 @@ async def get_batstats(
|
||||
if player_id:
|
||||
all_stats = all_stats.where(BattingStat.player_id << player_id)
|
||||
else:
|
||||
p_query = Player.select_season(season).where(fn.Lower(Player.name) << [x.lower() for x in player_name])
|
||||
p_query = Player.select_season(season).where(
|
||||
fn.Lower(Player.name) << [x.lower() for x in player_name]
|
||||
)
|
||||
all_stats = all_stats.where(BattingStat.player << p_query)
|
||||
if game_num:
|
||||
all_stats = all_stats.where(BattingStat.game == game_num)
|
||||
@ -108,21 +130,19 @@ async def get_batstats(
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail=f'Start week {start} is after end week {end} - cannot pull stats'
|
||||
)
|
||||
all_stats = all_stats.where(
|
||||
(BattingStat.week >= start) & (BattingStat.week <= end)
|
||||
detail=f"Start week {start} is after end week {end} - cannot pull stats",
|
||||
)
|
||||
all_stats = all_stats.where((BattingStat.week >= start) & (BattingStat.week <= end))
|
||||
|
||||
if limit:
|
||||
all_stats = all_stats.limit(limit)
|
||||
if sort:
|
||||
if sort == 'newest':
|
||||
if sort == "newest":
|
||||
all_stats = all_stats.order_by(-BattingStat.week, -BattingStat.game)
|
||||
|
||||
return_stats = {
|
||||
'count': all_stats.count(),
|
||||
'stats': [model_to_dict(x, recurse=not short_output) for x in all_stats],
|
||||
"count": all_stats.count(),
|
||||
"stats": [model_to_dict(x, recurse=not short_output) for x in all_stats],
|
||||
# 'stats': [{'id': x.id} for x in all_stats]
|
||||
}
|
||||
|
||||
@ -130,50 +150,80 @@ async def get_batstats(
|
||||
return return_stats
|
||||
|
||||
|
||||
@router.get('/totals')
|
||||
@router.get("/totals")
|
||||
@handle_db_errors
|
||||
async def get_totalstats(
|
||||
season: int, s_type: Literal['regular', 'post', 'total', None] = None, team_abbrev: list = Query(default=None),
|
||||
team_id: list = Query(default=None), player_name: list = Query(default=None),
|
||||
week_start: Optional[int] = None, week_end: Optional[int] = None, game_num: list = Query(default=None),
|
||||
position: list = Query(default=None), sort: Optional[str] = None, player_id: list = Query(default=None),
|
||||
group_by: Literal['team', 'player', 'playerteam'] = 'player', short_output: Optional[bool] = False,
|
||||
min_pa: Optional[int] = 1, week: list = Query(default=None)):
|
||||
season: int,
|
||||
s_type: Literal["regular", "post", "total", None] = None,
|
||||
team_abbrev: list = Query(default=None),
|
||||
team_id: list = Query(default=None),
|
||||
player_name: list = Query(default=None),
|
||||
week_start: Optional[int] = None,
|
||||
week_end: Optional[int] = None,
|
||||
game_num: list = Query(default=None),
|
||||
position: list = Query(default=None),
|
||||
sort: Optional[str] = None,
|
||||
player_id: list = Query(default=None),
|
||||
group_by: Literal["team", "player", "playerteam"] = "player",
|
||||
short_output: Optional[bool] = False,
|
||||
min_pa: Optional[int] = 1,
|
||||
week: list = Query(default=None),
|
||||
):
|
||||
if sum(1 for x in [s_type, (week_start or week_end), week] if x is not None) > 1:
|
||||
raise HTTPException(status_code=400, detail=f'Only one of s_type, week_start/week_end, or week may be used.')
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Only one of s_type, week_start/week_end, or week may be used.",
|
||||
)
|
||||
|
||||
# Build SELECT fields conditionally based on group_by to match GROUP BY exactly
|
||||
select_fields = []
|
||||
|
||||
if group_by == 'player':
|
||||
if group_by == "player":
|
||||
select_fields = [BattingStat.player]
|
||||
elif group_by == 'team':
|
||||
elif group_by == "team":
|
||||
select_fields = [BattingStat.team]
|
||||
elif group_by == 'playerteam':
|
||||
elif group_by == "playerteam":
|
||||
select_fields = [BattingStat.player, BattingStat.team]
|
||||
else:
|
||||
# Default case
|
||||
select_fields = [BattingStat.player]
|
||||
|
||||
all_stats = (
|
||||
BattingStat
|
||||
.select(*select_fields,
|
||||
fn.SUM(BattingStat.pa).alias('sum_pa'), fn.SUM(BattingStat.ab).alias('sum_ab'),
|
||||
fn.SUM(BattingStat.run).alias('sum_run'), 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.so).alias('sum_so'),
|
||||
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'),
|
||||
fn.SUM(BattingStat.xba).alias('sum_xba'), fn.SUM(BattingStat.xbt).alias('sum_xbt'),
|
||||
fn.SUM(BattingStat.xch).alias('sum_xch'), fn.SUM(BattingStat.xhit).alias('sum_xhit'),
|
||||
fn.SUM(BattingStat.error).alias('sum_error'), fn.SUM(BattingStat.pb).alias('sum_pb'),
|
||||
fn.SUM(BattingStat.sbc).alias('sum_sbc'), fn.SUM(BattingStat.csc).alias('sum_csc'),
|
||||
fn.SUM(BattingStat.roba).alias('sum_roba'), fn.SUM(BattingStat.robs).alias('sum_robs'),
|
||||
fn.SUM(BattingStat.raa).alias('sum_raa'), fn.SUM(BattingStat.rto).alias('sum_rto'))
|
||||
BattingStat.select(
|
||||
*select_fields,
|
||||
fn.SUM(BattingStat.pa).alias("sum_pa"),
|
||||
fn.SUM(BattingStat.ab).alias("sum_ab"),
|
||||
fn.SUM(BattingStat.run).alias("sum_run"),
|
||||
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.so).alias("sum_so"),
|
||||
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"),
|
||||
fn.SUM(BattingStat.xba).alias("sum_xba"),
|
||||
fn.SUM(BattingStat.xbt).alias("sum_xbt"),
|
||||
fn.SUM(BattingStat.xch).alias("sum_xch"),
|
||||
fn.SUM(BattingStat.xhit).alias("sum_xhit"),
|
||||
fn.SUM(BattingStat.error).alias("sum_error"),
|
||||
fn.SUM(BattingStat.pb).alias("sum_pb"),
|
||||
fn.SUM(BattingStat.sbc).alias("sum_sbc"),
|
||||
fn.SUM(BattingStat.csc).alias("sum_csc"),
|
||||
fn.SUM(BattingStat.roba).alias("sum_roba"),
|
||||
fn.SUM(BattingStat.robs).alias("sum_robs"),
|
||||
fn.SUM(BattingStat.raa).alias("sum_raa"),
|
||||
fn.SUM(BattingStat.rto).alias("sum_rto"),
|
||||
)
|
||||
.where(BattingStat.season == season)
|
||||
.having(fn.SUM(BattingStat.pa) >= min_pa)
|
||||
)
|
||||
@ -185,16 +235,20 @@ async def get_totalstats(
|
||||
elif week_start is not None or week_end is not None:
|
||||
if week_start is None or week_end is None:
|
||||
raise HTTPException(
|
||||
status_code=400, detail='Both week_start and week_end must be included if either is used.'
|
||||
status_code=400,
|
||||
detail="Both week_start and week_end must be included if either is used.",
|
||||
)
|
||||
weeks["start"] = week_start
|
||||
if week_end < weeks["start"]:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="week_end must be greater than or equal to week_start",
|
||||
)
|
||||
weeks['start'] = week_start
|
||||
if week_end < weeks['start']:
|
||||
raise HTTPException(status_code=400, detail='week_end must be greater than or equal to week_start')
|
||||
else:
|
||||
weeks['end'] = week_end
|
||||
weeks["end"] = week_end
|
||||
|
||||
all_stats = all_stats.where(
|
||||
(BattingStat.week >= weeks['start']) & (BattingStat.week <= weeks['end'])
|
||||
(BattingStat.week >= weeks["start"]) & (BattingStat.week <= weeks["end"])
|
||||
)
|
||||
elif week is not None:
|
||||
all_stats = all_stats.where(BattingStat.week << week)
|
||||
@ -204,14 +258,20 @@ async def get_totalstats(
|
||||
if position is not None:
|
||||
p_list = [x.upper() for x in position]
|
||||
all_players = Player.select().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)
|
||||
(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)
|
||||
)
|
||||
all_stats = all_stats.where(BattingStat.player << all_players)
|
||||
if sort is not None:
|
||||
if sort == 'player':
|
||||
if sort == "player":
|
||||
all_stats = all_stats.order_by(BattingStat.player)
|
||||
elif sort == 'team':
|
||||
elif sort == "team":
|
||||
all_stats = all_stats.order_by(BattingStat.team)
|
||||
if group_by is not None:
|
||||
# Use the same fields for GROUP BY as we used for SELECT
|
||||
@ -227,56 +287,63 @@ async def get_totalstats(
|
||||
all_teams = Team.select().where(Team.id << team_id)
|
||||
all_stats = all_stats.where(BattingStat.team << all_teams)
|
||||
elif team_abbrev is not None:
|
||||
all_teams = Team.select().where(fn.Lower(Team.abbrev) << [x.lower() for x in team_abbrev])
|
||||
all_teams = Team.select().where(
|
||||
fn.Lower(Team.abbrev) << [x.lower() for x in team_abbrev]
|
||||
)
|
||||
all_stats = all_stats.where(BattingStat.team << all_teams)
|
||||
|
||||
if player_name is not None:
|
||||
all_players = Player.select().where(fn.Lower(Player.name) << [x.lower() for x in player_name])
|
||||
all_players = Player.select().where(
|
||||
fn.Lower(Player.name) << [x.lower() for x in player_name]
|
||||
)
|
||||
all_stats = all_stats.where(BattingStat.player << all_players)
|
||||
elif player_id is not None:
|
||||
all_players = Player.select().where(Player.id << player_id)
|
||||
all_stats = all_stats.where(BattingStat.player << all_players)
|
||||
|
||||
return_stats = {
|
||||
'count': all_stats.count(),
|
||||
'stats': []
|
||||
}
|
||||
return_stats = {"count": all_stats.count(), "stats": []}
|
||||
|
||||
for x in all_stats:
|
||||
# Handle player field based on grouping with safe access
|
||||
this_player = 'TOT'
|
||||
if 'player' in group_by and hasattr(x, 'player'):
|
||||
this_player = x.player_id if short_output else model_to_dict(x.player, recurse=False)
|
||||
this_player = "TOT"
|
||||
if "player" in group_by and hasattr(x, "player"):
|
||||
this_player = (
|
||||
x.player_id if short_output else model_to_dict(x.player, recurse=False)
|
||||
)
|
||||
|
||||
# Handle team field based on grouping with safe access
|
||||
this_team = 'TOT'
|
||||
if 'team' in group_by and hasattr(x, 'team'):
|
||||
this_team = x.team_id if short_output else model_to_dict(x.team, recurse=False)
|
||||
this_team = "TOT"
|
||||
if "team" in group_by and hasattr(x, "team"):
|
||||
this_team = (
|
||||
x.team_id if short_output else model_to_dict(x.team, recurse=False)
|
||||
)
|
||||
|
||||
return_stats['stats'].append({
|
||||
'player': this_player,
|
||||
'team': this_team,
|
||||
'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
|
||||
})
|
||||
return_stats["stats"].append(
|
||||
{
|
||||
"player": this_player,
|
||||
"team": this_team,
|
||||
"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,
|
||||
}
|
||||
)
|
||||
db.close()
|
||||
return return_stats
|
||||
|
||||
@ -287,15 +354,17 @@ async def get_totalstats(
|
||||
# pass # Keep Career Stats table and recalculate after posting stats
|
||||
|
||||
|
||||
@router.patch('/{stat_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{stat_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_batstats(stat_id: int, new_stats: BatStatModel, token: str = Depends(oauth2_scheme)):
|
||||
async def patch_batstats(
|
||||
stat_id: int, new_stats: BatStatModel, token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_batstats - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_batstats - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
if BattingStat.get_or_none(BattingStat.id == stat_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Stat ID {stat_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Stat ID {stat_id} not found")
|
||||
|
||||
BattingStat.update(**new_stats.dict()).where(BattingStat.id == stat_id).execute()
|
||||
r_stat = model_to_dict(BattingStat.get_by_id(stat_id))
|
||||
@ -303,12 +372,12 @@ async def patch_batstats(stat_id: int, new_stats: BatStatModel, token: str = Dep
|
||||
return r_stat
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_batstats(s_list: BatStatList, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_batstats - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_batstats - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
all_stats = []
|
||||
|
||||
@ -316,9 +385,13 @@ async def post_batstats(s_list: BatStatList, token: str = Depends(oauth2_scheme)
|
||||
team = Team.get_or_none(Team.id == x.team_id)
|
||||
this_player = Player.get_or_none(Player.id == x.player_id)
|
||||
if team is None:
|
||||
raise HTTPException(status_code=404, detail=f'Team ID {x.team_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Team ID {x.team_id} not found"
|
||||
)
|
||||
if this_player is None:
|
||||
raise HTTPException(status_code=404, detail=f'Player ID {x.player_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Player ID {x.player_id} not found"
|
||||
)
|
||||
|
||||
all_stats.append(BattingStat(**x.dict()))
|
||||
|
||||
@ -329,4 +402,4 @@ async def post_batstats(s_list: BatStatList, token: str = Depends(oauth2_scheme)
|
||||
# Update career stats
|
||||
|
||||
db.close()
|
||||
return f'Added {len(all_stats)} batting lines'
|
||||
return f"Added {len(all_stats)} batting lines"
|
||||
|
||||
@ -4,15 +4,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, Current, model_to_dict
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/current',
|
||||
tags=['current']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/current", tags=["current"])
|
||||
|
||||
|
||||
class CurrentModel(pydantic.BaseModel):
|
||||
week: Optional[int] = 0
|
||||
@ -29,7 +31,7 @@ class CurrentModel(pydantic.BaseModel):
|
||||
injury_count: Optional[int] = 0
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_current(season: Optional[int] = None):
|
||||
if season is not None:
|
||||
@ -45,21 +47,33 @@ async def get_current(season: Optional[int] = None):
|
||||
return None
|
||||
|
||||
|
||||
@router.patch('/{current_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{current_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_current(
|
||||
current_id: int, season: Optional[int] = None, week: Optional[int] = None, freeze: Optional[bool] = None,
|
||||
transcount: Optional[int] = None, bstatcount: Optional[int] = None, pstatcount: Optional[int] = None,
|
||||
bet_week: Optional[int] = None, trade_deadline: Optional[int] = None, pick_trade_start: Optional[int] = None,
|
||||
pick_trade_end: Optional[int] = None, injury_count: Optional[int] = None, token: str = Depends(oauth2_scheme)):
|
||||
current_id: int,
|
||||
season: Optional[int] = None,
|
||||
week: Optional[int] = None,
|
||||
freeze: Optional[bool] = None,
|
||||
transcount: Optional[int] = None,
|
||||
bstatcount: Optional[int] = None,
|
||||
pstatcount: Optional[int] = None,
|
||||
bet_week: Optional[int] = None,
|
||||
trade_deadline: Optional[int] = None,
|
||||
pick_trade_start: Optional[int] = None,
|
||||
pick_trade_end: Optional[int] = None,
|
||||
injury_count: Optional[int] = None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_current - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_current - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
try:
|
||||
current = Current.get_by_id(current_id)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=404, detail=f'Current id {current_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Current id {current_id} not found"
|
||||
)
|
||||
|
||||
if week is not None:
|
||||
current.week = week
|
||||
@ -90,15 +104,17 @@ async def patch_current(
|
||||
return r_curr
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to patch current {current_id}')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to patch current {current_id}"
|
||||
)
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_current(new_current: CurrentModel, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_current - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_current - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_current = Current(**new_current.dict())
|
||||
|
||||
@ -108,17 +124,22 @@ async def post_current(new_current: CurrentModel, token: str = Depends(oauth2_sc
|
||||
return r_curr
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to post season {new_current.season} current')
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"Unable to post season {new_current.season} current",
|
||||
)
|
||||
|
||||
|
||||
@router.delete('/{current_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{current_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_current(current_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_current - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_current - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
if Current.delete_by_id(current_id) == 1:
|
||||
return f'Deleted current ID {current_id}'
|
||||
return f"Deleted current ID {current_id}"
|
||||
|
||||
raise HTTPException(status_code=500, detail=f'Unable to delete current {current_id}')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to delete current {current_id}"
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -4,15 +4,26 @@ import copy
|
||||
import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, Decision, StratGame, Player, model_to_dict, chunked, fn, Team
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/decisions',
|
||||
tags=['decisions']
|
||||
from ..db_engine import (
|
||||
db,
|
||||
Decision,
|
||||
StratGame,
|
||||
Player,
|
||||
model_to_dict,
|
||||
chunked,
|
||||
fn,
|
||||
Team,
|
||||
)
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/decisions", tags=["decisions"])
|
||||
|
||||
|
||||
class DecisionModel(pydantic.BaseModel):
|
||||
@ -43,17 +54,31 @@ class DecisionReturnList(pydantic.BaseModel):
|
||||
decisions: list[DecisionModel]
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_decisions(
|
||||
season: list = Query(default=None), week: list = Query(default=None), game_num: list = Query(default=None),
|
||||
s_type: Literal['regular', 'post', 'all', None] = None, team_id: list = Query(default=None),
|
||||
week_start: Optional[int] = None, week_end: Optional[int] = None, win: Optional[int] = None,
|
||||
loss: Optional[int] = None, hold: Optional[int] = None, save: Optional[int] = None,
|
||||
b_save: Optional[int] = None, irunners: list = Query(default=None), irunners_scored: list = Query(default=None),
|
||||
game_id: list = Query(default=None), player_id: list = Query(default=None),
|
||||
limit: Optional[int] = None, short_output: Optional[bool] = False):
|
||||
all_dec = Decision.select().order_by(-Decision.season, -Decision.week, -Decision.game_num)
|
||||
season: list = Query(default=None),
|
||||
week: list = Query(default=None),
|
||||
game_num: list = Query(default=None),
|
||||
s_type: Literal["regular", "post", "all", None] = None,
|
||||
team_id: list = Query(default=None),
|
||||
week_start: Optional[int] = None,
|
||||
week_end: Optional[int] = None,
|
||||
win: Optional[int] = None,
|
||||
loss: Optional[int] = None,
|
||||
hold: Optional[int] = None,
|
||||
save: Optional[int] = None,
|
||||
b_save: Optional[int] = None,
|
||||
irunners: list = Query(default=None),
|
||||
irunners_scored: list = Query(default=None),
|
||||
game_id: list = Query(default=None),
|
||||
player_id: list = Query(default=None),
|
||||
limit: Optional[int] = None,
|
||||
short_output: Optional[bool] = False,
|
||||
):
|
||||
all_dec = Decision.select().order_by(
|
||||
-Decision.season, -Decision.week, -Decision.game_num
|
||||
)
|
||||
|
||||
if season is not None:
|
||||
all_dec = all_dec.where(Decision.season << season)
|
||||
@ -79,7 +104,8 @@ async def get_decisions(
|
||||
if season is not None and 8 in season or s8_teams:
|
||||
all_teams = Team.select().where(Team.id << team_id)
|
||||
all_games = StratGame.select().where(
|
||||
(StratGame.away_team << all_teams) | (StratGame.home_team << all_teams))
|
||||
(StratGame.away_team << all_teams) | (StratGame.home_team << all_teams)
|
||||
)
|
||||
all_dec = all_dec.where(Decision.game << all_games)
|
||||
else:
|
||||
all_teams = Team.select().where(Team.id << team_id)
|
||||
@ -115,28 +141,38 @@ async def get_decisions(
|
||||
all_dec = all_dec.limit(limit)
|
||||
|
||||
return_dec = {
|
||||
'count': all_dec.count(),
|
||||
'decisions': [model_to_dict(x, recurse=not short_output) for x in all_dec]
|
||||
"count": all_dec.count(),
|
||||
"decisions": [model_to_dict(x, recurse=not short_output) for x in all_dec],
|
||||
}
|
||||
db.close()
|
||||
return return_dec
|
||||
|
||||
|
||||
@router.patch('/{decision_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{decision_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_decision(
|
||||
decision_id: int, win: Optional[int] = None, loss: Optional[int] = None, hold: Optional[int] = None,
|
||||
save: Optional[int] = None, b_save: Optional[int] = None, irunners: Optional[int] = None,
|
||||
irunners_scored: Optional[int] = None, rest_ip: Optional[int] = None, rest_required: Optional[int] = None,
|
||||
token: str = Depends(oauth2_scheme)):
|
||||
decision_id: int,
|
||||
win: Optional[int] = None,
|
||||
loss: Optional[int] = None,
|
||||
hold: Optional[int] = None,
|
||||
save: Optional[int] = None,
|
||||
b_save: Optional[int] = None,
|
||||
irunners: Optional[int] = None,
|
||||
irunners_scored: Optional[int] = None,
|
||||
rest_ip: Optional[int] = None,
|
||||
rest_required: Optional[int] = None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_decision - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_decision - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_dec = Decision.get_or_none(Decision.id == decision_id)
|
||||
if this_dec is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Decision ID {decision_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Decision ID {decision_id} not found"
|
||||
)
|
||||
|
||||
if win is not None:
|
||||
this_dec.win = win
|
||||
@ -163,22 +199,28 @@ async def patch_decision(
|
||||
return d_result
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to patch decision {decision_id}')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to patch decision {decision_id}"
|
||||
)
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_decisions(dec_list: DecisionList, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_decisions - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_decisions - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
new_dec = []
|
||||
for x in dec_list.decisions:
|
||||
if StratGame.get_or_none(StratGame.id == x.game_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Game ID {x.game_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Game ID {x.game_id} not found"
|
||||
)
|
||||
if Player.get_or_none(Player.id == x.pitcher_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Player ID {x.pitcher_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Player ID {x.pitcher_id} not found"
|
||||
)
|
||||
|
||||
new_dec.append(x.dict())
|
||||
|
||||
@ -187,49 +229,53 @@ async def post_decisions(dec_list: DecisionList, token: str = Depends(oauth2_sch
|
||||
Decision.insert_many(batch).on_conflict_ignore().execute()
|
||||
db.close()
|
||||
|
||||
return f'Inserted {len(new_dec)} decisions'
|
||||
return f"Inserted {len(new_dec)} decisions"
|
||||
|
||||
|
||||
@router.delete('/{decision_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{decision_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_decision(decision_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_decision - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_decision - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_dec = Decision.get_or_none(Decision.id == decision_id)
|
||||
if this_dec is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Decision ID {decision_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Decision ID {decision_id} not found"
|
||||
)
|
||||
|
||||
count = this_dec.delete_instance()
|
||||
db.close()
|
||||
|
||||
if count == 1:
|
||||
return f'Decision {decision_id} has been deleted'
|
||||
return f"Decision {decision_id} has been deleted"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'Decision {decision_id} could not be deleted')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Decision {decision_id} could not be deleted"
|
||||
)
|
||||
|
||||
|
||||
@router.delete('/game/{game_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/game/{game_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_decisions_game(game_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_decisions_game - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_decisions_game - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_game = StratGame.get_or_none(StratGame.id == game_id)
|
||||
if not this_game:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Game ID {game_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Game ID {game_id} not found")
|
||||
|
||||
count = Decision.delete().where(Decision.game == this_game).execute()
|
||||
db.close()
|
||||
|
||||
if count > 0:
|
||||
return f'Deleted {count} decisions matching Game ID {game_id}'
|
||||
return f"Deleted {count} decisions matching Game ID {game_id}"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'No decisions matching Game ID {game_id} were deleted')
|
||||
|
||||
|
||||
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"No decisions matching Game ID {game_id} were deleted",
|
||||
)
|
||||
|
||||
@ -4,15 +4,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, Division, Team, model_to_dict, chunked, fn
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/divisions',
|
||||
tags=['divisions']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/divisions", tags=["divisions"])
|
||||
|
||||
|
||||
class DivisionModel(pydantic.BaseModel):
|
||||
division_name: str
|
||||
@ -22,11 +24,15 @@ class DivisionModel(pydantic.BaseModel):
|
||||
season: int = 0
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_divisions(
|
||||
season: int, div_name: Optional[str] = None, div_abbrev: Optional[str] = None, lg_name: Optional[str] = None,
|
||||
lg_abbrev: Optional[str] = None):
|
||||
season: int,
|
||||
div_name: Optional[str] = None,
|
||||
div_abbrev: Optional[str] = None,
|
||||
lg_name: Optional[str] = None,
|
||||
lg_abbrev: Optional[str] = None,
|
||||
):
|
||||
all_divisions = Division.select().where(Division.season == season)
|
||||
|
||||
if div_name is not None:
|
||||
@ -39,39 +45,48 @@ async def get_divisions(
|
||||
all_divisions = all_divisions.where(Division.league_abbrev == lg_abbrev)
|
||||
|
||||
return_div = {
|
||||
'count': all_divisions.count(),
|
||||
'divisions': [model_to_dict(x) for x in all_divisions]
|
||||
"count": all_divisions.count(),
|
||||
"divisions": [model_to_dict(x) for x in all_divisions],
|
||||
}
|
||||
db.close()
|
||||
return return_div
|
||||
|
||||
|
||||
@router.get('/{division_id}')
|
||||
@router.get("/{division_id}")
|
||||
@handle_db_errors
|
||||
async def get_one_division(division_id: int):
|
||||
this_div = Division.get_or_none(Division.id == division_id)
|
||||
if this_div is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Division ID {division_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Division ID {division_id} not found"
|
||||
)
|
||||
|
||||
r_div = model_to_dict(this_div)
|
||||
db.close()
|
||||
return r_div
|
||||
|
||||
|
||||
@router.patch('/{division_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{division_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_division(
|
||||
division_id: int, div_name: Optional[str] = None, div_abbrev: Optional[str] = None,
|
||||
lg_name: Optional[str] = None, lg_abbrev: Optional[str] = None, token: str = Depends(oauth2_scheme)):
|
||||
division_id: int,
|
||||
div_name: Optional[str] = None,
|
||||
div_abbrev: Optional[str] = None,
|
||||
lg_name: Optional[str] = None,
|
||||
lg_abbrev: Optional[str] = None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_division - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_division - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_div = Division.get_or_none(Division.id == division_id)
|
||||
if this_div is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Division ID {division_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Division ID {division_id} not found"
|
||||
)
|
||||
|
||||
if div_name is not None:
|
||||
this_div.division_name = div_name
|
||||
@ -88,15 +103,19 @@ async def patch_division(
|
||||
return r_division
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to patch division {division_id}')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to patch division {division_id}"
|
||||
)
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_division(new_division: DivisionModel, token: str = Depends(oauth2_scheme)):
|
||||
async def post_division(
|
||||
new_division: DivisionModel, token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_division - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_division - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_division = Division(**new_division.dict())
|
||||
|
||||
@ -106,27 +125,29 @@ async def post_division(new_division: DivisionModel, token: str = Depends(oauth2
|
||||
return r_division
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to post division')
|
||||
raise HTTPException(status_code=500, detail=f"Unable to post division")
|
||||
|
||||
|
||||
@router.delete('/{division_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{division_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_division(division_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_division - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_division - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_div = Division.get_or_none(Division.id == division_id)
|
||||
if this_div is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Division ID {division_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Division ID {division_id} not found"
|
||||
)
|
||||
|
||||
count = this_div.delete_instance()
|
||||
db.close()
|
||||
|
||||
if count == 1:
|
||||
return f'Division {division_id} has been deleted'
|
||||
return f"Division {division_id} has been deleted"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'Division {division_id} could not be deleted')
|
||||
|
||||
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Division {division_id} could not be deleted"
|
||||
)
|
||||
|
||||
@ -4,15 +4,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, DraftList, Team, model_to_dict, chunked
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/draftlist',
|
||||
tags=['draftlist']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/draftlist", tags=["draftlist"])
|
||||
|
||||
|
||||
class DraftListModel(pydantic.BaseModel):
|
||||
season: int
|
||||
@ -26,13 +28,16 @@ class DraftListList(pydantic.BaseModel):
|
||||
draft_list: List[DraftListModel]
|
||||
|
||||
|
||||
@router.get('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.get("", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def get_draftlist(
|
||||
season: Optional[int], team_id: list = Query(default=None), token: str = Depends(oauth2_scheme)):
|
||||
season: Optional[int],
|
||||
team_id: list = Query(default=None),
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'get_draftlist - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"get_draftlist - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
all_list = DraftList.select()
|
||||
|
||||
@ -41,47 +46,49 @@ async def get_draftlist(
|
||||
if team_id is not None:
|
||||
all_list = all_list.where(DraftList.team_id << team_id)
|
||||
|
||||
r_list = {
|
||||
'count': all_list.count(),
|
||||
'picks': [model_to_dict(x) for x in all_list]
|
||||
}
|
||||
r_list = {"count": all_list.count(), "picks": [model_to_dict(x) for x in all_list]}
|
||||
|
||||
db.close()
|
||||
return r_list
|
||||
|
||||
|
||||
@router.get('/team/{team_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.get("/team/{team_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def get_team_draftlist(team_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_draftlist - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_draftlist - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_team = Team.get_or_none(Team.id == team_id)
|
||||
if this_team is None:
|
||||
raise HTTPException(status_code=404, detail=f'Team ID {team_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Team ID {team_id} not found")
|
||||
|
||||
this_list = DraftList.select().where(DraftList.team == this_team)
|
||||
r_list = {
|
||||
'count': this_list.count(),
|
||||
'picks': [model_to_dict(x) for x in this_list]
|
||||
"count": this_list.count(),
|
||||
"picks": [model_to_dict(x) for x in this_list],
|
||||
}
|
||||
|
||||
db.close()
|
||||
return r_list
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_draftlist(draft_list: DraftListList, token: str = Depends(oauth2_scheme)):
|
||||
async def post_draftlist(
|
||||
draft_list: DraftListList, token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_draftlist - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_draftlist - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
new_list = []
|
||||
this_team = Team.get_or_none(Team.id == draft_list.draft_list[0].team_id)
|
||||
if this_team is None:
|
||||
raise HTTPException(status_code=404, detail=f'Team ID {draft_list.draft_list[0].team_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail=f"Team ID {draft_list.draft_list[0].team_id} not found",
|
||||
)
|
||||
|
||||
DraftList.delete().where(DraftList.team == this_team).execute()
|
||||
|
||||
@ -93,16 +100,16 @@ async def post_draftlist(draft_list: DraftListList, token: str = Depends(oauth2_
|
||||
DraftList.insert_many(batch).on_conflict_ignore().execute()
|
||||
|
||||
db.close()
|
||||
return f'Inserted {len(new_list)} list values'
|
||||
return f"Inserted {len(new_list)} list values"
|
||||
|
||||
|
||||
@router.delete('/team/{team_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/team/{team_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_draftlist(team_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_draftlist - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_draftlist - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
count = DraftList.delete().where(DraftList.team_id == team_id).execute()
|
||||
db.close()
|
||||
return f'Deleted {count} list values'
|
||||
return f"Deleted {count} list values"
|
||||
|
||||
@ -4,15 +4,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, DraftPick, Team, model_to_dict, chunked
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/draftpicks',
|
||||
tags=['draftpicks']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/draftpicks", tags=["draftpicks"])
|
||||
|
||||
|
||||
class DraftPickModel(pydantic.BaseModel):
|
||||
overall: Optional[int] = None
|
||||
@ -32,15 +34,26 @@ class DraftPickReturnList(pydantic.BaseModel):
|
||||
picks: list[DraftPickModel]
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_picks(
|
||||
season: int, owner_team_abbrev: list = Query(default=None), orig_team_abbrev: list = Query(default=None),
|
||||
owner_team_id: list = Query(default=None), orig_team_id: list = Query(default=None),
|
||||
pick_round_start: Optional[int] = None, pick_round_end: Optional[int] = None, traded: Optional[bool] = None,
|
||||
overall: Optional[int] = None, overall_start: Optional[int] = None, overall_end: Optional[int] = None,
|
||||
short_output: Optional[bool] = False, sort: Optional[str] = None, limit: Optional[int] = None,
|
||||
player_id: list = Query(default=None), player_taken: Optional[bool] = None):
|
||||
season: int,
|
||||
owner_team_abbrev: list = Query(default=None),
|
||||
orig_team_abbrev: list = Query(default=None),
|
||||
owner_team_id: list = Query(default=None),
|
||||
orig_team_id: list = Query(default=None),
|
||||
pick_round_start: Optional[int] = None,
|
||||
pick_round_end: Optional[int] = None,
|
||||
traded: Optional[bool] = None,
|
||||
overall: Optional[int] = None,
|
||||
overall_start: Optional[int] = None,
|
||||
overall_end: Optional[int] = None,
|
||||
short_output: Optional[bool] = False,
|
||||
sort: Optional[str] = None,
|
||||
limit: Optional[int] = None,
|
||||
player_id: list = Query(default=None),
|
||||
player_taken: Optional[bool] = None,
|
||||
):
|
||||
all_picks = DraftPick.select().where(DraftPick.season == season)
|
||||
|
||||
if owner_team_abbrev is not None:
|
||||
@ -61,16 +74,25 @@ async def get_picks(
|
||||
|
||||
if owner_team_id is not None:
|
||||
all_picks = all_picks.where(
|
||||
(DraftPick.owner_id << owner_team_id) | (DraftPick.owner_id << owner_team_id)
|
||||
(DraftPick.owner_id << owner_team_id)
|
||||
| (DraftPick.owner_id << owner_team_id)
|
||||
)
|
||||
|
||||
if orig_team_id is not None:
|
||||
all_picks = all_picks.where(
|
||||
(DraftPick.origowner_id << orig_team_id) | (DraftPick.origowner_id << orig_team_id)
|
||||
(DraftPick.origowner_id << orig_team_id)
|
||||
| (DraftPick.origowner_id << orig_team_id)
|
||||
)
|
||||
|
||||
if pick_round_start is not None and pick_round_end is not None and pick_round_end < pick_round_start:
|
||||
raise HTTPException(status_code=400, detail=f'pick_round_end must be greater than or equal to pick_round_start')
|
||||
if (
|
||||
pick_round_start is not None
|
||||
and pick_round_end is not None
|
||||
and pick_round_end < pick_round_start
|
||||
):
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"pick_round_end must be greater than or equal to pick_round_start",
|
||||
)
|
||||
|
||||
if player_id is not None:
|
||||
all_picks = all_picks.where(DraftPick.player_id << player_id)
|
||||
@ -92,40 +114,42 @@ async def get_picks(
|
||||
all_picks = all_picks.limit(limit)
|
||||
|
||||
if sort is not None:
|
||||
if sort == 'order-asc':
|
||||
if sort == "order-asc":
|
||||
all_picks = all_picks.order_by(DraftPick.overall)
|
||||
elif sort == 'order-desc':
|
||||
elif sort == "order-desc":
|
||||
all_picks = all_picks.order_by(-DraftPick.overall)
|
||||
|
||||
return_picks = {'count': all_picks.count(), 'picks': []}
|
||||
return_picks = {"count": all_picks.count(), "picks": []}
|
||||
for line in all_picks:
|
||||
return_picks['picks'].append(model_to_dict(line, recurse=not short_output))
|
||||
return_picks["picks"].append(model_to_dict(line, recurse=not short_output))
|
||||
|
||||
db.close()
|
||||
return return_picks
|
||||
|
||||
|
||||
@router.get('/{pick_id}')
|
||||
@router.get("/{pick_id}")
|
||||
@handle_db_errors
|
||||
async def get_one_pick(pick_id: int, short_output: Optional[bool] = False):
|
||||
this_pick = DraftPick.get_or_none(DraftPick.id == pick_id)
|
||||
if this_pick is not None:
|
||||
r_pick = model_to_dict(this_pick, recurse=not short_output)
|
||||
else:
|
||||
raise HTTPException(status_code=404, detail=f'Pick ID {pick_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Pick ID {pick_id} not found")
|
||||
db.close()
|
||||
return r_pick
|
||||
|
||||
|
||||
@router.patch('/{pick_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{pick_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_pick(pick_id: int, new_pick: DraftPickModel, token: str = Depends(oauth2_scheme)):
|
||||
async def patch_pick(
|
||||
pick_id: int, new_pick: DraftPickModel, token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_pick - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_pick - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
if DraftPick.get_or_none(DraftPick.id == pick_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Pick ID {pick_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Pick ID {pick_id} not found")
|
||||
|
||||
DraftPick.update(**new_pick.dict()).where(DraftPick.id == pick_id).execute()
|
||||
r_pick = model_to_dict(DraftPick.get_by_id(pick_id))
|
||||
@ -133,21 +157,23 @@ async def patch_pick(pick_id: int, new_pick: DraftPickModel, token: str = Depend
|
||||
return r_pick
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_picks(p_list: DraftPickList, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_picks - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_picks - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
new_picks = []
|
||||
for pick in p_list.picks:
|
||||
dupe = DraftPick.get_or_none(DraftPick.season == pick.season, DraftPick.overall == pick.overall)
|
||||
dupe = DraftPick.get_or_none(
|
||||
DraftPick.season == pick.season, DraftPick.overall == pick.overall
|
||||
)
|
||||
if dupe:
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f'Pick # {pick.overall} already exists for season {pick.season}'
|
||||
detail=f"Pick # {pick.overall} already exists for season {pick.season}",
|
||||
)
|
||||
|
||||
new_picks.append(pick.dict())
|
||||
@ -157,25 +183,26 @@ async def post_picks(p_list: DraftPickList, token: str = Depends(oauth2_scheme))
|
||||
DraftPick.insert_many(batch).on_conflict_ignore().execute()
|
||||
db.close()
|
||||
|
||||
return f'Inserted {len(new_picks)} picks'
|
||||
return f"Inserted {len(new_picks)} picks"
|
||||
|
||||
|
||||
@router.delete('/{pick_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{pick_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_pick(pick_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_pick - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_pick - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_pick = DraftPick.get_or_none(DraftPick.id == pick_id)
|
||||
if this_pick is None:
|
||||
raise HTTPException(status_code=404, detail=f'Pick ID {pick_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Pick ID {pick_id} not found")
|
||||
|
||||
count = this_pick.delete_instance()
|
||||
db.close()
|
||||
|
||||
if count == 1:
|
||||
return f'Draft pick {pick_id} has been deleted'
|
||||
return f"Draft pick {pick_id} has been deleted"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'Draft pick {pick_id} could not be deleted')
|
||||
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Draft pick {pick_id} could not be deleted"
|
||||
)
|
||||
|
||||
@ -6,15 +6,17 @@ from pydantic import BaseModel, Field
|
||||
from playhouse.shortcuts import model_to_dict
|
||||
from peewee import fn
|
||||
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
from ..db_engine import db, HelpCommand
|
||||
|
||||
logger = logging.getLogger('database_api')
|
||||
logger = logging.getLogger("database_api")
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/help_commands',
|
||||
tags=['help_commands']
|
||||
)
|
||||
router = APIRouter(prefix="/api/v3/help_commands", tags=["help_commands"])
|
||||
|
||||
|
||||
# Pydantic Models for API
|
||||
@ -52,15 +54,16 @@ class HelpCommandStatsResponse(BaseModel):
|
||||
|
||||
# API Endpoints
|
||||
|
||||
@router.get('')
|
||||
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_help_commands(
|
||||
name: Optional[str] = None,
|
||||
category: Optional[str] = None,
|
||||
is_active: Optional[bool] = True,
|
||||
sort: Optional[str] = 'name',
|
||||
sort: Optional[str] = "name",
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(25, ge=1, le=100)
|
||||
page_size: int = Query(25, ge=1, le=100),
|
||||
):
|
||||
"""Get help commands with filtering and pagination"""
|
||||
try:
|
||||
@ -82,16 +85,16 @@ async def get_help_commands(
|
||||
|
||||
# Apply sorting
|
||||
sort_mapping = {
|
||||
'name': HelpCommand.name,
|
||||
'title': HelpCommand.title,
|
||||
'category': HelpCommand.category,
|
||||
'created_at': HelpCommand.created_at,
|
||||
'updated_at': HelpCommand.updated_at,
|
||||
'view_count': HelpCommand.view_count,
|
||||
'display_order': HelpCommand.display_order
|
||||
"name": HelpCommand.name,
|
||||
"title": HelpCommand.title,
|
||||
"category": HelpCommand.category,
|
||||
"created_at": HelpCommand.created_at,
|
||||
"updated_at": HelpCommand.updated_at,
|
||||
"view_count": HelpCommand.view_count,
|
||||
"display_order": HelpCommand.display_order,
|
||||
}
|
||||
|
||||
if sort.startswith('-'):
|
||||
if sort.startswith("-"):
|
||||
sort_field = sort[1:]
|
||||
order_by = sort_mapping.get(sort_field, HelpCommand.name).desc()
|
||||
else:
|
||||
@ -111,10 +114,10 @@ async def get_help_commands(
|
||||
for help_cmd in query:
|
||||
cmd_dict = model_to_dict(help_cmd)
|
||||
# Convert datetime objects to ISO strings
|
||||
if cmd_dict.get('created_at'):
|
||||
cmd_dict['created_at'] = cmd_dict['created_at'].isoformat()
|
||||
if cmd_dict.get('updated_at'):
|
||||
cmd_dict['updated_at'] = cmd_dict['updated_at'].isoformat()
|
||||
if cmd_dict.get("created_at"):
|
||||
cmd_dict["created_at"] = cmd_dict["created_at"].isoformat()
|
||||
if cmd_dict.get("updated_at"):
|
||||
cmd_dict["updated_at"] = cmd_dict["updated_at"].isoformat()
|
||||
|
||||
try:
|
||||
command_model = HelpCommandModel(**cmd_dict)
|
||||
@ -129,7 +132,7 @@ async def get_help_commands(
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
total_pages=total_pages,
|
||||
has_more=page < total_pages
|
||||
has_more=page < total_pages,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
@ -139,22 +142,23 @@ async def get_help_commands(
|
||||
db.close()
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def create_help_command_endpoint(
|
||||
command: HelpCommandModel,
|
||||
token: str = Depends(oauth2_scheme)
|
||||
command: HelpCommandModel, token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
"""Create a new help command"""
|
||||
if not valid_token(token):
|
||||
logger.warning(f'create_help_command - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"create_help_command - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
try:
|
||||
# Check if command name already exists
|
||||
existing = HelpCommand.get_by_name(command.name)
|
||||
if existing:
|
||||
raise HTTPException(status_code=409, detail=f"Help topic '{command.name}' already exists")
|
||||
raise HTTPException(
|
||||
status_code=409, detail=f"Help topic '{command.name}' already exists"
|
||||
)
|
||||
|
||||
# Create the command
|
||||
help_cmd = HelpCommand.create(
|
||||
@ -166,15 +170,15 @@ async def create_help_command_endpoint(
|
||||
created_at=datetime.now(),
|
||||
is_active=True,
|
||||
view_count=0,
|
||||
display_order=command.display_order
|
||||
display_order=command.display_order,
|
||||
)
|
||||
|
||||
# Return the created command
|
||||
result = model_to_dict(help_cmd)
|
||||
if result.get('created_at'):
|
||||
result['created_at'] = result['created_at'].isoformat()
|
||||
if result.get('updated_at'):
|
||||
result['updated_at'] = result['updated_at'].isoformat()
|
||||
if result.get("created_at"):
|
||||
result["created_at"] = result["created_at"].isoformat()
|
||||
if result.get("updated_at"):
|
||||
result["updated_at"] = result["updated_at"].isoformat()
|
||||
|
||||
return result
|
||||
|
||||
@ -187,23 +191,23 @@ async def create_help_command_endpoint(
|
||||
db.close()
|
||||
|
||||
|
||||
@router.put('/{command_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.put("/{command_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def update_help_command_endpoint(
|
||||
command_id: int,
|
||||
command: HelpCommandModel,
|
||||
token: str = Depends(oauth2_scheme)
|
||||
command_id: int, command: HelpCommandModel, token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
"""Update an existing help command"""
|
||||
if not valid_token(token):
|
||||
logger.warning(f'update_help_command - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"update_help_command - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
try:
|
||||
# Get the command
|
||||
help_cmd = HelpCommand.get_or_none(HelpCommand.id == command_id)
|
||||
if not help_cmd:
|
||||
raise HTTPException(status_code=404, detail=f"Help command {command_id} not found")
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Help command {command_id} not found"
|
||||
)
|
||||
|
||||
# Update fields
|
||||
if command.title:
|
||||
@ -222,10 +226,10 @@ async def update_help_command_endpoint(
|
||||
|
||||
# Return updated command
|
||||
result = model_to_dict(help_cmd)
|
||||
if result.get('created_at'):
|
||||
result['created_at'] = result['created_at'].isoformat()
|
||||
if result.get('updated_at'):
|
||||
result['updated_at'] = result['updated_at'].isoformat()
|
||||
if result.get("created_at"):
|
||||
result["created_at"] = result["created_at"].isoformat()
|
||||
if result.get("updated_at"):
|
||||
result["updated_at"] = result["updated_at"].isoformat()
|
||||
|
||||
return result
|
||||
|
||||
@ -238,32 +242,33 @@ async def update_help_command_endpoint(
|
||||
db.close()
|
||||
|
||||
|
||||
@router.patch('/{command_id}/restore', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{command_id}/restore", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def restore_help_command_endpoint(
|
||||
command_id: int,
|
||||
token: str = Depends(oauth2_scheme)
|
||||
command_id: int, token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
"""Restore a soft-deleted help command"""
|
||||
if not valid_token(token):
|
||||
logger.warning(f'restore_help_command - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"restore_help_command - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
try:
|
||||
# Get the command
|
||||
help_cmd = HelpCommand.get_or_none(HelpCommand.id == command_id)
|
||||
if not help_cmd:
|
||||
raise HTTPException(status_code=404, detail=f"Help command {command_id} not found")
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Help command {command_id} not found"
|
||||
)
|
||||
|
||||
# Restore the command
|
||||
help_cmd.restore()
|
||||
|
||||
# Return restored command
|
||||
result = model_to_dict(help_cmd)
|
||||
if result.get('created_at'):
|
||||
result['created_at'] = result['created_at'].isoformat()
|
||||
if result.get('updated_at'):
|
||||
result['updated_at'] = result['updated_at'].isoformat()
|
||||
if result.get("created_at"):
|
||||
result["created_at"] = result["created_at"].isoformat()
|
||||
if result.get("updated_at"):
|
||||
result["updated_at"] = result["updated_at"].isoformat()
|
||||
|
||||
return result
|
||||
|
||||
@ -276,22 +281,23 @@ async def restore_help_command_endpoint(
|
||||
db.close()
|
||||
|
||||
|
||||
@router.delete('/{command_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{command_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_help_command_endpoint(
|
||||
command_id: int,
|
||||
token: str = Depends(oauth2_scheme)
|
||||
command_id: int, token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
"""Soft delete a help command"""
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_help_command - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_help_command - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
try:
|
||||
# Get the command
|
||||
help_cmd = HelpCommand.get_or_none(HelpCommand.id == command_id)
|
||||
if not help_cmd:
|
||||
raise HTTPException(status_code=404, detail=f"Help command {command_id} not found")
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Help command {command_id} not found"
|
||||
)
|
||||
|
||||
# Soft delete the command
|
||||
help_cmd.soft_delete()
|
||||
@ -307,44 +313,56 @@ async def delete_help_command_endpoint(
|
||||
db.close()
|
||||
|
||||
|
||||
@router.get('/stats')
|
||||
@router.get("/stats")
|
||||
@handle_db_errors
|
||||
async def get_help_command_stats():
|
||||
"""Get comprehensive statistics about help commands"""
|
||||
try:
|
||||
# Get basic counts
|
||||
total_commands = HelpCommand.select().count()
|
||||
active_commands = HelpCommand.select().where(HelpCommand.is_active == True).count()
|
||||
active_commands = (
|
||||
HelpCommand.select().where(HelpCommand.is_active == True).count()
|
||||
)
|
||||
|
||||
# Get total views
|
||||
total_views = HelpCommand.select(fn.SUM(HelpCommand.view_count)).where(
|
||||
HelpCommand.is_active == True
|
||||
).scalar() or 0
|
||||
total_views = (
|
||||
HelpCommand.select(fn.SUM(HelpCommand.view_count))
|
||||
.where(HelpCommand.is_active == True)
|
||||
.scalar()
|
||||
or 0
|
||||
)
|
||||
|
||||
# Get most viewed command
|
||||
most_viewed = HelpCommand.get_most_viewed(limit=1).first()
|
||||
most_viewed_command = None
|
||||
if most_viewed:
|
||||
most_viewed_dict = model_to_dict(most_viewed)
|
||||
if most_viewed_dict.get('created_at'):
|
||||
most_viewed_dict['created_at'] = most_viewed_dict['created_at'].isoformat()
|
||||
if most_viewed_dict.get('updated_at'):
|
||||
most_viewed_dict['updated_at'] = most_viewed_dict['updated_at'].isoformat()
|
||||
if most_viewed_dict.get("created_at"):
|
||||
most_viewed_dict["created_at"] = most_viewed_dict[
|
||||
"created_at"
|
||||
].isoformat()
|
||||
if most_viewed_dict.get("updated_at"):
|
||||
most_viewed_dict["updated_at"] = most_viewed_dict[
|
||||
"updated_at"
|
||||
].isoformat()
|
||||
most_viewed_command = most_viewed_dict
|
||||
|
||||
# Get recent commands count (last 7 days)
|
||||
week_ago = datetime.now() - timedelta(days=7)
|
||||
recent_count = HelpCommand.select().where(
|
||||
(HelpCommand.created_at >= week_ago) &
|
||||
(HelpCommand.is_active == True)
|
||||
).count()
|
||||
recent_count = (
|
||||
HelpCommand.select()
|
||||
.where(
|
||||
(HelpCommand.created_at >= week_ago) & (HelpCommand.is_active == True)
|
||||
)
|
||||
.count()
|
||||
)
|
||||
|
||||
return HelpCommandStatsResponse(
|
||||
total_commands=total_commands,
|
||||
active_commands=active_commands,
|
||||
total_views=int(total_views),
|
||||
most_viewed_command=most_viewed_command,
|
||||
recent_commands_count=recent_count
|
||||
recent_commands_count=recent_count,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
@ -355,24 +373,27 @@ async def get_help_command_stats():
|
||||
|
||||
|
||||
# Special endpoints for Discord bot integration
|
||||
@router.get('/by_name/{command_name}')
|
||||
@router.get("/by_name/{command_name}")
|
||||
@handle_db_errors
|
||||
async def get_help_command_by_name_endpoint(
|
||||
command_name: str,
|
||||
include_inactive: bool = Query(False)
|
||||
command_name: str, include_inactive: bool = Query(False)
|
||||
):
|
||||
"""Get a help command by name (for Discord bot)"""
|
||||
try:
|
||||
help_cmd = HelpCommand.get_by_name(command_name, include_inactive=include_inactive)
|
||||
help_cmd = HelpCommand.get_by_name(
|
||||
command_name, include_inactive=include_inactive
|
||||
)
|
||||
|
||||
if not help_cmd:
|
||||
raise HTTPException(status_code=404, detail=f"Help topic '{command_name}' not found")
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Help topic '{command_name}' not found"
|
||||
)
|
||||
|
||||
result = model_to_dict(help_cmd)
|
||||
if result.get('created_at'):
|
||||
result['created_at'] = result['created_at'].isoformat()
|
||||
if result.get('updated_at'):
|
||||
result['updated_at'] = result['updated_at'].isoformat()
|
||||
if result.get("created_at"):
|
||||
result["created_at"] = result["created_at"].isoformat()
|
||||
if result.get("updated_at"):
|
||||
result["updated_at"] = result["updated_at"].isoformat()
|
||||
|
||||
return result
|
||||
|
||||
@ -385,32 +406,31 @@ async def get_help_command_by_name_endpoint(
|
||||
db.close()
|
||||
|
||||
|
||||
@router.patch('/by_name/{command_name}/view', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/by_name/{command_name}/view", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def increment_view_count(
|
||||
command_name: str,
|
||||
token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
async def increment_view_count(command_name: str, token: str = Depends(oauth2_scheme)):
|
||||
"""Increment view count for a help command"""
|
||||
if not valid_token(token):
|
||||
logger.warning(f'increment_view_count - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"increment_view_count - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
try:
|
||||
help_cmd = HelpCommand.get_by_name(command_name)
|
||||
|
||||
if not help_cmd:
|
||||
raise HTTPException(status_code=404, detail=f"Help topic '{command_name}' not found")
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Help topic '{command_name}' not found"
|
||||
)
|
||||
|
||||
# Increment view count
|
||||
help_cmd.increment_view_count()
|
||||
|
||||
# Return updated command
|
||||
result = model_to_dict(help_cmd)
|
||||
if result.get('created_at'):
|
||||
result['created_at'] = result['created_at'].isoformat()
|
||||
if result.get('updated_at'):
|
||||
result['updated_at'] = result['updated_at'].isoformat()
|
||||
if result.get("created_at"):
|
||||
result["created_at"] = result["created_at"].isoformat()
|
||||
if result.get("updated_at"):
|
||||
result["updated_at"] = result["updated_at"].isoformat()
|
||||
|
||||
return result
|
||||
|
||||
@ -423,11 +443,10 @@ async def increment_view_count(
|
||||
db.close()
|
||||
|
||||
|
||||
@router.get('/autocomplete')
|
||||
@router.get("/autocomplete")
|
||||
@handle_db_errors
|
||||
async def get_help_names_for_autocomplete(
|
||||
q: str = Query(""),
|
||||
limit: int = Query(25, ge=1, le=100)
|
||||
q: str = Query(""), limit: int = Query(25, ge=1, le=100)
|
||||
):
|
||||
"""Get help command names for Discord autocomplete"""
|
||||
try:
|
||||
@ -438,11 +457,11 @@ async def get_help_names_for_autocomplete(
|
||||
|
||||
# Return list of dictionaries with name, title, category
|
||||
return {
|
||||
'results': [
|
||||
"results": [
|
||||
{
|
||||
'name': help_cmd.name,
|
||||
'title': help_cmd.title,
|
||||
'category': help_cmd.category
|
||||
"name": help_cmd.name,
|
||||
"title": help_cmd.title,
|
||||
"category": help_cmd.category,
|
||||
}
|
||||
for help_cmd in results
|
||||
]
|
||||
@ -455,7 +474,7 @@ async def get_help_names_for_autocomplete(
|
||||
db.close()
|
||||
|
||||
|
||||
@router.get('/{command_id}')
|
||||
@router.get("/{command_id}")
|
||||
@handle_db_errors
|
||||
async def get_help_command(command_id: int):
|
||||
"""Get a single help command by ID"""
|
||||
@ -463,13 +482,15 @@ async def get_help_command(command_id: int):
|
||||
help_cmd = HelpCommand.get_or_none(HelpCommand.id == command_id)
|
||||
|
||||
if not help_cmd:
|
||||
raise HTTPException(status_code=404, detail=f"Help command {command_id} not found")
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Help command {command_id} not found"
|
||||
)
|
||||
|
||||
result = model_to_dict(help_cmd)
|
||||
if result.get('created_at'):
|
||||
result['created_at'] = result['created_at'].isoformat()
|
||||
if result.get('updated_at'):
|
||||
result['updated_at'] = result['updated_at'].isoformat()
|
||||
if result.get("created_at"):
|
||||
result["created_at"] = result["created_at"].isoformat()
|
||||
if result.get("updated_at"):
|
||||
result["updated_at"] = result["updated_at"].isoformat()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@ -4,15 +4,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, Injury, Player, model_to_dict, fn
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/injuries',
|
||||
tags=['injuries']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/injuries", tags=["injuries"])
|
||||
|
||||
|
||||
class InjuryModel(pydantic.BaseModel):
|
||||
season: int
|
||||
@ -25,12 +27,18 @@ class InjuryModel(pydantic.BaseModel):
|
||||
is_active: bool = True
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_injuries(
|
||||
season: list = Query(default=None), player_id: list = Query(default=None), min_games: int = None,
|
||||
max_games: int = None, team_id: list = Query(default=None), is_active: bool = None,
|
||||
short_output: bool = False, sort: Optional[str] = 'start-asc'):
|
||||
season: list = Query(default=None),
|
||||
player_id: list = Query(default=None),
|
||||
min_games: int = None,
|
||||
max_games: int = None,
|
||||
team_id: list = Query(default=None),
|
||||
is_active: bool = None,
|
||||
short_output: bool = False,
|
||||
sort: Optional[str] = "start-asc",
|
||||
):
|
||||
all_injuries = Injury.select()
|
||||
|
||||
if season is not None:
|
||||
@ -47,34 +55,38 @@ async def get_injuries(
|
||||
all_players = Player.select().where(Player.team_id << team_id)
|
||||
all_injuries = all_injuries.where(Injury.player << all_players)
|
||||
|
||||
if sort == 'return-asc':
|
||||
if sort == "return-asc":
|
||||
all_injuries = all_injuries.order_by(Injury.end_week, Injury.end_game)
|
||||
elif sort == 'return-desc':
|
||||
elif sort == "return-desc":
|
||||
all_injuries = all_injuries.order_by(-Injury.end_week, -Injury.end_game)
|
||||
elif sort == 'start-asc':
|
||||
elif sort == "start-asc":
|
||||
all_injuries = all_injuries.order_by(Injury.start_week, Injury.start_game)
|
||||
elif sort == 'start-desc':
|
||||
elif sort == "start-desc":
|
||||
all_injuries = all_injuries.order_by(-Injury.start_week, -Injury.start_game)
|
||||
|
||||
return_injuries = {
|
||||
'count': all_injuries.count(),
|
||||
'injuries': [model_to_dict(x, recurse=not short_output) for x in all_injuries]
|
||||
"count": all_injuries.count(),
|
||||
"injuries": [model_to_dict(x, recurse=not short_output) for x in all_injuries],
|
||||
}
|
||||
db.close()
|
||||
return return_injuries
|
||||
|
||||
|
||||
@router.patch('/{injury_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{injury_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_injury(injury_id: int, is_active: Optional[bool] = None, token: str = Depends(oauth2_scheme)):
|
||||
async def patch_injury(
|
||||
injury_id: int,
|
||||
is_active: Optional[bool] = None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_injury - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_injury - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_injury = Injury.get_or_none(Injury.id == injury_id)
|
||||
if this_injury is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Injury ID {injury_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Injury ID {injury_id} not found")
|
||||
|
||||
if is_active is not None:
|
||||
this_injury.is_active = is_active
|
||||
@ -85,15 +97,17 @@ async def patch_injury(injury_id: int, is_active: Optional[bool] = None, token:
|
||||
return r_injury
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to patch injury {injury_id}')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to patch injury {injury_id}"
|
||||
)
|
||||
|
||||
|
||||
@router.post(f'', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_injury(new_injury: InjuryModel, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_injury - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_injury - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_injury = Injury(**new_injury.dict())
|
||||
|
||||
@ -103,28 +117,27 @@ async def post_injury(new_injury: InjuryModel, token: str = Depends(oauth2_schem
|
||||
return r_injury
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to post injury')
|
||||
raise HTTPException(status_code=500, detail=f"Unable to post injury")
|
||||
|
||||
|
||||
@router.delete('/{injury_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{injury_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_injury(injury_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_injury - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_injury - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_injury = Injury.get_or_none(Injury.id == injury_id)
|
||||
if this_injury is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Injury ID {injury_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Injury ID {injury_id} not found")
|
||||
|
||||
count = this_injury.delete_instance()
|
||||
db.close()
|
||||
|
||||
if count == 1:
|
||||
return f'Injury {injury_id} has been deleted'
|
||||
return f"Injury {injury_id} has been deleted"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'Unable to delete injury {injury_id}')
|
||||
|
||||
|
||||
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to delete injury {injury_id}"
|
||||
)
|
||||
|
||||
@ -4,15 +4,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, Keeper, Player, model_to_dict, chunked, fn
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/keepers',
|
||||
tags=['keepers']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/keepers", tags=["keepers"])
|
||||
|
||||
|
||||
class KeeperModel(pydantic.BaseModel):
|
||||
season: int
|
||||
@ -25,11 +27,14 @@ class KeeperList(pydantic.BaseModel):
|
||||
keepers: List[KeeperModel]
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_keepers(
|
||||
season: list = Query(default=None), team_id: list = Query(default=None), player_id: list = Query(default=None),
|
||||
short_output: bool = False):
|
||||
season: list = Query(default=None),
|
||||
team_id: list = Query(default=None),
|
||||
player_id: list = Query(default=None),
|
||||
short_output: bool = False,
|
||||
):
|
||||
all_keepers = Keeper.select()
|
||||
|
||||
if season is not None:
|
||||
@ -40,25 +45,29 @@ async def get_keepers(
|
||||
all_keepers = all_keepers.where(Keeper.player_id << player_id)
|
||||
|
||||
return_keepers = {
|
||||
'count': all_keepers.count(),
|
||||
'keepers': [model_to_dict(x, recurse=not short_output) for x in all_keepers]
|
||||
"count": all_keepers.count(),
|
||||
"keepers": [model_to_dict(x, recurse=not short_output) for x in all_keepers],
|
||||
}
|
||||
db.close()
|
||||
return return_keepers
|
||||
|
||||
|
||||
@router.patch('/{keeper_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{keeper_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_keeper(
|
||||
keeper_id: int, season: Optional[int] = None, team_id: Optional[int] = None, player_id: Optional[int] = None,
|
||||
token: str = Depends(oauth2_scheme)):
|
||||
keeper_id: int,
|
||||
season: Optional[int] = None,
|
||||
team_id: Optional[int] = None,
|
||||
player_id: Optional[int] = None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_keeper - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_keeper - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_keeper = Keeper.get_or_none(Keeper.id == keeper_id)
|
||||
if not this_keeper:
|
||||
raise HTTPException(status_code=404, detail=f'Keeper ID {keeper_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Keeper ID {keeper_id} not found")
|
||||
|
||||
if season is not None:
|
||||
this_keeper.season = season
|
||||
@ -73,15 +82,17 @@ async def patch_keeper(
|
||||
return r_keeper
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to patch keeper {keeper_id}')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to patch keeper {keeper_id}"
|
||||
)
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_keepers(k_list: KeeperList, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_keepers - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_keepers - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
new_keepers = []
|
||||
for keeper in k_list.keepers:
|
||||
@ -92,26 +103,26 @@ async def post_keepers(k_list: KeeperList, token: str = Depends(oauth2_scheme)):
|
||||
Keeper.insert_many(batch).on_conflict_ignore().execute()
|
||||
db.close()
|
||||
|
||||
return f'Inserted {len(new_keepers)} keepers'
|
||||
return f"Inserted {len(new_keepers)} keepers"
|
||||
|
||||
|
||||
@router.delete('/{keeper_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{keeper_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_keeper(keeper_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_keeper - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_keeper - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_keeper = Keeper.get_or_none(Keeper.id == keeper_id)
|
||||
if not this_keeper:
|
||||
raise HTTPException(status_code=404, detail=f'Keeper ID {keeper_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Keeper ID {keeper_id} not found")
|
||||
|
||||
count = this_keeper.delete_instance()
|
||||
db.close()
|
||||
|
||||
if count == 1:
|
||||
return f'Keeper ID {keeper_id} has been deleted'
|
||||
return f"Keeper ID {keeper_id} has been deleted"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'Keeper ID {keeper_id} could not be deleted')
|
||||
|
||||
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Keeper ID {keeper_id} could not be deleted"
|
||||
)
|
||||
|
||||
@ -4,15 +4,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, Manager, Team, Current, model_to_dict, fn
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/managers',
|
||||
tags=['managers']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/managers", tags=["managers"])
|
||||
|
||||
|
||||
class ManagerModel(pydantic.BaseModel):
|
||||
name: str
|
||||
@ -21,45 +23,45 @@ class ManagerModel(pydantic.BaseModel):
|
||||
bio: Optional[str] = None
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_managers(
|
||||
name: list = Query(default=None), active: Optional[bool] = None, short_output: Optional[bool] = False):
|
||||
name: list = Query(default=None),
|
||||
active: Optional[bool] = None,
|
||||
short_output: Optional[bool] = False,
|
||||
):
|
||||
if active is not None:
|
||||
current = Current.latest()
|
||||
t_query = Team.select_season(current.season)
|
||||
t_query = t_query.where(
|
||||
~(Team.abbrev.endswith('IL')) & ~(Team.abbrev.endswith('MiL'))
|
||||
~(Team.abbrev.endswith("IL")) & ~(Team.abbrev.endswith("MiL"))
|
||||
)
|
||||
logger.info(f'tquery: {t_query}')
|
||||
logger.info(f"tquery: {t_query}")
|
||||
a_mgr = []
|
||||
i_mgr = []
|
||||
|
||||
for x in t_query:
|
||||
logger.info(f'Team: {x.abbrev} / mgr1: {x.manager1} / mgr2: {x.manager2}')
|
||||
logger.info(f"Team: {x.abbrev} / mgr1: {x.manager1} / mgr2: {x.manager2}")
|
||||
if x.manager1 is not None:
|
||||
a_mgr.append(x.manager1)
|
||||
logger.info(f'appending {x.manager1.name}')
|
||||
logger.info(f"appending {x.manager1.name}")
|
||||
if x.manager2 is not None:
|
||||
a_mgr.append(x.manager2)
|
||||
logger.info(f'appending {x.manager2.name}')
|
||||
logger.info(f"appending {x.manager2.name}")
|
||||
|
||||
logger.info(f'a_mgr: {a_mgr}')
|
||||
logger.info(f"a_mgr: {a_mgr}")
|
||||
if active:
|
||||
final_mgrs = [model_to_dict(y, recurse=not short_output) for y in a_mgr]
|
||||
else:
|
||||
logger.info(f'checking inactive')
|
||||
logger.info(f"checking inactive")
|
||||
for z in Manager.select():
|
||||
logger.info(f'checking: {z.name}')
|
||||
logger.info(f"checking: {z.name}")
|
||||
if z not in a_mgr:
|
||||
logger.info(f'+inactive: {z.name}')
|
||||
logger.info(f"+inactive: {z.name}")
|
||||
i_mgr.append(z)
|
||||
final_mgrs = [model_to_dict(y, recurse=not short_output) for y in i_mgr]
|
||||
|
||||
return_managers = {
|
||||
'count': len(final_mgrs),
|
||||
'managers': final_mgrs
|
||||
}
|
||||
return_managers = {"count": len(final_mgrs), "managers": final_mgrs}
|
||||
|
||||
else:
|
||||
all_managers = Manager.select()
|
||||
@ -68,15 +70,17 @@ async def get_managers(
|
||||
all_managers = all_managers.where(fn.Lower(Manager.name) << name_list)
|
||||
|
||||
return_managers = {
|
||||
'count': all_managers.count(),
|
||||
'managers': [model_to_dict(x, recurse=not short_output) for x in all_managers]
|
||||
"count": all_managers.count(),
|
||||
"managers": [
|
||||
model_to_dict(x, recurse=not short_output) for x in all_managers
|
||||
],
|
||||
}
|
||||
|
||||
db.close()
|
||||
return return_managers
|
||||
|
||||
|
||||
@router.get('/{manager_id}')
|
||||
@router.get("/{manager_id}")
|
||||
@handle_db_errors
|
||||
async def get_one_manager(manager_id: int, short_output: Optional[bool] = False):
|
||||
this_manager = Manager.get_or_none(Manager.id == manager_id)
|
||||
@ -85,22 +89,29 @@ async def get_one_manager(manager_id: int, short_output: Optional[bool] = False)
|
||||
db.close()
|
||||
return r_manager
|
||||
else:
|
||||
raise HTTPException(status_code=404, detail=f'Manager {manager_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Manager {manager_id} not found")
|
||||
|
||||
|
||||
@router.patch('/{manager_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{manager_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_manager(
|
||||
manager_id: int, name: Optional[str] = None, image: Optional[str] = None, headline: Optional[str] = None,
|
||||
bio: Optional[str] = None, token: str = Depends(oauth2_scheme)):
|
||||
manager_id: int,
|
||||
name: Optional[str] = None,
|
||||
image: Optional[str] = None,
|
||||
headline: Optional[str] = None,
|
||||
bio: Optional[str] = None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_manager - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_manager - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_manager = Manager.get_or_none(Manager.id == manager_id)
|
||||
if this_manager is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Manager ID {manager_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Manager ID {manager_id} not found"
|
||||
)
|
||||
|
||||
if name is not None:
|
||||
this_manager.name = name
|
||||
@ -117,15 +128,17 @@ async def patch_manager(
|
||||
return r_manager
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to patch manager {this_manager}')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to patch manager {this_manager}"
|
||||
)
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_manager(new_manager: ManagerModel, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_manager - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_manager - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_manager = Manager(**new_manager.dict())
|
||||
|
||||
@ -135,25 +148,31 @@ async def post_manager(new_manager: ManagerModel, token: str = Depends(oauth2_sc
|
||||
return r_manager
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to post manager {this_manager.name}')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to post manager {this_manager.name}"
|
||||
)
|
||||
|
||||
|
||||
@router.delete('/{manager_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{manager_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_manager(manager_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_manager - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_manager - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_manager = Manager.get_or_none(Manager.id == manager_id)
|
||||
if this_manager is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Manager ID {manager_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Manager ID {manager_id} not found"
|
||||
)
|
||||
|
||||
count = this_manager.delete_instance()
|
||||
db.close()
|
||||
|
||||
if count == 1:
|
||||
return f'Manager {manager_id} has been deleted'
|
||||
return f"Manager {manager_id} has been deleted"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'Manager {manager_id} could not be deleted')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Manager {manager_id} could not be deleted"
|
||||
)
|
||||
|
||||
@ -6,15 +6,27 @@ from typing import List, Optional, Literal
|
||||
import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, PitchingStat, Team, Player, Current, model_to_dict, chunked, fn, per_season_weeks
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/pitchingstats',
|
||||
tags=['pitchingstats']
|
||||
from ..db_engine import (
|
||||
db,
|
||||
PitchingStat,
|
||||
Team,
|
||||
Player,
|
||||
Current,
|
||||
model_to_dict,
|
||||
chunked,
|
||||
fn,
|
||||
per_season_weeks,
|
||||
)
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/pitchingstats", tags=["pitchingstats"])
|
||||
|
||||
|
||||
class PitStatModel(pydantic.BaseModel):
|
||||
@ -48,29 +60,37 @@ class PitStatList(pydantic.BaseModel):
|
||||
stats: List[PitStatModel]
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_pitstats(
|
||||
season: int, s_type: Optional[str] = 'regular', team_abbrev: list = Query(default=None),
|
||||
player_name: list = Query(default=None), player_id: list = Query(default=None),
|
||||
week_start: Optional[int] = None, week_end: Optional[int] = None, game_num: list = Query(default=None),
|
||||
limit: Optional[int] = None, ip_min: Optional[float] = None, sort: Optional[str] = None,
|
||||
short_output: Optional[bool] = True):
|
||||
if 'post' in s_type.lower():
|
||||
season: int,
|
||||
s_type: Optional[str] = "regular",
|
||||
team_abbrev: list = Query(default=None),
|
||||
player_name: list = Query(default=None),
|
||||
player_id: list = Query(default=None),
|
||||
week_start: Optional[int] = None,
|
||||
week_end: Optional[int] = None,
|
||||
game_num: list = Query(default=None),
|
||||
limit: Optional[int] = None,
|
||||
ip_min: Optional[float] = None,
|
||||
sort: Optional[str] = None,
|
||||
short_output: Optional[bool] = True,
|
||||
):
|
||||
if "post" in s_type.lower():
|
||||
all_stats = PitchingStat.post_season(season)
|
||||
if all_stats.count() == 0:
|
||||
db.close()
|
||||
return {'count': 0, 'stats': []}
|
||||
elif s_type.lower() in ['combined', 'total', 'all']:
|
||||
return {"count": 0, "stats": []}
|
||||
elif s_type.lower() in ["combined", "total", "all"]:
|
||||
all_stats = PitchingStat.combined_season(season)
|
||||
if all_stats.count() == 0:
|
||||
db.close()
|
||||
return {'count': 0, 'stats': []}
|
||||
return {"count": 0, "stats": []}
|
||||
else:
|
||||
all_stats = PitchingStat.regular_season(season)
|
||||
if all_stats.count() == 0:
|
||||
db.close()
|
||||
return {'count': 0, 'stats': []}
|
||||
return {"count": 0, "stats": []}
|
||||
|
||||
if team_abbrev is not None:
|
||||
t_query = Team.select().where(Team.abbrev << [x.upper() for x in team_abbrev])
|
||||
@ -79,7 +99,9 @@ async def get_pitstats(
|
||||
if player_id:
|
||||
all_stats = all_stats.where(PitchingStat.player_id << player_id)
|
||||
else:
|
||||
p_query = Player.select_season(season).where(fn.Lower(Player.name) << [x.lower() for x in player_name])
|
||||
p_query = Player.select_season(season).where(
|
||||
fn.Lower(Player.name) << [x.lower() for x in player_name]
|
||||
)
|
||||
all_stats = all_stats.where(PitchingStat.player << p_query)
|
||||
if game_num:
|
||||
all_stats = all_stats.where(PitchingStat.game == game_num)
|
||||
@ -96,7 +118,7 @@ async def get_pitstats(
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail=f'Start week {start} is after end week {end} - cannot pull stats'
|
||||
detail=f"Start week {start} is after end week {end} - cannot pull stats",
|
||||
)
|
||||
all_stats = all_stats.where(
|
||||
(PitchingStat.week >= start) & (PitchingStat.week <= end)
|
||||
@ -105,56 +127,79 @@ async def get_pitstats(
|
||||
if limit:
|
||||
all_stats = all_stats.limit(limit)
|
||||
if sort:
|
||||
if sort == 'newest':
|
||||
if sort == "newest":
|
||||
all_stats = all_stats.order_by(-PitchingStat.week, -PitchingStat.game)
|
||||
|
||||
return_stats = {
|
||||
'count': all_stats.count(),
|
||||
'stats': [model_to_dict(x, recurse=not short_output) for x in all_stats]
|
||||
"count": all_stats.count(),
|
||||
"stats": [model_to_dict(x, recurse=not short_output) for x in all_stats],
|
||||
}
|
||||
|
||||
db.close()
|
||||
return return_stats
|
||||
|
||||
|
||||
@router.get('/totals')
|
||||
@router.get("/totals")
|
||||
@handle_db_errors
|
||||
async def get_totalstats(
|
||||
season: int, s_type: Literal['regular', 'post', 'total', None] = None, team_abbrev: list = Query(default=None),
|
||||
team_id: list = Query(default=None), player_name: list = Query(default=None),
|
||||
week_start: Optional[int] = None, week_end: Optional[int] = None, game_num: list = Query(default=None),
|
||||
is_sp: Optional[bool] = None, ip_min: Optional[float] = 0.25, sort: Optional[str] = None,
|
||||
player_id: list = Query(default=None), short_output: Optional[bool] = False,
|
||||
group_by: Literal['team', 'player', 'playerteam'] = 'player', week: list = Query(default=None)):
|
||||
season: int,
|
||||
s_type: Literal["regular", "post", "total", None] = None,
|
||||
team_abbrev: list = Query(default=None),
|
||||
team_id: list = Query(default=None),
|
||||
player_name: list = Query(default=None),
|
||||
week_start: Optional[int] = None,
|
||||
week_end: Optional[int] = None,
|
||||
game_num: list = Query(default=None),
|
||||
is_sp: Optional[bool] = None,
|
||||
ip_min: Optional[float] = 0.25,
|
||||
sort: Optional[str] = None,
|
||||
player_id: list = Query(default=None),
|
||||
short_output: Optional[bool] = False,
|
||||
group_by: Literal["team", "player", "playerteam"] = "player",
|
||||
week: list = Query(default=None),
|
||||
):
|
||||
if sum(1 for x in [s_type, (week_start or week_end), week] if x is not None) > 1:
|
||||
raise HTTPException(status_code=400, detail=f'Only one of s_type, week_start/week_end, or week may be used.')
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Only one of s_type, week_start/week_end, or week may be used.",
|
||||
)
|
||||
|
||||
# Build SELECT fields conditionally based on group_by to match GROUP BY exactly
|
||||
select_fields = []
|
||||
|
||||
if group_by == 'player':
|
||||
if group_by == "player":
|
||||
select_fields = [PitchingStat.player]
|
||||
elif group_by == 'team':
|
||||
elif group_by == "team":
|
||||
select_fields = [PitchingStat.team]
|
||||
elif group_by == 'playerteam':
|
||||
elif group_by == "playerteam":
|
||||
select_fields = [PitchingStat.player, PitchingStat.team]
|
||||
else:
|
||||
# Default case
|
||||
select_fields = [PitchingStat.player]
|
||||
|
||||
all_stats = (
|
||||
PitchingStat
|
||||
.select(*select_fields,
|
||||
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.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.SUM(PitchingStat.irs).alias('sum_irs'),
|
||||
fn.SUM(PitchingStat.gs).alias('sum_gs'), fn.COUNT(PitchingStat.game).alias('sum_games'))
|
||||
PitchingStat.select(
|
||||
*select_fields,
|
||||
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.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.SUM(PitchingStat.irs).alias("sum_irs"),
|
||||
fn.SUM(PitchingStat.gs).alias("sum_gs"),
|
||||
fn.COUNT(PitchingStat.game).alias("sum_games"),
|
||||
)
|
||||
.where(PitchingStat.season == season)
|
||||
.having(fn.SUM(PitchingStat.ip) >= ip_min)
|
||||
)
|
||||
@ -166,16 +211,20 @@ async def get_totalstats(
|
||||
elif week_start is not None or week_end is not None:
|
||||
if week_start is None or week_end is None:
|
||||
raise HTTPException(
|
||||
status_code=400, detail='Both week_start and week_end must be included if either is used.'
|
||||
status_code=400,
|
||||
detail="Both week_start and week_end must be included if either is used.",
|
||||
)
|
||||
weeks["start"] = week_start
|
||||
if week_end < weeks["start"]:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="week_end must be greater than or equal to week_start",
|
||||
)
|
||||
weeks['start'] = week_start
|
||||
if week_end < weeks['start']:
|
||||
raise HTTPException(status_code=400, detail='week_end must be greater than or equal to week_start')
|
||||
else:
|
||||
weeks['end'] = week_end
|
||||
weeks["end"] = week_end
|
||||
|
||||
all_stats = all_stats.where(
|
||||
(PitchingStat.week >= weeks['start']) & (PitchingStat.week <= weeks['end'])
|
||||
(PitchingStat.week >= weeks["start"]) & (PitchingStat.week <= weeks["end"])
|
||||
)
|
||||
|
||||
elif week is not None:
|
||||
@ -189,9 +238,9 @@ async def get_totalstats(
|
||||
if not is_sp:
|
||||
all_stats = all_stats.where(PitchingStat.gs == 0)
|
||||
if sort is not None:
|
||||
if sort == 'player':
|
||||
if sort == "player":
|
||||
all_stats = all_stats.order_by(PitchingStat.player)
|
||||
elif sort == 'team':
|
||||
elif sort == "team":
|
||||
all_stats = all_stats.order_by(PitchingStat.team)
|
||||
if group_by is not None:
|
||||
# Use the same fields for GROUP BY as we used for SELECT
|
||||
@ -200,67 +249,76 @@ async def get_totalstats(
|
||||
all_teams = Team.select().where(Team.id << team_id)
|
||||
all_stats = all_stats.where(PitchingStat.team << all_teams)
|
||||
elif team_abbrev is not None:
|
||||
all_teams = Team.select().where(fn.Lower(Team.abbrev) << [x.lower() for x in team_abbrev])
|
||||
all_teams = Team.select().where(
|
||||
fn.Lower(Team.abbrev) << [x.lower() for x in team_abbrev]
|
||||
)
|
||||
all_stats = all_stats.where(PitchingStat.team << all_teams)
|
||||
if player_name is not None:
|
||||
all_players = Player.select().where(fn.Lower(Player.name) << [x.lower() for x in player_name])
|
||||
all_players = Player.select().where(
|
||||
fn.Lower(Player.name) << [x.lower() for x in player_name]
|
||||
)
|
||||
all_stats = all_stats.where(PitchingStat.player << all_players)
|
||||
elif player_id is not None:
|
||||
all_players = Player.select().where(Player.id << player_id)
|
||||
all_stats = all_stats.where(PitchingStat.player << all_players)
|
||||
|
||||
return_stats = {
|
||||
'count': all_stats.count(),
|
||||
'stats': []
|
||||
}
|
||||
return_stats = {"count": all_stats.count(), "stats": []}
|
||||
|
||||
for x in all_stats:
|
||||
# Handle player field based on grouping with safe access
|
||||
this_player = 'TOT'
|
||||
if 'player' in group_by and hasattr(x, 'player'):
|
||||
this_player = x.player_id if short_output else model_to_dict(x.player, recurse=False)
|
||||
this_player = "TOT"
|
||||
if "player" in group_by and hasattr(x, "player"):
|
||||
this_player = (
|
||||
x.player_id if short_output else model_to_dict(x.player, recurse=False)
|
||||
)
|
||||
|
||||
# Handle team field based on grouping with safe access
|
||||
this_team = 'TOT'
|
||||
if 'team' in group_by and hasattr(x, 'team'):
|
||||
this_team = x.team_id if short_output else model_to_dict(x.team, recurse=False)
|
||||
this_team = "TOT"
|
||||
if "team" in group_by and hasattr(x, "team"):
|
||||
this_team = (
|
||||
x.team_id if short_output else model_to_dict(x.team, recurse=False)
|
||||
)
|
||||
|
||||
return_stats['stats'].append({
|
||||
'player': this_player,
|
||||
'team': this_team,
|
||||
'ip': x.sum_ip,
|
||||
'hit': x.sum_hit,
|
||||
'run': x.sum_run,
|
||||
'erun': x.sum_erun,
|
||||
'so': x.sum_so,
|
||||
'bb': x.sum_bb,
|
||||
'hbp': x.sum_hbp,
|
||||
'wp': x.sum_wp,
|
||||
'balk': x.sum_balk,
|
||||
'hr': x.sum_hr,
|
||||
'ir': x.sum_ir,
|
||||
'irs': x.sum_irs,
|
||||
'gs': x.sum_gs,
|
||||
'games': x.sum_games,
|
||||
'win': x.sum_win,
|
||||
'loss': x.sum_loss,
|
||||
'hold': x.sum_hold,
|
||||
'sv': x.sum_sv,
|
||||
'bsv': x.sum_bsv
|
||||
})
|
||||
return_stats["stats"].append(
|
||||
{
|
||||
"player": this_player,
|
||||
"team": this_team,
|
||||
"ip": x.sum_ip,
|
||||
"hit": x.sum_hit,
|
||||
"run": x.sum_run,
|
||||
"erun": x.sum_erun,
|
||||
"so": x.sum_so,
|
||||
"bb": x.sum_bb,
|
||||
"hbp": x.sum_hbp,
|
||||
"wp": x.sum_wp,
|
||||
"balk": x.sum_balk,
|
||||
"hr": x.sum_hr,
|
||||
"ir": x.sum_ir,
|
||||
"irs": x.sum_irs,
|
||||
"gs": x.sum_gs,
|
||||
"games": x.sum_games,
|
||||
"win": x.sum_win,
|
||||
"loss": x.sum_loss,
|
||||
"hold": x.sum_hold,
|
||||
"sv": x.sum_sv,
|
||||
"bsv": x.sum_bsv,
|
||||
}
|
||||
)
|
||||
db.close()
|
||||
return return_stats
|
||||
|
||||
|
||||
@router.patch('/{stat_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{stat_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_pitstats(stat_id: int, new_stats: PitStatModel, token: str = Depends(oauth2_scheme)):
|
||||
async def patch_pitstats(
|
||||
stat_id: int, new_stats: PitStatModel, token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_pitstats - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_pitstats - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
if PitchingStat.get_or_none(PitchingStat.id == stat_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Stat ID {stat_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Stat ID {stat_id} not found")
|
||||
|
||||
PitchingStat.update(**new_stats.dict()).where(PitchingStat.id == stat_id).execute()
|
||||
r_stat = model_to_dict(PitchingStat.get_by_id(stat_id))
|
||||
@ -268,12 +326,12 @@ async def patch_pitstats(stat_id: int, new_stats: PitStatModel, token: str = Dep
|
||||
return r_stat
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_pitstats(s_list: PitStatList, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_pitstats - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_pitstats - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
all_stats = []
|
||||
|
||||
@ -281,9 +339,13 @@ async def post_pitstats(s_list: PitStatList, token: str = Depends(oauth2_scheme)
|
||||
team = Team.get_or_none(Team.id == x.team_id)
|
||||
this_player = Player.get_or_none(Player.id == x.player_id)
|
||||
if team is None:
|
||||
raise HTTPException(status_code=404, detail=f'Team ID {x.team_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Team ID {x.team_id} not found"
|
||||
)
|
||||
if this_player is None:
|
||||
raise HTTPException(status_code=404, detail=f'Player ID {x.player_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Player ID {x.player_id} not found"
|
||||
)
|
||||
|
||||
all_stats.append(PitchingStat(**x.dict()))
|
||||
|
||||
@ -292,4 +354,4 @@ async def post_pitstats(s_list: PitStatList, token: str = Depends(oauth2_scheme)
|
||||
PitchingStat.insert_many(batch).on_conflict_ignore().execute()
|
||||
|
||||
db.close()
|
||||
return f'Added {len(all_stats)} batting lines'
|
||||
return f"Added {len(all_stats)} batting lines"
|
||||
|
||||
@ -24,8 +24,12 @@ async def get_players(
|
||||
strat_code: list = Query(default=None),
|
||||
is_injured: Optional[bool] = None,
|
||||
sort: Optional[str] = None,
|
||||
limit: Optional[int] = Query(default=None, ge=1, description="Maximum number of results to return"),
|
||||
offset: Optional[int] = Query(default=None, ge=0, description="Number of results to skip for pagination"),
|
||||
limit: Optional[int] = Query(
|
||||
default=None, ge=1, description="Maximum number of results to return"
|
||||
),
|
||||
offset: Optional[int] = Query(
|
||||
default=None, ge=0, description="Number of results to skip for pagination"
|
||||
),
|
||||
short_output: Optional[bool] = False,
|
||||
csv: Optional[bool] = False,
|
||||
):
|
||||
@ -41,7 +45,7 @@ async def get_players(
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
short_output=short_output or False,
|
||||
as_csv=csv or False
|
||||
as_csv=csv or False,
|
||||
)
|
||||
|
||||
if csv:
|
||||
@ -54,35 +58,29 @@ async def get_players(
|
||||
@cache_result(ttl=15 * 60, key_prefix="players-search")
|
||||
async def search_players(
|
||||
q: str = Query(..., description="Search query for player name"),
|
||||
season: Optional[int] = Query(default=None, description="Season to search (0 for all)"),
|
||||
season: Optional[int] = Query(
|
||||
default=None, description="Season to search (0 for all)"
|
||||
),
|
||||
limit: int = Query(default=10, ge=1, le=50),
|
||||
short_output: bool = False,
|
||||
):
|
||||
"""Search players by name with fuzzy matching."""
|
||||
return PlayerService.search_players(
|
||||
query_str=q,
|
||||
season=season,
|
||||
limit=limit,
|
||||
short_output=short_output
|
||||
query_str=q, season=season, limit=limit, short_output=short_output
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{player_id}")
|
||||
@handle_db_errors
|
||||
@cache_result(ttl=30 * 60, key_prefix="player")
|
||||
async def get_one_player(
|
||||
player_id: int,
|
||||
short_output: Optional[bool] = False
|
||||
):
|
||||
async def get_one_player(player_id: int, short_output: Optional[bool] = False):
|
||||
"""Get a single player by ID."""
|
||||
return PlayerService.get_player(player_id, short_output=short_output or False)
|
||||
|
||||
|
||||
@router.put("/{player_id}")
|
||||
async def put_player(
|
||||
player_id: int,
|
||||
new_player: dict,
|
||||
token: str = Depends(oauth2_scheme)
|
||||
player_id: int, new_player: dict, token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
"""Update a player (full replacement)."""
|
||||
return PlayerService.update_player(player_id, new_player, token)
|
||||
@ -120,14 +118,28 @@ async def patch_player(
|
||||
data = {
|
||||
key: value
|
||||
for key, value in {
|
||||
'name': name, 'wara': wara, 'image': image, 'image2': image2,
|
||||
'team_id': team_id, 'season': season,
|
||||
'pos_1': pos_1, 'pos_2': pos_2, 'pos_3': pos_3, 'pos_4': pos_4,
|
||||
'pos_5': pos_5, 'pos_6': pos_6, 'pos_7': pos_7, 'pos_8': pos_8,
|
||||
'vanity_card': vanity_card, 'headshot': headshot,
|
||||
'il_return': il_return, 'demotion_week': demotion_week,
|
||||
'strat_code': strat_code, 'bbref_id': bbref_id,
|
||||
'injury_rating': injury_rating, 'sbaref_id': sbaref_id,
|
||||
"name": name,
|
||||
"wara": wara,
|
||||
"image": image,
|
||||
"image2": image2,
|
||||
"team_id": team_id,
|
||||
"season": season,
|
||||
"pos_1": pos_1,
|
||||
"pos_2": pos_2,
|
||||
"pos_3": pos_3,
|
||||
"pos_4": pos_4,
|
||||
"pos_5": pos_5,
|
||||
"pos_6": pos_6,
|
||||
"pos_7": pos_7,
|
||||
"pos_8": pos_8,
|
||||
"vanity_card": vanity_card,
|
||||
"headshot": headshot,
|
||||
"il_return": il_return,
|
||||
"demotion_week": demotion_week,
|
||||
"strat_code": strat_code,
|
||||
"bbref_id": bbref_id,
|
||||
"injury_rating": injury_rating,
|
||||
"sbaref_id": sbaref_id,
|
||||
}.items()
|
||||
if value is not None
|
||||
}
|
||||
@ -135,19 +147,13 @@ async def patch_player(
|
||||
return PlayerService.patch_player(player_id, data, token)
|
||||
|
||||
|
||||
@router.post("")
|
||||
async def post_players(
|
||||
p_list: dict,
|
||||
token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
@router.post("/")
|
||||
async def post_players(p_list: dict, token: str = Depends(oauth2_scheme)):
|
||||
"""Create multiple players."""
|
||||
return PlayerService.create_players(p_list.get("players", []), token)
|
||||
|
||||
|
||||
@router.delete("/{player_id}")
|
||||
async def delete_player(
|
||||
player_id: int,
|
||||
token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
async def delete_player(player_id: int, token: str = Depends(oauth2_scheme)):
|
||||
"""Delete a player."""
|
||||
return PlayerService.delete_player(player_id, token)
|
||||
|
||||
@ -4,15 +4,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, Result, Team, model_to_dict, chunked
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/results',
|
||||
tags=['results']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/results", tags=["results"])
|
||||
|
||||
|
||||
class ResultModel(pydantic.BaseModel):
|
||||
week: int
|
||||
@ -29,13 +31,18 @@ class ResultList(pydantic.BaseModel):
|
||||
results: List[ResultModel]
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_results(
|
||||
season: int, team_abbrev: list = Query(default=None), week_start: Optional[int] = None,
|
||||
week_end: Optional[int] = None, game_num: list = Query(default=None),
|
||||
away_abbrev: list = Query(default=None), home_abbrev: list = Query(default=None),
|
||||
short_output: Optional[bool] = False):
|
||||
season: int,
|
||||
team_abbrev: list = Query(default=None),
|
||||
week_start: Optional[int] = None,
|
||||
week_end: Optional[int] = None,
|
||||
game_num: list = Query(default=None),
|
||||
away_abbrev: list = Query(default=None),
|
||||
home_abbrev: list = Query(default=None),
|
||||
short_output: Optional[bool] = False,
|
||||
):
|
||||
all_results = Result.select_season(season)
|
||||
|
||||
if team_abbrev is not None:
|
||||
@ -68,14 +75,14 @@ async def get_results(
|
||||
all_results = all_results.where(Result.week <= week_end)
|
||||
|
||||
return_results = {
|
||||
'count': all_results.count(),
|
||||
'results': [model_to_dict(x, recurse=not short_output) for x in all_results]
|
||||
"count": all_results.count(),
|
||||
"results": [model_to_dict(x, recurse=not short_output) for x in all_results],
|
||||
}
|
||||
db.close()
|
||||
return return_results
|
||||
|
||||
|
||||
@router.get('/{result_id}')
|
||||
@router.get("/{result_id}")
|
||||
@handle_db_errors
|
||||
async def get_one_result(result_id: int, short_output: Optional[bool] = False):
|
||||
this_result = Result.get_or_none(Result.id == result_id)
|
||||
@ -87,20 +94,27 @@ async def get_one_result(result_id: int, short_output: Optional[bool] = False):
|
||||
return r_result
|
||||
|
||||
|
||||
@router.patch('/{result_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{result_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_result(
|
||||
result_id: int, week_num: Optional[int] = None, game_num: Optional[int] = None,
|
||||
away_team_id: Optional[int] = None, home_team_id: Optional[int] = None, away_score: Optional[int] = None,
|
||||
home_score: Optional[int] = None, season: Optional[int] = None, scorecard_url: Optional[str] = None,
|
||||
token: str = Depends(oauth2_scheme)):
|
||||
result_id: int,
|
||||
week_num: Optional[int] = None,
|
||||
game_num: Optional[int] = None,
|
||||
away_team_id: Optional[int] = None,
|
||||
home_team_id: Optional[int] = None,
|
||||
away_score: Optional[int] = None,
|
||||
home_score: Optional[int] = None,
|
||||
season: Optional[int] = None,
|
||||
scorecard_url: Optional[str] = None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_player - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_player - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_result = Result.get_or_none(Result.id == result_id)
|
||||
if this_result is None:
|
||||
raise HTTPException(status_code=404, detail=f'Result ID {result_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Result ID {result_id} not found")
|
||||
|
||||
if week_num is not None:
|
||||
this_result.week = week_num
|
||||
@ -132,22 +146,28 @@ async def patch_result(
|
||||
return r_result
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to patch result {result_id}')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to patch result {result_id}"
|
||||
)
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_results(result_list: ResultList, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_player - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_player - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
new_results = []
|
||||
for x in result_list.results:
|
||||
if Team.get_or_none(Team.id == x.awayteam_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Team ID {x.awayteam_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Team ID {x.awayteam_id} not found"
|
||||
)
|
||||
if Team.get_or_none(Team.id == x.hometeam_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Team ID {x.hometeam_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Team ID {x.hometeam_id} not found"
|
||||
)
|
||||
|
||||
new_results.append(x.dict())
|
||||
|
||||
@ -156,27 +176,27 @@ async def post_results(result_list: ResultList, token: str = Depends(oauth2_sche
|
||||
Result.insert_many(batch).on_conflict_ignore().execute()
|
||||
db.close()
|
||||
|
||||
return f'Inserted {len(new_results)} results'
|
||||
return f"Inserted {len(new_results)} results"
|
||||
|
||||
|
||||
@router.delete('/{result_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{result_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_result(result_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_result - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_result - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_result = Result.get_or_none(Result.id == result_id)
|
||||
if not this_result:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'Result ID {result_id} not found')
|
||||
raise HTTPException(status_code=404, detail=f"Result ID {result_id} not found")
|
||||
|
||||
count = this_result.delete_instance()
|
||||
db.close()
|
||||
|
||||
if count == 1:
|
||||
return f'Result {result_id} has been deleted'
|
||||
return f"Result {result_id} has been deleted"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'Result {result_id} could not be deleted')
|
||||
|
||||
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Result {result_id} could not be deleted"
|
||||
)
|
||||
|
||||
@ -7,15 +7,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, SbaPlayer, model_to_dict, fn, chunked, query_to_csv
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/sbaplayers',
|
||||
tags=['sbaplayers']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/sbaplayers", tags=["sbaplayers"])
|
||||
|
||||
|
||||
class SbaPlayerModel(pydantic.BaseModel):
|
||||
first_name: str
|
||||
@ -30,19 +32,26 @@ class PlayerList(pydantic.BaseModel):
|
||||
players: List[SbaPlayerModel]
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_players(
|
||||
full_name: list = Query(default=None), first_name: list = Query(default=None),
|
||||
last_name: list = Query(default=None), key_fangraphs: list = Query(default=None),
|
||||
key_bbref: list = Query(default=None), key_retro: list = Query(default=None),
|
||||
key_mlbam: list = Query(default=None), sort: Optional[str] = None, csv: Optional[bool] = False):
|
||||
full_name: list = Query(default=None),
|
||||
first_name: list = Query(default=None),
|
||||
last_name: list = Query(default=None),
|
||||
key_fangraphs: list = Query(default=None),
|
||||
key_bbref: list = Query(default=None),
|
||||
key_retro: list = Query(default=None),
|
||||
key_mlbam: list = Query(default=None),
|
||||
sort: Optional[str] = None,
|
||||
csv: Optional[bool] = False,
|
||||
):
|
||||
all_players = SbaPlayer.select()
|
||||
|
||||
if full_name is not None:
|
||||
name_list = [x.lower() for x in full_name]
|
||||
all_players = all_players.where(
|
||||
fn.lower(SbaPlayer.first_name) + ' ' + fn.lower(SbaPlayer.last_name) << name_list
|
||||
fn.lower(SbaPlayer.first_name) + " " + fn.lower(SbaPlayer.last_name)
|
||||
<< name_list
|
||||
)
|
||||
if first_name is not None:
|
||||
name_list = [x.lower() for x in first_name]
|
||||
@ -62,74 +71,85 @@ async def get_players(
|
||||
all_players = all_players.where(SbaPlayer.key_mlbam << key_mlbam)
|
||||
|
||||
if sort is not None:
|
||||
if sort in ['firstname-asc', 'fullname-asc']:
|
||||
if sort in ["firstname-asc", "fullname-asc"]:
|
||||
all_players = all_players.order_by(SbaPlayer.first_name)
|
||||
elif sort in ['firstname-desc', 'fullname-desc']:
|
||||
elif sort in ["firstname-desc", "fullname-desc"]:
|
||||
all_players = all_players.order_by(-SbaPlayer.first_name)
|
||||
elif sort == 'lastname-asc':
|
||||
elif sort == "lastname-asc":
|
||||
all_players = all_players.order_by(SbaPlayer.last_name)
|
||||
elif sort == 'lastname-desc':
|
||||
elif sort == "lastname-desc":
|
||||
all_players = all_players.order_by(-SbaPlayer.last_name)
|
||||
elif sort == 'fangraphs-asc':
|
||||
elif sort == "fangraphs-asc":
|
||||
all_players = all_players.order_by(SbaPlayer.key_fangraphs)
|
||||
elif sort == 'fangraphs-desc':
|
||||
elif sort == "fangraphs-desc":
|
||||
all_players = all_players.order_by(-SbaPlayer.key_fangraphs)
|
||||
elif sort == 'bbref-asc':
|
||||
elif sort == "bbref-asc":
|
||||
all_players = all_players.order_by(SbaPlayer.key_bbref)
|
||||
elif sort == 'bbref-desc':
|
||||
elif sort == "bbref-desc":
|
||||
all_players = all_players.order_by(-SbaPlayer.key_bbref)
|
||||
elif sort == 'retro-asc':
|
||||
elif sort == "retro-asc":
|
||||
all_players = all_players.order_by(SbaPlayer.key_retro)
|
||||
elif sort == 'retro-desc':
|
||||
elif sort == "retro-desc":
|
||||
all_players = all_players.order_by(-SbaPlayer.key_retro)
|
||||
elif sort == 'mlbam-asc':
|
||||
elif sort == "mlbam-asc":
|
||||
all_players = all_players.order_by(SbaPlayer.key_mlbam)
|
||||
elif sort == 'mlbam-desc':
|
||||
elif sort == "mlbam-desc":
|
||||
all_players = all_players.order_by(-SbaPlayer.key_mlbam)
|
||||
|
||||
if csv:
|
||||
return_val = query_to_csv(all_players)
|
||||
db.close()
|
||||
return Response(content=return_val, media_type='text/csv')
|
||||
return Response(content=return_val, media_type="text/csv")
|
||||
|
||||
return_val = {'count': all_players.count(), 'players': [
|
||||
model_to_dict(x) for x in all_players
|
||||
]}
|
||||
return_val = {
|
||||
"count": all_players.count(),
|
||||
"players": [model_to_dict(x) for x in all_players],
|
||||
}
|
||||
db.close()
|
||||
return return_val
|
||||
|
||||
|
||||
@router.get('/{player_id}')
|
||||
@router.get("/{player_id}")
|
||||
@handle_db_errors
|
||||
async def get_one_player(player_id: int):
|
||||
this_player = SbaPlayer.get_or_none(SbaPlayer.id == player_id)
|
||||
if this_player is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'SbaPlayer id {player_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"SbaPlayer id {player_id} not found"
|
||||
)
|
||||
|
||||
r_data = model_to_dict(this_player)
|
||||
db.close()
|
||||
return r_data
|
||||
|
||||
|
||||
@router.patch('/{player_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{player_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_player(
|
||||
player_id: int, first_name: Optional[str] = None, last_name: Optional[str] = None,
|
||||
key_fangraphs: Optional[str] = None, key_bbref: Optional[str] = None, key_retro: Optional[str] = None,
|
||||
key_mlbam: Optional[str] = None, token: str = Depends(oauth2_scheme)):
|
||||
player_id: int,
|
||||
first_name: Optional[str] = None,
|
||||
last_name: Optional[str] = None,
|
||||
key_fangraphs: Optional[str] = None,
|
||||
key_bbref: Optional[str] = None,
|
||||
key_retro: Optional[str] = None,
|
||||
key_mlbam: Optional[str] = None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logging.warning(f'Bad Token: {token}')
|
||||
logging.warning(f"Bad Token: {token}")
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail='You are not authorized to patch mlb players. This event has been logged.'
|
||||
detail="You are not authorized to patch mlb players. This event has been logged.",
|
||||
)
|
||||
|
||||
this_player = SbaPlayer.get_or_none(SbaPlayer.id == player_id)
|
||||
if this_player is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'SbaPlayer id {player_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"SbaPlayer id {player_id} not found"
|
||||
)
|
||||
|
||||
if first_name is not None:
|
||||
this_player.first_name = first_name
|
||||
@ -152,33 +172,38 @@ async def patch_player(
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=418,
|
||||
detail='Well slap my ass and call me a teapot; I could not save that player'
|
||||
detail="Well slap my ass and call me a teapot; I could not save that player",
|
||||
)
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_players(players: PlayerList, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logging.warning(f'Bad Token: {token}')
|
||||
logging.warning(f"Bad Token: {token}")
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail='You are not authorized to post mlb players. This event has been logged.'
|
||||
detail="You are not authorized to post mlb players. This event has been logged.",
|
||||
)
|
||||
|
||||
new_players = []
|
||||
for x in players.players:
|
||||
dupes = SbaPlayer.select().where(
|
||||
((SbaPlayer.key_fangraphs == x.key_fangraphs) & (x.key_fangraphs is not None)) | ((SbaPlayer.key_mlbam == x.key_mlbam) & (x.key_mlbam is not None)) |
|
||||
((SbaPlayer.key_retro == x.key_retro) & (x.key_retro is not None)) | ((SbaPlayer.key_bbref == x.key_bbref) & (x.key_bbref is not None))
|
||||
(
|
||||
(SbaPlayer.key_fangraphs == x.key_fangraphs)
|
||||
& (x.key_fangraphs is not None)
|
||||
)
|
||||
| ((SbaPlayer.key_mlbam == x.key_mlbam) & (x.key_mlbam is not None))
|
||||
| ((SbaPlayer.key_retro == x.key_retro) & (x.key_retro is not None))
|
||||
| ((SbaPlayer.key_bbref == x.key_bbref) & (x.key_bbref is not None))
|
||||
)
|
||||
if dupes.count() > 0:
|
||||
logger.error(f'Found a dupe for {x}')
|
||||
logger.error(f"Found a dupe for {x}")
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f'{x.first_name} {x.last_name} has a key already in the database'
|
||||
detail=f"{x.first_name} {x.last_name} has a key already in the database",
|
||||
)
|
||||
|
||||
new_players.append(x.model_dump())
|
||||
@ -188,32 +213,33 @@ async def post_players(players: PlayerList, token: str = Depends(oauth2_scheme))
|
||||
SbaPlayer.insert_many(batch).on_conflict_ignore().execute()
|
||||
db.close()
|
||||
|
||||
return f'Inserted {len(new_players)} new MLB players'
|
||||
return f"Inserted {len(new_players)} new MLB players"
|
||||
|
||||
|
||||
@router.post('/one', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/one", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_one_player(player: SbaPlayerModel, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logging.warning(f'Bad Token: {token}')
|
||||
logging.warning(f"Bad Token: {token}")
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail='You are not authorized to post mlb players. This event has been logged.'
|
||||
detail="You are not authorized to post mlb players. This event has been logged.",
|
||||
)
|
||||
|
||||
dupes = SbaPlayer.select().where(
|
||||
(SbaPlayer.key_fangraphs == player.key_fangraphs) | (SbaPlayer.key_mlbam == player.key_mlbam) |
|
||||
(SbaPlayer.key_bbref == player.key_bbref)
|
||||
(SbaPlayer.key_fangraphs == player.key_fangraphs)
|
||||
| (SbaPlayer.key_mlbam == player.key_mlbam)
|
||||
| (SbaPlayer.key_bbref == player.key_bbref)
|
||||
)
|
||||
if dupes.count() > 0:
|
||||
logging.info(f'POST /SbaPlayers/one - dupes found:')
|
||||
logging.info(f"POST /SbaPlayers/one - dupes found:")
|
||||
for x in dupes:
|
||||
logging.info(f'{x}')
|
||||
logging.info(f"{x}")
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f'{player.first_name} {player.last_name} has a key already in the database'
|
||||
detail=f"{player.first_name} {player.last_name} has a key already in the database",
|
||||
)
|
||||
|
||||
new_player = SbaPlayer(**player.dict())
|
||||
@ -226,30 +252,34 @@ async def post_one_player(player: SbaPlayerModel, token: str = Depends(oauth2_sc
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=418,
|
||||
detail='Well slap my ass and call me a teapot; I could not save that player'
|
||||
detail="Well slap my ass and call me a teapot; I could not save that player",
|
||||
)
|
||||
|
||||
|
||||
@router.delete('/{player_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{player_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_player(player_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logging.warning(f'Bad Token: {token}')
|
||||
logging.warning(f"Bad Token: {token}")
|
||||
db.close()
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail='You are not authorized to delete mlb players. This event has been logged.'
|
||||
detail="You are not authorized to delete mlb players. This event has been logged.",
|
||||
)
|
||||
|
||||
this_player = SbaPlayer.get_or_none(SbaPlayer.id == player_id)
|
||||
if this_player is None:
|
||||
db.close()
|
||||
raise HTTPException(status_code=404, detail=f'SbaPlayer id {player_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"SbaPlayer id {player_id} not found"
|
||||
)
|
||||
|
||||
count = this_player.delete_instance()
|
||||
db.close()
|
||||
|
||||
if count == 1:
|
||||
return f'Player {player_id} has been deleted'
|
||||
return f"Player {player_id} has been deleted"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'Player {player_id} was not deleted')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Player {player_id} was not deleted"
|
||||
)
|
||||
|
||||
@ -4,15 +4,17 @@ import logging
|
||||
import pydantic
|
||||
|
||||
from ..db_engine import db, Schedule, Team, model_to_dict, chunked
|
||||
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
router = APIRouter(
|
||||
prefix='/api/v3/schedules',
|
||||
tags=['schedules']
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
valid_token,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
router = APIRouter(prefix="/api/v3/schedules", tags=["schedules"])
|
||||
|
||||
|
||||
class ScheduleModel(pydantic.BaseModel):
|
||||
week: int
|
||||
@ -26,12 +28,17 @@ class ScheduleList(pydantic.BaseModel):
|
||||
schedules: List[ScheduleModel]
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
async def get_schedules(
|
||||
season: int, team_abbrev: list = Query(default=None), away_abbrev: list = Query(default=None),
|
||||
home_abbrev: list = Query(default=None), week_start: Optional[int] = None, week_end: Optional[int] = None,
|
||||
short_output: Optional[bool] = True):
|
||||
season: int,
|
||||
team_abbrev: list = Query(default=None),
|
||||
away_abbrev: list = Query(default=None),
|
||||
home_abbrev: list = Query(default=None),
|
||||
week_start: Optional[int] = None,
|
||||
week_end: Optional[int] = None,
|
||||
short_output: Optional[bool] = True,
|
||||
):
|
||||
all_sched = Schedule.select_season(season)
|
||||
|
||||
if team_abbrev is not None:
|
||||
@ -63,14 +70,14 @@ async def get_schedules(
|
||||
all_sched = all_sched.order_by(Schedule.id)
|
||||
|
||||
return_sched = {
|
||||
'count': all_sched.count(),
|
||||
'schedules': [model_to_dict(x, recurse=not short_output) for x in all_sched]
|
||||
"count": all_sched.count(),
|
||||
"schedules": [model_to_dict(x, recurse=not short_output) for x in all_sched],
|
||||
}
|
||||
db.close()
|
||||
return return_sched
|
||||
|
||||
|
||||
@router.get('/{schedule_id}')
|
||||
@router.get("/{schedule_id}")
|
||||
@handle_db_errors
|
||||
async def get_one_schedule(schedule_id: int):
|
||||
this_sched = Schedule.get_or_none(Schedule.id == schedule_id)
|
||||
@ -82,19 +89,26 @@ async def get_one_schedule(schedule_id: int):
|
||||
return r_sched
|
||||
|
||||
|
||||
@router.patch('/{schedule_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.patch("/{schedule_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def patch_schedule(
|
||||
schedule_id: int, week: list = Query(default=None), awayteam_id: Optional[int] = None,
|
||||
hometeam_id: Optional[int] = None, gamecount: Optional[int] = None, season: Optional[int] = None,
|
||||
token: str = Depends(oauth2_scheme)):
|
||||
schedule_id: int,
|
||||
week: list = Query(default=None),
|
||||
awayteam_id: Optional[int] = None,
|
||||
hometeam_id: Optional[int] = None,
|
||||
gamecount: Optional[int] = None,
|
||||
season: Optional[int] = None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'patch_schedule - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"patch_schedule - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_sched = Schedule.get_or_none(Schedule.id == schedule_id)
|
||||
if this_sched is None:
|
||||
raise HTTPException(status_code=404, detail=f'Schedule ID {schedule_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Schedule ID {schedule_id} not found"
|
||||
)
|
||||
|
||||
if week is not None:
|
||||
this_sched.week = week
|
||||
@ -117,22 +131,28 @@ async def patch_schedule(
|
||||
return r_sched
|
||||
else:
|
||||
db.close()
|
||||
raise HTTPException(status_code=500, detail=f'Unable to patch schedule {schedule_id}')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unable to patch schedule {schedule_id}"
|
||||
)
|
||||
|
||||
|
||||
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_schedules(sched_list: ScheduleList, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'post_schedules - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"post_schedules - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
new_sched = []
|
||||
for x in sched_list.schedules:
|
||||
if Team.get_or_none(Team.id == x.awayteam_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Team ID {x.awayteam_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Team ID {x.awayteam_id} not found"
|
||||
)
|
||||
if Team.get_or_none(Team.id == x.hometeam_id) is None:
|
||||
raise HTTPException(status_code=404, detail=f'Team ID {x.hometeam_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Team ID {x.hometeam_id} not found"
|
||||
)
|
||||
|
||||
new_sched.append(x.dict())
|
||||
|
||||
@ -141,24 +161,28 @@ async def post_schedules(sched_list: ScheduleList, token: str = Depends(oauth2_s
|
||||
Schedule.insert_many(batch).on_conflict_ignore().execute()
|
||||
db.close()
|
||||
|
||||
return f'Inserted {len(new_sched)} schedules'
|
||||
return f"Inserted {len(new_sched)} schedules"
|
||||
|
||||
|
||||
@router.delete('/{schedule_id}', include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.delete("/{schedule_id}", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def delete_schedule(schedule_id: int, token: str = Depends(oauth2_scheme)):
|
||||
if not valid_token(token):
|
||||
logger.warning(f'delete_schedule - Bad Token: {token}')
|
||||
raise HTTPException(status_code=401, detail='Unauthorized')
|
||||
logger.warning(f"delete_schedule - Bad Token: {token}")
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
|
||||
this_sched = Schedule.get_or_none(Schedule.id == schedule_id)
|
||||
if this_sched is None:
|
||||
raise HTTPException(status_code=404, detail=f'Schedule ID {schedule_id} not found')
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Schedule ID {schedule_id} not found"
|
||||
)
|
||||
|
||||
count = this_sched.delete_instance()
|
||||
db.close()
|
||||
|
||||
if count == 1:
|
||||
return f'Schedule {this_sched} has been deleted'
|
||||
return f"Schedule {this_sched} has been deleted"
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f'Schedule {this_sched} could not be deleted')
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Schedule {this_sched} could not be deleted"
|
||||
)
|
||||
|
||||
@ -230,7 +230,7 @@ async def patch_game(
|
||||
raise HTTPException(status_code=500, detail=f"Unable to patch game {game_id}")
|
||||
|
||||
|
||||
@router.post("", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_games(game_list: GameList, token: str = Depends(oauth2_scheme)) -> Any:
|
||||
if not valid_token(token):
|
||||
|
||||
@ -6,16 +6,21 @@ Thin HTTP layer using TeamService for business logic.
|
||||
from fastapi import APIRouter, Query, Response, Depends
|
||||
from typing import List, Optional, Literal
|
||||
|
||||
from ..dependencies import oauth2_scheme, PRIVATE_IN_SCHEMA, handle_db_errors, cache_result
|
||||
from ..dependencies import (
|
||||
oauth2_scheme,
|
||||
PRIVATE_IN_SCHEMA,
|
||||
handle_db_errors,
|
||||
cache_result,
|
||||
)
|
||||
from ..services.base import BaseService
|
||||
from ..services.team_service import TeamService
|
||||
|
||||
router = APIRouter(prefix='/api/v3/teams', tags=['teams'])
|
||||
router = APIRouter(prefix="/api/v3/teams", tags=["teams"])
|
||||
|
||||
|
||||
@router.get('')
|
||||
@router.get("")
|
||||
@handle_db_errors
|
||||
@cache_result(ttl=10*60, key_prefix='teams')
|
||||
@cache_result(ttl=10 * 60, key_prefix="teams")
|
||||
async def get_teams(
|
||||
season: Optional[int] = None,
|
||||
owner_id: list = Query(default=None),
|
||||
@ -23,7 +28,7 @@ async def get_teams(
|
||||
team_abbrev: list = Query(default=None),
|
||||
active_only: Optional[bool] = False,
|
||||
short_output: Optional[bool] = False,
|
||||
csv: Optional[bool] = False
|
||||
csv: Optional[bool] = False,
|
||||
):
|
||||
"""Get teams with filtering."""
|
||||
result = TeamService.get_teams(
|
||||
@ -33,46 +38,41 @@ async def get_teams(
|
||||
team_abbrev=team_abbrev if team_abbrev else None,
|
||||
active_only=active_only or False,
|
||||
short_output=short_output or False,
|
||||
as_csv=csv or False
|
||||
as_csv=csv or False,
|
||||
)
|
||||
|
||||
if csv:
|
||||
return Response(content=result, media_type='text/csv')
|
||||
return Response(content=result, media_type="text/csv")
|
||||
return result
|
||||
|
||||
|
||||
@router.get('/{team_id}')
|
||||
@router.get("/{team_id}")
|
||||
@handle_db_errors
|
||||
@cache_result(ttl=30*60, key_prefix='team')
|
||||
@cache_result(ttl=30 * 60, key_prefix="team")
|
||||
async def get_one_team(team_id: int):
|
||||
"""Get a single team by ID."""
|
||||
return TeamService.get_team(team_id)
|
||||
|
||||
|
||||
@router.get('/{team_id}/roster')
|
||||
@router.get("/{team_id}/roster")
|
||||
@handle_db_errors
|
||||
@cache_result(ttl=30*60, key_prefix='team-roster')
|
||||
async def get_team_roster_default(
|
||||
team_id: int,
|
||||
sort: Optional[str] = None
|
||||
):
|
||||
@cache_result(ttl=30 * 60, key_prefix="team-roster")
|
||||
async def get_team_roster_default(team_id: int, sort: Optional[str] = None):
|
||||
"""Get team roster with IL lists (defaults to current season)."""
|
||||
return TeamService.get_team_roster(team_id, 'current', sort=sort)
|
||||
return TeamService.get_team_roster(team_id, "current", sort=sort)
|
||||
|
||||
|
||||
@router.get('/{team_id}/roster/{which}')
|
||||
@router.get("/{team_id}/roster/{which}")
|
||||
@handle_db_errors
|
||||
@cache_result(ttl=30*60, key_prefix='team-roster')
|
||||
@cache_result(ttl=30 * 60, key_prefix="team-roster")
|
||||
async def get_team_roster(
|
||||
team_id: int,
|
||||
which: Literal['current', 'next'],
|
||||
sort: Optional[str] = None
|
||||
team_id: int, which: Literal["current", "next"], sort: Optional[str] = None
|
||||
):
|
||||
"""Get team roster with IL lists."""
|
||||
return TeamService.get_team_roster(team_id, which, sort=sort)
|
||||
|
||||
|
||||
@router.patch('/{team_id}')
|
||||
@router.patch("/{team_id}")
|
||||
async def patch_team(
|
||||
team_id: int,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
@ -95,11 +95,19 @@ async def patch_team(
|
||||
data = {
|
||||
key: value
|
||||
for key, value in {
|
||||
'manager1_id': manager1_id, 'manager2_id': manager2_id,
|
||||
'gmid': gmid, 'gmid2': gmid2, 'mascot': mascot,
|
||||
'stadium': stadium, 'thumbnail': thumbnail, 'color': color,
|
||||
'abbrev': abbrev, 'sname': sname, 'lname': lname,
|
||||
'dice_color': dice_color, 'division_id': division_id,
|
||||
"manager1_id": manager1_id,
|
||||
"manager2_id": manager2_id,
|
||||
"gmid": gmid,
|
||||
"gmid2": gmid2,
|
||||
"mascot": mascot,
|
||||
"stadium": stadium,
|
||||
"thumbnail": thumbnail,
|
||||
"color": color,
|
||||
"abbrev": abbrev,
|
||||
"sname": sname,
|
||||
"lname": lname,
|
||||
"dice_color": dice_color,
|
||||
"division_id": division_id,
|
||||
}.items()
|
||||
if value is not None
|
||||
}
|
||||
@ -107,19 +115,13 @@ async def patch_team(
|
||||
return TeamService.update_team(team_id, data, token)
|
||||
|
||||
|
||||
@router.post('')
|
||||
async def post_teams(
|
||||
team_list: dict,
|
||||
token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
@router.post("/")
|
||||
async def post_teams(team_list: dict, token: str = Depends(oauth2_scheme)):
|
||||
"""Create multiple teams."""
|
||||
return TeamService.create_teams(team_list.get("teams", []), token)
|
||||
|
||||
|
||||
@router.delete('/{team_id}')
|
||||
async def delete_team(
|
||||
team_id: int,
|
||||
token: str = Depends(oauth2_scheme)
|
||||
):
|
||||
@router.delete("/{team_id}")
|
||||
async def delete_team(team_id: int, token: str = Depends(oauth2_scheme)):
|
||||
"""Delete a team."""
|
||||
return TeamService.delete_team(team_id, token)
|
||||
|
||||
@ -132,7 +132,7 @@ async def patch_transactions(
|
||||
return f"Updated {these_moves.count()} transactions"
|
||||
|
||||
|
||||
@router.post("", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@router.post("/", include_in_schema=PRIVATE_IN_SCHEMA)
|
||||
@handle_db_errors
|
||||
async def post_transactions(
|
||||
moves: TransactionList, token: str = Depends(oauth2_scheme)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user