mirror of
https://github.com/oddluck/limnoria-plugins.git
synced 2025-04-26 13:01:09 -05:00
271 lines
13 KiB
Python
271 lines
13 KiB
Python
###
|
|
# Copyright (c) 2018, cottongin
|
|
# Copyright (c) 2020, oddluck <oddluck@riseup.net>
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are met:
|
|
#
|
|
# * Redistributions of source code must retain the above copyright notice,
|
|
# this list of conditions, and the following disclaimer.
|
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
# this list of conditions, and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
# * Neither the name of the author of this software nor the name of
|
|
# contributors to this software may be used to endorse or promote products
|
|
# derived from this software without specific prior written consent.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
###
|
|
|
|
import pendulum
|
|
import requests
|
|
import collections
|
|
|
|
from supybot import utils, plugins, ircutils, callbacks, conf, schedule, ircmsgs
|
|
from supybot.commands import *
|
|
try:
|
|
from supybot.i18n import PluginInternationalization
|
|
_ = PluginInternationalization('CBB')
|
|
except ImportError:
|
|
# Placeholder that allows to run the plugin on a bot
|
|
# without the i18n module
|
|
_ = lambda x: x
|
|
|
|
SCOREBOARD = ('http://site.api.espn.com/apis/site/v2/sports/basketball/'
|
|
'mens-college-basketball/scoreboard?lang=en®ion=us'
|
|
'&calendartype=blacklist&limit=300&groups=50&dates={date}')
|
|
|
|
class CBB(callbacks.Plugin):
|
|
"""Fetches College Basketball scores"""
|
|
threaded = True
|
|
|
|
def __init__(self, irc):
|
|
self.__parent = super(CBB, self)
|
|
self.__parent.__init__(irc)
|
|
|
|
####################
|
|
# PUBLIC FUNCTIONS #
|
|
####################
|
|
|
|
@wrap([getopts({'date': 'somethingWithoutSpaces', 'all':''}),
|
|
optional('text')])
|
|
def cbb(self, irc, msg, args, options, team=None):
|
|
"""[--date] [--all] [team]
|
|
Fetches college basketball scores/schedule for given date and/or team.
|
|
Defaults to today and top 25 teams (if playing, otherwise shows all games).
|
|
Use --all to show results for all teams.
|
|
"""
|
|
channel = msg.args[0]
|
|
if channel == irc.nick:
|
|
channel = msg.nick
|
|
options = dict(options)
|
|
date = options.get('date')
|
|
if 'all' in options:
|
|
all = True
|
|
else:
|
|
all = False
|
|
if date:
|
|
if date.lower() in ['yesterday', 'tomorrow', 'today']:
|
|
if date.lower() in 'yesterday':
|
|
date = pendulum.yesterday().format('YYYYMMDD')
|
|
elif date.lower() in 'tomorrow':
|
|
date = pendulum.tomorrow().format('YYYYMMDD')
|
|
else:
|
|
date = pendulum.now().format('YYYYMMDD')
|
|
else:
|
|
try:
|
|
date = pendulum.parse(date, strict=False).format('YYYYMMDD')
|
|
except:
|
|
irc.reply('Invalid date format')
|
|
return
|
|
SCORES = self._checkscores(date)
|
|
if date not in SCORES:
|
|
niceDate = pendulum.parse(date)
|
|
niceDate = "{0}/{1}/{2}".format(niceDate.month, niceDate.day, niceDate.year)
|
|
irc.reply('No games found for {}.'.format(date))
|
|
else:
|
|
today = pendulum.now().format('YYYYMMDD')
|
|
yesterday = pendulum.yesterday().format('YYYYMMDD')
|
|
tomorrow = date = pendulum.tomorrow().format('YYYYMMDD')
|
|
SCORES = self._checkscores()
|
|
if today in SCORES:
|
|
date = today
|
|
elif yesterday in SCORES:
|
|
date = yesterday
|
|
elif tomorrow in SCORES:
|
|
date = tomorrow
|
|
else:
|
|
irc.reply('No games found.')
|
|
return
|
|
|
|
if team:
|
|
if len(team) > 2:
|
|
reply = []
|
|
# single team
|
|
for key,value in SCORES[date].items():
|
|
if team.lower() in value['lookup']['abbr'].lower():
|
|
#print(team.lower(), '\t', value['lookup']['abbr'].lower())
|
|
reply.append(value['long'])
|
|
#break
|
|
if not reply:
|
|
for key,value in SCORES[date].items():
|
|
if team.lower() in value['lookup']['full'].lower():
|
|
reply.append(value['long'])
|
|
#break
|
|
if not reply:
|
|
irc.reply('ERROR: no match found for your input: {}'.format(team))
|
|
return
|
|
else:
|
|
if len(reply) <= 4:
|
|
for item in reply:
|
|
irc.sendMsg(ircmsgs.privmsg(channel, item))
|
|
else:
|
|
for item in reply:
|
|
irc.reply(item)
|
|
return
|
|
else:
|
|
irc.reply('ERROR: search string too short')
|
|
return
|
|
else:
|
|
niceDate = pendulum.parse(date)
|
|
niceDate = "{0}/{1}/{2}".format(niceDate.month, niceDate.day, niceDate.year)
|
|
reply = ' | '.join(value['short'] for item,value in SCORES[date].items() if value['top25'])
|
|
if reply and not all:
|
|
irc.reply("Showing teams in the top 25 for {0}. Use --all to see more games.".format(niceDate), prefixNick = False)
|
|
irc.reply(reply, prefixNick = False)
|
|
else:
|
|
reply = ' | '.join(value['short'] for item,value in SCORES[date].items())
|
|
irc.reply("Showing all games for {0}.".format(niceDate), prefixNick = False)
|
|
irc.reply(reply, prefixNick = False)
|
|
return
|
|
|
|
return
|
|
|
|
######################
|
|
# INTERNAL FUNCTIONS #
|
|
######################
|
|
|
|
def _checkscores(self, cdate=None):
|
|
if cdate:
|
|
#today = pendulum.parse(cdate, strict=False).format('YYYYMMDD')
|
|
#yesterday = pendulum.parse(cdate, strict=False).subtract(days=1).format('YYYYMMDD')
|
|
#tomorrow = pendulum.parse(cdate, strict=False).add(days=1).format('YYYYMMDD')
|
|
dates = [cdate]
|
|
else:
|
|
today = pendulum.now().format('YYYYMMDD')
|
|
yesterday = pendulum.yesterday().format('YYYYMMDD')
|
|
tomorrow = pendulum.tomorrow().format('YYYYMMDD')
|
|
dates = [yesterday, today, tomorrow]
|
|
|
|
data = collections.OrderedDict()
|
|
for date in dates:
|
|
tmp = requests.get(SCOREBOARD.format(date=date)).json()
|
|
tmp_date = pendulum.parse(tmp['eventsDate']['date'],
|
|
strict=False).in_tz('US/Eastern').format('YYYYMMDD')
|
|
data[tmp_date] = tmp['events']
|
|
|
|
#print(data)
|
|
"""
|
|
'day': {'game1': {'short', 'long'},
|
|
'game2': {'short', 'long'}}
|
|
"""
|
|
games = collections.OrderedDict()
|
|
for day, d in data.items():
|
|
#print(day, d)
|
|
if d:
|
|
games[day] = collections.OrderedDict()
|
|
for event in d:
|
|
key = event['id']
|
|
lookup = {'abbr': '{}'.format(event['shortName']),
|
|
'full': '{}'.format(event['name'])}
|
|
comp = event['competitions'][0]
|
|
time = pendulum.parse(comp['date'], strict=False).in_tz('US/Eastern')
|
|
short_time = time.format('h:mm A zz')
|
|
long_time = time.format('dddd, MMM Do, h:mm A zz')
|
|
status = comp['status']['type']['state']
|
|
is_ended = comp['status']['type']['completed']
|
|
top25 = True if (0 < comp['competitors'][0]['curatedRank']['current'] <= 25
|
|
or 0 < comp['competitors'][1]['curatedRank']['current'] <= 25) else False
|
|
home_rank = '(#{})'.format(comp['competitors'][0]['curatedRank']['current']) \
|
|
if 0 < comp['competitors'][0]['curatedRank']['current'] <= 25 else ''
|
|
away_rank = '(#{})'.format(comp['competitors'][1]['curatedRank']['current']) \
|
|
if 0 < comp['competitors'][1]['curatedRank']['current'] <= 25 else ''
|
|
home_short = comp['competitors'][0]['team']['abbreviation']
|
|
home_long = comp['competitors'][0]['team']['displayName']
|
|
away_short = comp['competitors'][1]['team']['abbreviation']
|
|
away_long = comp['competitors'][1]['team']['displayName']
|
|
home_score = int(comp['competitors'][0]['score'])
|
|
away_score = int(comp['competitors'][1]['score'])
|
|
broadcasts = []
|
|
try:
|
|
for thing in comp['broadcasts']:
|
|
for station in thing['names']:
|
|
broadcasts.append(station)
|
|
except:
|
|
pass
|
|
#print(home_short, away_short, '\t||\t', top25, status, comp['competitors'][0]['curatedRank']['current'],
|
|
# comp['competitors'][1]['curatedRank']['current'])
|
|
if status == 'pre':
|
|
# pre
|
|
short = '{} @ {} {}'.format(away_short, home_short, short_time)
|
|
long = '{}{} @ {}{} | {}{}'.format(away_long, away_rank, home_long, home_rank, long_time,
|
|
" [TV: {}]".format(", ".join(broadcasts) if broadcasts else "")
|
|
)
|
|
else:
|
|
# inp
|
|
if is_ended:
|
|
clock_short = ircutils.mircColor('F', 'red')
|
|
clock_long = ircutils.mircColor('Final', 'red')
|
|
else:
|
|
if 'Halftime' in comp['status']['type']['detail']:
|
|
clock_short = ircutils.mircColor('HT', 'orange')
|
|
clock_long = ircutils.mircColor('Halftime', 'orange')
|
|
else:
|
|
clock_short = ircutils.mircColor(comp['status']['type']['shortDetail'].replace(' - ', ' '), 'green')
|
|
clock_long = ircutils.mircColor(comp['status']['type']['detail'], 'green')
|
|
try:
|
|
last_play = ' | \x02Last Play:\x02 {}'.format(comp['situation']['lastPlay']['text']) \
|
|
if 'situation' in comp else ''
|
|
except:
|
|
last_play = ''
|
|
if away_score > home_score:
|
|
away_short_str = ircutils.bold('{} {}'.format(away_short, away_score))
|
|
away_long_str = ircutils.bold('{}{} {}'.format(away_long, away_rank, away_score))
|
|
home_short_str = '{} {}'.format(home_short, home_score)
|
|
home_long_str = '{}{} {}'.format(home_long, home_rank, home_score)
|
|
elif home_score > away_score:
|
|
away_short_str = '{} {}'.format(away_short, away_score)
|
|
away_long_str = '{}{} {}'.format(away_long, away_rank, away_score)
|
|
home_short_str = ircutils.bold('{} {}'.format(home_short, home_score))
|
|
home_long_str = ircutils.bold('{}{} {}'.format(home_long, home_rank, home_score))
|
|
else:
|
|
away_short_str = '{} {}'.format(away_short, away_score)
|
|
away_long_str = '{}{} {}'.format(away_long, away_rank, away_score)
|
|
home_short_str = '{} {}'.format(home_short, home_score)
|
|
home_long_str = '{}{} {}'.format(home_long, home_rank, home_score)
|
|
short = '{} {} {}'.format(away_short_str, home_short_str, clock_short)
|
|
long = '{} @ {} - {}{}'.format(away_long_str, home_long_str, clock_long, last_play)
|
|
games[day][key] = {'short': short, 'long': long, 'ended': is_ended, 'top25': top25, 'lookup': lookup}
|
|
|
|
# sort events
|
|
games[day] = collections.OrderedDict(sorted(games[day].items(), key=lambda k: k[1]['ended']))
|
|
|
|
return games
|
|
|
|
|
|
Class = CBB
|
|
|
|
|
|
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|