Skip to content

Commit

Permalink
v1.0
Browse files Browse the repository at this point in the history
### Platform
FIX: Web interface inaccessible when AUTH_TYPE=None
FIX: Basic and None authentication options were not providing access to bots (no user-specific privileges will be honored for either of these options now).
FIX: Error when creating bot with AUTH_TYPE=None (see #13 for other known issues)
FIX: Bot config import fails for big config file
FIX: Refresh token not saved when creating a new reddit authorization
ENH: Game Threads bot label changed to MLB Game Threads
NEW: NFL Game Thread Bot (v1.0-alpha)
VER: 1.0
DBVER: 5

### MLB Game Threads
FIX: Errors in gumbo data patch process
FIX: Comment thread crashing when isScoringPlay is missing from data
FIX: Off thread sometimes unstickied prematurely
FIX: Comment body sometimes lists wrong team as leading
FIX: Scoring play list missing from game/post threads
FIX: Unwanted comments for other team's plays
FIX: Line score showed 0 for new inning earlier than MLB does
FIX: Hide weather conditions if only dummy data is published
FIX: Gameday thread update loop never ends if game gets postponed before game thread is posted and UPDATE_UNTIL="Game thread is posted"
FIX: GameDay and Game threads get posted when bot is restarted after game is postponed
FIX: Error getting bot state when gameday/game threads are skipped
FIX: DH Game 2 game thread does not post
FIX: Straight DH Game 2 shows wrong game date/time
FIX: Game thread update process crashes for DH G2 before G1 is final
FIX: DH Game 2 fails to match DH Game 1 when home/away teams flip
FIX: DH Game 2 using stale status for Game 1
FIX: Query error in check if all postgame threads are submitted (in order to skip gameday thread)
FIX: Bot thought season was suspended if restarted after all games ended
FIX: Don't default pitch count to 0-0 in comment body
ENH: Added custom date format and home/road win/loss and exception prefix settings for for thread titles
ENH: Wait 5 minutes after game 1 is final before posting game thread for straight DH game 2, to hopefully have updated records for thread title
ENH: Include game status in gameday thread
ENH: List runner and matchup info in game threads
ENH: Add locks to prevent multiple threads from updating data cache at the same time
ENH: Logging improvements
REM: Removed table holding game ids for game thread bots -- was not being used and was throwing an error for rescheduled games
INT: Better naming of scheduled tasks
VER: 1.0

### NFL Game Threads
VER: 1.0-alpha
  • Loading branch information
toddrob99 authored Aug 14, 2020
2 parents 3fe8ce4 + fe6f57a commit c3fafd7
Show file tree
Hide file tree
Showing 36 changed files with 5,459 additions and 464 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
**/.dockerignore
**/.env
**/.git
**/.github
**/.gitignore
**/.project
**/.settings
Expand Down
1,198 changes: 792 additions & 406 deletions bots/game_threads/__init__.py

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions bots/game_threads/templates/comment_body.mako
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ ${atBat['result']['description']}
% if len(atBat['pitchIndex']) > 0 and atBat['playEvents'][atBat['pitchIndex'][-1]].get('pitchData'):
## Event has pitch data

Pitch from ${atBat['matchup']['pitcher']['fullName']}: ${atBat['playEvents'][atBat['pitchIndex'][-1]].get('preCount',{}).get('balls','0')}-${atBat['playEvents'][atBat['pitchIndex'][-1]].get('preCount',{}).get('strikes','0')} ${atBat['playEvents'][atBat['pitchIndex'][-1]].get('details',{}).get('type',{}).get('description','Unknown pitch type')} @ ${atBat['playEvents'][atBat['pitchIndex'][-1]].get('pitchData',{}).get('startSpeed','-')} mph
Pitch from ${atBat['matchup']['pitcher']['fullName']}: \
% if atBat['playEvents'][atBat['pitchIndex'][-1]].get('preCount'): # preCount is no longer included in the data, so don't list pitch count as 0-0
${atBat['playEvents'][atBat['pitchIndex'][-1]].get('preCount',{}).get('balls','0')}-${atBat['playEvents'][atBat['pitchIndex'][-1]].get('preCount',{}).get('strikes','0')} \
% endif
${atBat['playEvents'][atBat['pitchIndex'][-1]].get('details',{}).get('type',{}).get('description','Unknown pitch type')} @ ${atBat['playEvents'][atBat['pitchIndex'][-1]].get('pitchData',{}).get('startSpeed','-')} mph
% endif
% if len(atBat['pitchIndex']) > 0 and atBat['playEvents'][atBat['pitchIndex'][-1]].get('hitData'):
## Event has hit data
Expand All @@ -67,7 +71,7 @@ Hit by ${atBat['matchup']['batter']['fullName']}: Launched ${atBat['playEvents']

${atBat['about']['halfInning'].capitalize()} ${atBat['about']['inning']} - \
${max(atBat['result']['homeScore'], atBat['result']['awayScore'])}-${min(atBat['result']['homeScore'], atBat['result']['awayScore'])}
${'TIE' if atBat['result']['homeScore'] == atBat['result']['awayScore'] else data[0]['myTeam']['teamName'] if atBat['result']['homeScore'] > atBat['result']['awayScore'] and data[gamePk]['homeAway']=='home' else data[gamePk]['oppTeam']['teamName']}
${'TIE' if atBat['result']['homeScore'] == atBat['result']['awayScore'] else data[0]['myTeam']['teamName'] if ((atBat['result']['homeScore'] > atBat['result']['awayScore'] and data[gamePk]['homeAway']=='home') or (atBat['result']['awayScore'] > atBat['result']['homeScore'] and data[gamePk]['homeAway']=='away')) else data[gamePk]['oppTeam']['teamName']}
% endif
% if settings.get("Comments", {}).get(("MYTEAM_BATTING_FOOTER_" if myTeamBatting else "MYTEAM_PITCHING_FOOTER_") + eventType.upper()):
## Footer is defined for this event
Expand Down
6 changes: 4 additions & 2 deletions bots/game_threads/templates/game_info.mako
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<%page args="gamePk" />
${'###'}Links & Info
## Venue & weather
% if data[gamePk]['schedule'].get('weather') and len(data[gamePk]['schedule']['weather']):
* Current conditions at ${data[gamePk]['schedule']['venue']['name']}: ${data[gamePk]['schedule']['weather']['temp']+'&#176;F' if data[gamePk]['schedule']['weather'].get('temp') else ''} ${'- ' + data[gamePk]['schedule']['weather']['condition'] if data[gamePk]['schedule']['weather'].get('condition') else ''} ${'- Wind ' + data[gamePk]['schedule']['weather']['wind'] if data[gamePk]['schedule']['weather'].get('wind') else ''}
% if data[gamePk]['schedule'].get('weather') and len(data[gamePk]['schedule']['weather']) and (data[gamePk]['schedule']['weather'].get('temp') or data[gamePk]['schedule']['weather'].get('condition') or data[gamePk]['schedule']['weather'].get('wind') != 'null mph, null'):
* Current conditions at ${data[gamePk]['schedule']['venue']['name']}: ${data[gamePk]['schedule']['weather']['temp']+'&#176;F' if data[gamePk]['schedule']['weather'].get('temp') else ''} ${'- ' + data[gamePk]['schedule']['weather']['condition'] if data[gamePk]['schedule']['weather'].get('condition') else ''} ${'- Wind ' + data[gamePk]['schedule']['weather']['wind'] if data[gamePk]['schedule']['weather'].get('wind') != 'null mph, null' else ''}
% else:
* Venue: ${data[gamePk]['schedule']['venue']['name']}
% endif
<%
awayTv = [x for x in data[gamePk]['schedule'].get('broadcasts', []) if x.get('type')=='TV' and x.get('homeAway')=='away' and not x.get('isNational',False)]
Expand Down
64 changes: 60 additions & 4 deletions bots/game_threads/templates/game_thread.mako
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,74 @@ ${'###'}Game Status: ${data[gamePk]['schedule']['status']['detailedState']} \
due to ${data[gamePk]['schedule']['status']['reason']} \
% endif
% if data[gamePk]['gameTime']['utc'] > datetime.utcnow().replace(tzinfo=pytz.utc) and data[gamePk]['schedule']['status']['abstractGameCode'] != 'F':
%if not (data[gamePk]['schedule']['doubleHeader'] == 'Y' and data[gamePk]['schedule']['gameNumber'] == 2):
- First Pitch is scheduled for ${data[gamePk]['gameTime']['myTeam'].strftime('%I:%M %p %Z')}

% endif
% elif (data[gamePk]['schedule']['status']['abstractGameCode'] == 'L' and data[gamePk]['schedule']['status']['statusCode'] != 'PW') or (data[gamePk]['schedule']['status']['abstractGameCode'] == 'F' and data[gamePk]['schedule']['status']['codedGameState'] not in ['C','D']):
## Game status is live and not warmup, so include info about inning and outs on the game status line
- <%include file="score.mako" />\
- <%include file="score.mako" /> \
% if data[gamePk]['schedule']['status']['abstractGameCode'] != 'F':
## Only include inning if game is in progress (status!=F since we're already inside the other condition)
- ${data[gamePk]['schedule']['linescore']['inningState']} of the ${data[gamePk]['schedule']['linescore']['currentInningOrdinal']} \
% endif
${'- ' + str(data[gamePk]['schedule']['linescore']['outs']) + ' out' + ('s' if data[gamePk]['schedule']['linescore']['outs'] != 1 else '') if data[gamePk]['schedule']['linescore']['outs'] < 3 else ''}

% if data[gamePk]['schedule']['linescore']['inningState'] == "Middle" and data[gamePk]['schedule']['linescore']['currentInningOrdinal'] == "7th":
Seventh inning stretch\
% else:
${data[gamePk]['schedule']['linescore']['inningState']} of the ${data[gamePk]['schedule']['linescore']['currentInningOrdinal']}\
% endif
## current pitcher/batter matchup, count, on deck, in hole -- or due up
<%
currentPlay = data[gamePk]['gumbo']["liveData"].get('plays',{}).get('currentPlay',{})
offense = data[gamePk]['gumbo']["liveData"].get('linescore',{}).get('offense',{})
defense = data[gamePk]['gumbo']["liveData"].get('linescore',{}).get('defense',{})
outs =currentPlay.get('count',{}).get('outs','0')
comingUpTeamName = data[gamePk]['schedule']['teams']['away']['team']['teamName'] if data[gamePk]['schedule']['teams']['away']['team']['id'] == offense.get('team',{}).get('id') else data[gamePk]['schedule']['teams']['home']['team']['teamName']
%>\
% if outs == 3:
% if offense.get('batter',{}).get('fullName'):
## due up batter is in the data, so include them
${' '}with ${offense.get('batter',{}).get('fullName','*Unknown*')}, \
${offense.get('onDeck',{}).get('fullName','*Unknown')}, \
and ${offense.get('inHole',{}).get('fullName','*Unknown')} \
due up for the ${comingUpTeamName}
% else:
## due up batter is not in the data, so just put the team name due up
with the ${comingUpTeamName} coming up to bat
% endif
% else:
## else condition from if outs == 3--inning is in progress, so list outs, runners, matchup, on deck, and in hole
## Outs
, ${data[gamePk]['schedule']['linescore']['outs']} out${'s' if data[gamePk]['schedule']['linescore']['outs'] != 1 else ''}\
<%
runners = (
"bases empty" if not offense.get('first') and not offense.get('second') and not offense.get('third')
else "runner on first" if offense.get('first') and not offense.get('second') and not offense.get('third')
else "runner on second" if not offense.get('first') and offense.get('second') and not offense.get('third')
else "runner on third" if not offense.get('first') and not offense.get('second') and offense.get('third')
else "runners on first and second" if offense.get('first') and offense.get('second') and not offense.get('third')
else "runners on first and third" if offense.get('first') and not offense.get('second') and offense.get('third')
else "runners on second and third" if not offense.get('first') and offense.get('second') and offense.get('third')
else "bases loaded" if offense.get('first') and offense.get('second') and offense.get('third')
else None
)
ondeck = offense.get('onDeck',{}).get('fullName')
inthehole = offense.get('inHole',{}).get('fullName')
%>\
${(', ' + runners) if runners else ''}\
## Count
, ${currentPlay.get('count',{}).get('balls','0')}-${currentPlay.get('count',{}).get('strikes','0')} count \
## Matchup
with ${currentPlay.get('matchup',{}).get('pitcher',{}).get('fullName','*Unknown*')} pitching and ${currentPlay.get('matchup',{}).get('batter',{}).get('fullName','*Unknown*')} batting. \
## Ondeck
% if ondeck:
${ondeck} is on deck\
## In hole
% if inthehole:
, and ${inthehole} is in the hole.
% endif
% endif
% endif
% endif
% endif

## Broadcasts, gameday link, (strikezone map commented out since it doesn't seem to have data), (game notes commented out due to new press pass requirement)
Expand Down
11 changes: 10 additions & 1 deletion bots/game_threads/templates/game_title.mako
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<%
from datetime import datetime
prefix = settings.get("Game Thread", {}).get("TITLE_PREFIX","Game Thread:")
dateFormat = settings.get("Game Thread", {}).get("DATE_FORMAT","%a, %b %d @ %I:%M %p %Z")
dhDateFormat = settings.get("Game Thread", {}).get("DATE_FORMAT_DH","%a, %b %d")
%>\
${prefix + (" " if len(prefix) and not prefix.endswith(" ") else "")}\
%if data[gamePk]['schedule'].get('seriesDescription') and data[gamePk]['schedule'].get('gameType') not in ['R','I','S','E']:
Expand All @@ -9,4 +11,11 @@ ${'Game ' + str(data[gamePk]['schedule']['seriesGameNumber']) + ' - ' if data[ga
%endif
${data[gamePk]['schedule']['teams']['away']['team']['teamName']} (${data[gamePk]['schedule']['teams']['away']['leagueRecord']['wins']}-${data[gamePk]['schedule']['teams']['away']['leagueRecord']['losses']})\
@ ${data[gamePk]['schedule']['teams']['home']['team']['teamName']} (${data[gamePk]['schedule']['teams']['home']['leagueRecord']['wins']}-${data[gamePk]['schedule']['teams']['home']['leagueRecord']['losses']})\
- ${data[gamePk]['gameTime']['myTeam'].strftime('%a, %b %d @ %I:%M %p %Z')}
%if data[gamePk]['schedule']['doubleHeader'] == 'Y' and data[gamePk]['schedule']['gameNumber'] == 2:
- ${data[gamePk]['gameTime']['myTeam'].strftime(dhDateFormat)} - Doubleheader Game 2
%else:
- ${data[gamePk]['gameTime']['myTeam'].strftime(dateFormat)}
%endif
%if data[gamePk]['schedule']['doubleHeader'] == 'S':
- Doubleheader Game ${data[gamePk]['schedule']['gameNumber']}
%endif
6 changes: 6 additions & 0 deletions bots/game_threads/templates/gameday_thread.mako
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ ${'###'}\
% endif\
<%include file="matchup.mako" args="gamePk=pk,dateFormat='%I:%M %p %Z'" />

## Game status: show detailed state and then list first pitch time if game hasn't started yet and isn't final
${'###'}Game Status: ${data[pk]['schedule']['status']['detailedState']} \
% if data[pk]['schedule']['status'].get('reason') and len(data[pk]['schedule']['status']['reason']) > 0 and data[pk]['schedule']['status']['reason'] not in data[pk]['schedule']['status']['detailedState']:
due to ${data[pk]['schedule']['status']['reason']} \
% endif

## Broadcasts, gameday link, (strikezone map commented out since it doesn't seem to have data), (game notes commented out due to new press pass requirement)
<%include file="game_info.mako" args="gamePk=pk" />

Expand Down
3 changes: 2 additions & 1 deletion bots/game_threads/templates/gameday_title.mako
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<%
from datetime import datetime
prefix = settings.get("Game Day Thread", {}).get("TITLE_PREFIX","Game Day Thread")
dateFormat = settings.get("Game Day Thread", {}).get("DATE_FORMAT","%A, %B %d")
%>\
${data[0]['myTeam']['teamName']} ${prefix + (" " if len(prefix) and not prefix.endswith(" ") else "")}- ${datetime.strptime(data[0]['today']['Ymd'],'%Y%m%d').strftime('%A, %B %d')}
${data[0]['myTeam']['teamName']} ${prefix + (" " if len(prefix) and not prefix.endswith(" ") else "")}- ${datetime.strptime(data[0]['today']['Ymd'],'%Y%m%d').strftime(dateFormat)}
4 changes: 2 additions & 2 deletions bots/game_threads/templates/linescore.mako
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
away = []
for i in data[gamePk]['schedule']['linescore']['innings']:
header_row.append(str(i['num']))
away.append(str(i['away'].get('runs',0)))
home.append(str(i['home'].get('runs',0)))
away.append(str(i['away'].get('runs','')))
home.append(str(i['home'].get('runs','')))
if len(data[gamePk]['schedule']['linescore']['innings']) < 9:
for i in range(len(data[gamePk]['schedule']['linescore']['innings'])+1, 10):
Expand Down
10 changes: 9 additions & 1 deletion bots/game_threads/templates/matchup.mako
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
<%page args="gamePk,dateFormat='%a, %b %d @ %I:%M %p %Z'" />\
## Matchup header: Team names with links to team subs and matchup image, followed by game date
[${data[gamePk]['schedule']['teams']['away']['team']['teamName']}](${data[0]['teamSubs'].get(data[gamePk]['schedule']['teams']['away']['team']['id'], data[0]['teamSubs'][0])}) [@](http://mlb.mlb.com/images/2017_ipad/684/${data[gamePk]['schedule']['teams']['away']['team']['fileCode'] + data[gamePk]['schedule']['teams']['home']['team']['fileCode']}_684.jpg) [${data[gamePk]['schedule']['teams']['home']['team']['teamName']}](${data[0]['teamSubs'].get(data[gamePk]['schedule']['teams']['home']['team']['id'], data[0]['teamSubs'][0])}) - ${data[gamePk]['gameTime']['myTeam'].strftime(dateFormat)}
[${data[gamePk]['schedule']['teams']['away']['team']['teamName']}](${data[0]['teamSubs'].get(data[gamePk]['schedule']['teams']['away']['team']['id'], data[0]['teamSubs'][0])}) [@](http://mlb.mlb.com/images/2017_ipad/684/${data[gamePk]['schedule']['teams']['away']['team']['fileCode'] + data[gamePk]['schedule']['teams']['home']['team']['fileCode']}_684.jpg) [${data[gamePk]['schedule']['teams']['home']['team']['teamName']}](${data[0]['teamSubs'].get(data[gamePk]['schedule']['teams']['home']['team']['id'], data[0]['teamSubs'][0])}) \
%if data[gamePk]['schedule']['doubleHeader'] == 'Y' and data[gamePk]['schedule']['gameNumber'] == 2:
- ${data[gamePk]['gameTime']['myTeam'].strftime('%a, %b %d')} - Doubleheader Game 2
%else:
- ${data[gamePk]['gameTime']['myTeam'].strftime(dateFormat)} \
%endif
%if data[gamePk]['schedule']['doubleHeader'] == 'S':
- Doubleheader Game ${data[gamePk]['schedule']['gameNumber']}
%endif
5 changes: 3 additions & 2 deletions bots/game_threads/templates/off_title.mako
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<%
from datetime import datetime
prefix = settings.get("Off Day Thread", {}).get("TITLE_PREFIX","Off Day Thread")
prefix = settings.get("Off Day Thread", {}).get("TITLE_PREFIX","Off Day Thread")
dateFormat = settings.get("Off Day Thread", {}).get("DATE_FORMAT","%A, %B %d")
%>\
${data[0]['myTeam']['teamName']} \
${prefix if data[0]['myTeam']['seasonState'] in ['pre','regular','post:in'] else ''}\
${'Postseason Discussion Thread' if data[0]['myTeam']['seasonState'] == 'post:out' else ''}\
${'Offseason Discussion Thread' if data[0]['myTeam']['seasonState'].startswith('off') else ''}\
- ${datetime.strptime(data[0]['today']['Ymd'],'%Y%m%d').strftime('%A, %B %d')}
- ${datetime.strptime(data[0]['today']['Ymd'],'%Y%m%d').strftime(dateFormat)}
Loading

0 comments on commit c3fafd7

Please sign in to comment.