paper-dynasty-database/app/routers_v2/mlbplayers.py
Cal Corum 17416cd50f Log mlbplayer dupes
Update cardsets for season 8
2024-11-02 23:44:32 -05:00

326 lines
11 KiB
Python

import datetime
import random
from fastapi import APIRouter, Depends, HTTPException, Response, Query
from typing import Optional, List
import logging
import pydantic
from pandas import DataFrame
from ..db_engine import db, MlbPlayer, Player, BattingCard, PitchingCard, model_to_dict, fn, chunked, query_to_csv
from ..dependencies import oauth2_scheme, valid_token, LOG_DATA
logging.basicConfig(
filename=LOG_DATA['filename'],
format=LOG_DATA['format'],
level=LOG_DATA['log_level']
)
router = APIRouter(
prefix='/api/v2/mlbplayers',
tags=['mlbplayers']
)
class PlayerModel(pydantic.BaseModel):
first_name: str
last_name: str
key_mlbam: int
key_fangraphs: int = None
key_bbref: str = None
key_retro: str = None
offense_col: int = random.randint(1, 3)
class PlayerList(pydantic.BaseModel):
players: List[PlayerModel]
def update_card_urls(mlbplayer: MlbPlayer):
logging.info(f'Updating cards for mlbplayer: {mlbplayer.first_name} {mlbplayer.last_name} ({mlbplayer.key_bbref})')
now = datetime.datetime.now()
c1_update = Player.update({
Player.image: Player.image.name.split('?d=')[0] + f'?d={now.year}-{now.month}-{now.day}'
}).where(Player.mlbplayer_id == mlbplayer.id)
count = c1_update.execute()
logging.info(f'Updated {count} image1s')
c2_update = Player.update({
Player.image2: Player.image2.name.split('?d=')[0] + f'{now.year}-{now.month}-{now.day}'
}).where((Player.mlbplayer_id == mlbplayer.id) & (Player.image2.is_null(False)))
count2 = c2_update.execute()
logging.info(f'Updated {count2} image2s')
return count + count2
@router.get('')
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), offense_col: list = Query(default=None), csv: Optional[bool] = False):
all_players = MlbPlayer.select()
if full_name is not None:
name_list = [x.lower() for x in full_name]
all_players = all_players.where(
fn.lower(MlbPlayer.first_name) + ' ' + fn.lower(MlbPlayer.last_name) << name_list
)
if first_name is not None:
name_list = [x.lower() for x in first_name]
all_players = all_players.where(fn.lower(MlbPlayer.first_name) << name_list)
if last_name is not None:
name_list = [x.lower() for x in last_name]
all_players = all_players.where(fn.lower(MlbPlayer.last_name) << name_list)
if key_fangraphs is not None:
all_players = all_players.where(MlbPlayer.key_fangraphs << key_fangraphs)
if key_bbref is not None:
name_list = [x.lower() for x in key_bbref]
all_players = all_players.where(fn.lower(MlbPlayer.key_bbref) << name_list)
if key_retro is not None:
name_list = [x.lower() for x in key_retro]
all_players = all_players.where(fn.lower(MlbPlayer.key_retro) << name_list)
if key_mlbam is not None:
all_players = all_players.where(MlbPlayer.key_mlbam << key_mlbam)
if offense_col is not None:
all_players = all_players.where(MlbPlayer.offense_col << offense_col)
if csv:
return_val = query_to_csv(all_players)
db.close()
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
]}
db.close()
return return_val
@router.get('/{player_id}')
async def get_one_player(player_id: int):
this_player = MlbPlayer.get_or_none(MlbPlayer.id == player_id)
if this_player is None:
db.close()
raise HTTPException(status_code=404, detail=f'MlbPlayer id {player_id} not found')
r_data = model_to_dict(this_player)
db.close()
return r_data
@router.patch('/{player_id}')
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, offense_col: Optional[str] = None, token: str = Depends(oauth2_scheme)):
if not valid_token(token):
logging.warning(f'Bad Token: {token}')
db.close()
raise HTTPException(
status_code=401,
detail='You are not authorized to patch mlb players. This event has been logged.'
)
this_player = MlbPlayer.get_or_none(MlbPlayer.id == player_id)
if this_player is None:
db.close()
raise HTTPException(status_code=404, detail=f'MlbPlayer id {player_id} not found')
if first_name is not None:
this_player.first_name = first_name
if last_name is not None:
this_player.last_name = last_name
if key_fangraphs is not None:
this_player.key_fangraphs = key_fangraphs
if key_bbref is not None:
this_player.key_bbref = key_bbref
if key_retro is not None:
this_player.key_retro = key_retro
if key_mlbam is not None:
this_player.key_mlbam = key_mlbam
if offense_col is not None:
this_player.offense_col = offense_col
if this_player.save() == 1:
return_val = model_to_dict(this_player)
db.close()
return return_val
else:
db.close()
raise HTTPException(
status_code=418,
detail='Well slap my ass and call me a teapot; I could not save that player'
)
@router.post('')
async def post_players(players: PlayerList, token: str = Depends(oauth2_scheme)):
if not valid_token(token):
logging.warning(f'Bad Token: {token}')
db.close()
raise HTTPException(
status_code=401,
detail='You are not authorized to post mlb players. This event has been logged.'
)
new_players = []
for x in players.players:
dupes = MlbPlayer.select().where(
(MlbPlayer.key_fangraphs == x.key_fangraphs) | (MlbPlayer.key_mlbam == x.key_mlbam) |
(MlbPlayer.key_retro == x.key_retro) | (MlbPlayer.key_bbref == x.key_bbref)
)
if dupes.count() > 0:
db.close()
raise HTTPException(
status_code=400,
detail=f'{x.first_name} {x.last_name} has a key already in the database'
)
new_players.append(x.dict())
with db.atomic():
for batch in chunked(new_players, 15):
MlbPlayer.insert_many(batch).on_conflict_replace().execute()
db.close()
return f'Inserted {len(new_players)} new MLB players'
@router.post('/one')
async def post_one_player(player: PlayerModel, token: str = Depends(oauth2_scheme)):
if not valid_token(token):
logging.warning(f'Bad Token: {token}')
db.close()
raise HTTPException(
status_code=401,
detail='You are not authorized to post mlb players. This event has been logged.'
)
dupes = MlbPlayer.select().where(
(MlbPlayer.key_fangraphs == player.key_fangraphs) | (MlbPlayer.key_mlbam == player.key_mlbam) |
(MlbPlayer.key_bbref == player.key_bbref)
)
if dupes.count() > 0:
logging.info(f'POST /mlbplayers/one - dupes found:')
for x in dupes:
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'
)
new_player = MlbPlayer(**player.dict())
saved = new_player.save()
if saved == 1:
return_val = model_to_dict(new_player)
db.close()
return return_val
else:
raise HTTPException(
status_code=418,
detail='Well slap my ass and call me a teapot; I could not save that player'
)
@router.delete('/{player_id}')
async def delete_player(player_id: int, token: str = Depends(oauth2_scheme)):
if not valid_token(token):
logging.warning(f'Bad Token: {token}')
db.close()
raise HTTPException(
status_code=401,
detail='You are not authorized to delete mlb players. This event has been logged.'
)
this_player = MlbPlayer.get_or_none(MlbPlayer.id == player_id)
if this_player is None:
db.close()
raise HTTPException(status_code=404, detail=f'MlbPlayer id {player_id} not found')
count = this_player.delete_instance()
db.close()
if count == 1:
raise HTTPException(status_code=200, detail=f'Player {player_id} has been deleted')
else:
raise HTTPException(status_code=500, detail=f'Player {player_id} was not deleted')
@router.post('/update-cols')
@router.post('/update-cols/{mlbplayer_id}')
async def update_columns(mlbplayer_id: Optional[int] = None, token: str = Depends(oauth2_scheme)):
if not valid_token(token):
logging.warning(f'Bad Token: {token}')
db.close()
raise HTTPException(
status_code=401,
detail='You are not authorized to update mlb players. This event has been logged.'
)
p_query = MlbPlayer.select()
if mlbplayer_id is not None:
p_query = p_query.where(MlbPlayer.id == mlbplayer_id)
total_count = 0
for x in p_query:
all_players = Player.select().where(Player.mlbplayer == x)
bc_update = BattingCard.update({
BattingCard.offense_col: x.offense_col,
}).where((BattingCard.player << all_players) & (BattingCard.offense_col != x.offense_col))
count = bc_update.execute()
total_count += count
logging.info(f'Updated {count} batting cards for {x.first_name} {x.last_name}')
update_card_urls(x)
db.close()
return f'Updated {total_count} batting cards'
@router.post('/update-names')
@router.post('/update-names/{mlbplayer_id}')
async def update_names(mlbplayer_id: Optional[int] = None, token: str = Depends(oauth2_scheme)):
if not valid_token(token):
logging.warning(f'Bad Token: {token}')
db.close()
raise HTTPException(
status_code=401,
detail='You are not authorized to update mlb players. This event has been logged.'
)
p_query = MlbPlayer.select()
if mlbplayer_id is not None:
p_query = p_query.where(MlbPlayer.id == mlbplayer_id)
total_count = 0
for x in p_query:
p_update = Player.update({
Player.p_name: f'{x.first_name} {x.last_name}'
}).where((Player.mlbplayer == x) & (Player.p_name != f'{x.first_name} {x.last_name}'))
count = p_update.execute()
total_count += count
logging.info(f'Update {count} player records for {x.first_name} {x.last_name}')
update_card_urls(x)
db.close()
return f'Updated {total_count} names'
# @router.post('/link-players')
# async def post_players(token: str = Depends(oauth2_scheme)):
# if not valid_token(token):
# logging.warning(f'Bad Token: {token}')
# db.close()
# raise HTTPException(
# status_code=401,
# detail='You are not authorized to link mlb players. This event has been logged.'
# )
#
# for x in Player.select().where(Player.mlbplayer.is_null()):
# p_query = MlbPlayer.get_or_none(MlbPlayer.key_bbref == x.key_bbref)
# if p_query is not None:
# x.mlbplayer = p_query
# x.save()