diff --git a/CBBScores/LICENSE.txt b/CBB/LICENSE.txt similarity index 100% rename from CBBScores/LICENSE.txt rename to CBB/LICENSE.txt diff --git a/CBB/README.md b/CBB/README.md new file mode 100644 index 0000000..a4f4cfb --- /dev/null +++ b/CBB/README.md @@ -0,0 +1 @@ +Fetches NCAA Men's College Basketball scores diff --git a/CFBScores/__init__.py b/CBB/__init__.py similarity index 96% rename from CFBScores/__init__.py rename to CBB/__init__.py index 793d593..f10605f 100644 --- a/CFBScores/__init__.py +++ b/CBB/__init__.py @@ -6,7 +6,7 @@ ### """ -CFBScores: Fetches College Football scores +CBB: Fetches College Basketball scores """ import sys diff --git a/NewOdds/config.py b/CBB/config.py similarity index 81% rename from NewOdds/config.py rename to CBB/config.py index 0748585..9248f19 100644 --- a/NewOdds/config.py +++ b/CBB/config.py @@ -8,7 +8,7 @@ from supybot import conf, registry try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('NewOdds') + _ = PluginInternationalization('CBB') except: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -21,12 +21,12 @@ def configure(advanced): # user or not. You should effect your configuration by manipulating the # registry as appropriate. from supybot.questions import expect, anything, something, yn - conf.registerPlugin('NewOdds', True) + conf.registerPlugin('CBB', True) -NewOdds = conf.registerPlugin('NewOdds') +CBB = conf.registerPlugin('CBB') # This is where your configuration variables (if any) should go. For example: -# conf.registerGlobalValue(NewOdds, 'someConfigVariableName', +# conf.registerGlobalValue(CBB, 'someConfigVariableName', # registry.Boolean(False, _("""Help for someConfigVariableName."""))) diff --git a/CBBScores/plugin.py b/CBB/plugin.py similarity index 82% rename from CBBScores/plugin.py rename to CBB/plugin.py index 4d284c0..e467a9f 100644 --- a/CBBScores/plugin.py +++ b/CBB/plugin.py @@ -14,7 +14,7 @@ from supybot import utils, plugins, ircutils, callbacks, conf, schedule, ircmsgs from supybot.commands import * try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('CBBScores') + _ = PluginInternationalization('CBB') except ImportError: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -24,52 +24,35 @@ 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 CBBScores(callbacks.Plugin): +class CBB(callbacks.Plugin): """Fetches College Basketball scores""" threaded = True def __init__(self, irc): - self.__parent = super(CBBScores, self) + self.__parent = super(CBB, self) self.__parent.__init__(irc) - #self.filename = conf.supybot.directories.data.dirize('CBBScores.db') - def checkcbbscores(): - self.SCORES = self._checkscores() - self.SCORES = self._checkscores() - try: # check scores. - schedule.addPeriodicEvent(checkcbbscores, 20, - now=False, name='checkcbbscores') - except AssertionError: - try: - schedule.removeEvent('checkcbbscores') - except KeyError: - pass - schedule.addPeriodicEvent(checkcbbscores, 20, - now=False, name='checkcbbscores') - - def die(self): - try: - schedule.removeEvent('checkcbbscores') - except KeyError: - pass - self.__parent.die() #################### # PUBLIC FUNCTIONS # #################### - @wrap([getopts({'date': 'somethingWithoutSpaces'}), + @wrap([getopts({'date': 'somethingWithoutSpaces', 'all':''}), optional('text')]) def cbb(self, irc, msg, args, options, team=None): - """(--date YYYYMMDD) (team) - Fetches college basketball scores for given date and/or team. - Defaults to today and all teams if no input given. - Ex: --date 20181117 MICH + """[--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': @@ -84,16 +67,26 @@ class CBBScores(callbacks.Plugin): 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: - date = pendulum.now().format('YYYYMMDD') + 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 date not in self.SCORES: - # fetch another day - print('date not in scores db') - SCORES = self._checkscores(cdate=date) - else: - SCORES = self.SCORES - if team: if len(team) > 2: reply = [] @@ -123,8 +116,16 @@ class CBBScores(callbacks.Plugin): irc.reply('ERROR: search string too short') return else: - # all teams - irc.sendMsg(ircmsgs.privmsg(channel, ' | '.join(value['short'] for item,value in SCORES[date].items() if value['top25']))) + 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 @@ -144,11 +145,11 @@ class CBBScores(callbacks.Plugin): 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'], + tmp_date = pendulum.parse(tmp['eventsDate']['date'], strict=False).in_tz('US/Eastern').format('YYYYMMDD') data[tmp_date] = tmp['events'] @@ -241,7 +242,7 @@ class CBBScores(callbacks.Plugin): return games -Class = CBBScores +Class = CBB # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/CBBScores/requirements.txt b/CBB/requirements.txt similarity index 100% rename from CBBScores/requirements.txt rename to CBB/requirements.txt diff --git a/CBBScores/README.md b/CBBScores/README.md deleted file mode 100644 index 7d8e53b..0000000 --- a/CBBScores/README.md +++ /dev/null @@ -1 +0,0 @@ -Fetches College Basketball scores diff --git a/CBBScores/test.py b/CBBScores/test.py deleted file mode 100644 index fbc6a12..0000000 --- a/CBBScores/test.py +++ /dev/null @@ -1,15 +0,0 @@ -### -# Copyright (c) 2018, cottongin -# All rights reserved. -# -# -### - -from supybot.test import * - - -class CBBScoresTestCase(PluginTestCase): - plugins = ('CBBScores',) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/CFB/README.md b/CFB/README.md new file mode 100644 index 0000000..1f340f2 --- /dev/null +++ b/CFB/README.md @@ -0,0 +1 @@ +Fetches NCAA College Football scores. diff --git a/CBBScores/__init__.py b/CFB/__init__.py similarity index 96% rename from CBBScores/__init__.py rename to CFB/__init__.py index 1b17752..e35e03a 100644 --- a/CBBScores/__init__.py +++ b/CFB/__init__.py @@ -6,7 +6,7 @@ ### """ -CBBScores: Fetches College Basketball scores +CFB: Fetches College Football scores """ import sys diff --git a/CFBScores/abbrv.json b/CFB/abbrv.json similarity index 100% rename from CFBScores/abbrv.json rename to CFB/abbrv.json diff --git a/CBBScores/config.py b/CFB/config.py similarity index 80% rename from CBBScores/config.py rename to CFB/config.py index 38779ce..5f7d8c9 100644 --- a/CBBScores/config.py +++ b/CFB/config.py @@ -8,7 +8,7 @@ from supybot import conf, registry try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('CBBScores') + _ = PluginInternationalization('CFB') except: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -21,12 +21,12 @@ def configure(advanced): # user or not. You should effect your configuration by manipulating the # registry as appropriate. from supybot.questions import expect, anything, something, yn - conf.registerPlugin('CBBScores', True) + conf.registerPlugin('CFB', True) -CBBScores = conf.registerPlugin('CBBScores') +CFB = conf.registerPlugin('CFB') # This is where your configuration variables (if any) should go. For example: -# conf.registerGlobalValue(CBBScores, 'someConfigVariableName', +# conf.registerGlobalValue(CFB, 'someConfigVariableName', # registry.Boolean(False, _("""Help for someConfigVariableName."""))) diff --git a/CFBScores/plugin.py b/CFB/plugin.py similarity index 96% rename from CFBScores/plugin.py rename to CFB/plugin.py index 4c99f74..4291427 100644 --- a/CFBScores/plugin.py +++ b/CFB/plugin.py @@ -1,4 +1,3 @@ -# CFBScores ### # Copyright (c) 2018, cottongin # All rights reserved. @@ -17,19 +16,19 @@ from supybot import utils, plugins, ircutils, callbacks, schedule from supybot.commands import * try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('CFBScores') + _ = PluginInternationalization('CFB') except ImportError: # Placeholder that allows to run the plugin on a bot # without the i18n module _ = lambda x: x -class CFBScores(callbacks.Plugin): +class CFB(callbacks.Plugin): """Fetches CFB scores""" threaded = True def __init__(self, irc): - self.__parent = super(CFBScores, self) + self.__parent = super(CFB, self) self.__parent.__init__(irc) self.SCOREBOARD = ('http://site.api.espn.com/apis/site/v2/sports/' @@ -49,19 +48,6 @@ class CFBScores(callbacks.Plugin): 'https://raw.githubusercontent.com/diagonalfish/FootballBotX2/master/abbrv.json') self.abbrv = self.abbrv.json() - def periodicCheckGames(): - self.CFB_GAMES = self._fetchGames(None, '') - - periodicCheckGames() - - try: # check scores. - schedule.addPeriodicEvent(periodicCheckGames, 20, now=False, name='fetchCFBscores') - except AssertionError: - try: - schedule.removeEvent('fetchCFBscores') - except KeyError: - pass - schedule.addPeriodicEvent(periodicCheckGames, 20, now=False, name='fetchCFBscores') @wrap def cfbbyes(self, irc, msg, args): @@ -500,7 +486,7 @@ class CFBScores(callbacks.Plugin): return ircutils.bold(ircutils.underline(string)) -Class = CFBScores +Class = CFB # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/CFBScores/requirements.txt b/CFB/requirements.txt similarity index 100% rename from CFBScores/requirements.txt rename to CFB/requirements.txt diff --git a/CFBScores/README.md b/CFBScores/README.md deleted file mode 100644 index 971a7bf..0000000 --- a/CFBScores/README.md +++ /dev/null @@ -1 +0,0 @@ -Fetches CFB scores diff --git a/CFBScores/test.py b/CFBScores/test.py deleted file mode 100644 index 17c3915..0000000 --- a/CFBScores/test.py +++ /dev/null @@ -1,15 +0,0 @@ -### -# Copyright (c) 2018, cottongin -# All rights reserved. -# -# -### - -from supybot.test import * - - -class CFBScoresTestCase(PluginTestCase): - plugins = ('CFBScores',) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/GolfScores/README.md b/GolfScores/README.md deleted file mode 100644 index 83784a5..0000000 --- a/GolfScores/README.md +++ /dev/null @@ -1 +0,0 @@ -Fetches golf scores diff --git a/GolfScores/config.py b/GolfScores/config.py deleted file mode 100644 index d3c0ce9..0000000 --- a/GolfScores/config.py +++ /dev/null @@ -1,33 +0,0 @@ -### -# Copyright (c) 2018, cottongin -# All rights reserved. -# -# -### - -from supybot import conf, registry -try: - from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('GolfScores') -except: - # Placeholder that allows to run the plugin on a bot - # without the i18n module - _ = lambda x: x - - -def configure(advanced): - # This will be called by supybot to configure this module. advanced is - # a bool that specifies whether the user identified themself as an advanced - # user or not. You should effect your configuration by manipulating the - # registry as appropriate. - from supybot.questions import expect, anything, something, yn - conf.registerPlugin('GolfScores', True) - - -GolfScores = conf.registerPlugin('GolfScores') -# This is where your configuration variables (if any) should go. For example: -# conf.registerGlobalValue(GolfScores, 'someConfigVariableName', -# registry.Boolean(False, _("""Help for someConfigVariableName."""))) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/GolfScores/test.py b/GolfScores/test.py deleted file mode 100644 index e8a45db..0000000 --- a/GolfScores/test.py +++ /dev/null @@ -1,15 +0,0 @@ -### -# Copyright (c) 2018, cottongin -# All rights reserved. -# -# -### - -from supybot.test import * - - -class GolfScoresTestCase(PluginTestCase): - plugins = ('GolfScores',) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/MLBScores/README.md b/MLBScores/README.md deleted file mode 100644 index 73cca27..0000000 --- a/MLBScores/README.md +++ /dev/null @@ -1 +0,0 @@ -Plugin to fetch MLB scores from the MLB.com API diff --git a/MLBScores/__init__.py b/MLBScores/__init__.py deleted file mode 100644 index 6070166..0000000 --- a/MLBScores/__init__.py +++ /dev/null @@ -1,71 +0,0 @@ -### -# Copyright (c) 2018, cottongin -# 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. - -### - -""" -MLBScores: Plugin to fetch MLB scores from the MLB.com API -""" - -import supybot -import supybot.world as world - -# Use this for the version of this plugin. You may wish to put a CVS keyword -# in here if you're keeping the plugin in CVS or some similar system. -__version__ = "" - -# XXX Replace this with an appropriate author or supybot.Author instance. -__author__ = supybot.Author('cottongin', 'cottongin', - 'cottongin@cottongin.club') -__maintainer__ = getattr(supybot.authors, 'oddluck', - supybot.Author('oddluck', 'oddluck', 'oddluck@riseup.net')) - -# This is a dictionary mapping supybot.Author instances to lists of -# contributions. -__contributors__ = {} - -# This is a url where the most recent plugin package can be downloaded. -__url__ = 'https://github.com/oddluck/limnoria-plugins/' - -from . import config -from . import plugin -from imp import reload -# In case we're being reloaded. -reload(config) -reload(plugin) -# Add more reloads here if you add third-party modules and want them to be -# reloaded when this plugin is reloaded. Don't forget to import them as well! - -if world.testing: - from . import test - -Class = plugin.Class -configure = config.configure - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/MLBScores/config.py b/MLBScores/config.py deleted file mode 100644 index b8dfca3..0000000 --- a/MLBScores/config.py +++ /dev/null @@ -1,58 +0,0 @@ -### -# Copyright (c) 2018, cottongin -# 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 supybot.conf as conf -import supybot.registry as registry -try: - from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('MLBScores') -except: - # Placeholder that allows to run the plugin on a bot - # without the i18n module - _ = lambda x: x - - -def configure(advanced): - # This will be called by supybot to configure this module. advanced is - # a bool that specifies whether the user identified themself as an advanced - # user or not. You should effect your configuration by manipulating the - # registry as appropriate. - from supybot.questions import expect, anything, something, yn - conf.registerPlugin('MLBScores', True) - - -MLBScores = conf.registerPlugin('MLBScores') -# This is where your configuration variables (if any) should go. For example: -# conf.registerGlobalValue(MLBScores, 'someConfigVariableName', -# registry.Boolean(False, _("""Help for someConfigVariableName."""))) -conf.registerGlobalValue(MLBScores, 'bitlyAPIKey', - registry.String('', """Bit.ly API key.""", private=True)) - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/MLBScores/inputParser.py b/MLBScores/inputParser.py deleted file mode 100644 index d4b266b..0000000 --- a/MLBScores/inputParser.py +++ /dev/null @@ -1,109 +0,0 @@ -import pendulum -import re - -_FUZZY_DAYS = ['yesterday', 'tonight', 'today', 'tomorrow', - 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'] - -def _parseDate(string): - """parse date""" - date = string[:3].lower() - if date in _FUZZY_DAYS or string.lower() in _FUZZY_DAYS: - if date == 'yes': - date_string = pendulum.yesterday('US/Pacific').format('YYYY-MM-DD') - #print(date_string) - return date_string - elif date == 'tod' or date == 'ton': - date_string = pendulum.now('US/Pacific').format('YYYY-MM-DD') - return date_string - elif date == 'tom': - date_string = pendulum.tomorrow('US/Pacific').format('YYYY-MM-DD') - return date_string - elif date == 'sun': - date_string = pendulum.now('US/Pacific').next(pendulum.SUNDAY).format('YYYY-MM-DD') - return date_string - elif date == 'mon': - date_string = pendulum.now('US/Pacific').next(pendulum.MONDAY).format('YYYY-MM-DD') - return date_string - elif date == 'tue': - date_string = pendulum.now('US/Pacific').next(pendulum.TUESDAY).format('YYYY-MM-DD') - return date_string - elif date == 'wed': - date_string = pendulum.now('US/Pacific').next(pendulum.WEDNESDAY).format('YYYY-MM-DD') - return date_string - elif date == 'thu': - date_string = pendulum.now('US/Pacific').next(pendulum.THURSDAY).format('YYYY-MM-DD') - return date_string - elif date == 'fri': - date_string = pendulum.now('US/Pacific').next(pendulum.FRIDAY).format('YYYY-MM-DD') - return date_string - elif date == 'sat': - date_string = pendulum.now('US/Pacific').next(pendulum.SATURDAY).format('YYYY-MM-DD') - return date_string - -def parseInput(args=None, _TEAM_BY_TRI=None, _TEAM_BY_NICK=None): - """parse user input from mlb2""" - # return team, date, timezone - - tz = 'US/Eastern' - date = None - team = None - is_date = None - - if not args: - return team, date, tz - - arg_array = [] - for arg in args.split(' '): - arg_array.append(arg) - - print(_TEAM_BY_TRI) - - for idx, arg in enumerate(arg_array): - #print(arg) - if '--tz' in arg: - #print(arg_array[idx+1]) - try: - tz = arg_array[idx+1] - except: - tz = 'US/Eastern' - if arg.lower() in _FUZZY_DAYS or arg[:3].lower() in _FUZZY_DAYS: - date = _parseDate(arg) - #print(date) - #date = pendulum.parse(date).in_tz(tz) - try: - arg = arg.strip('-') - arg = arg.strip('/') - if arg[0].isdigit() and arg[1].isdigit() and arg[2].isalpha(): - if arg[-1].isdigit(): - yr = arg[-2:] - mnth = " ".join(re.findall("[a-zA-Z]+", arg)) - #print(mnth,yr) - rebuild = '{}-{}-{}'.format(mnth, arg[:2], yr) - else: - rebuild = arg[2:] + arg[:2] - #print('both', rebuild) - elif arg[0].isdigit() and arg[1].isalpha(): - rebuild = arg[1:] + arg[0] - #print('one', rebuild) - else: - rebuild = arg - - #print(rebuild) - is_date = pendulum.parse(rebuild, strict=False) - #print(is_date) - except: - is_date = None - if is_date: - date = is_date.format('YYYY-MM-DD') - if _TEAM_BY_TRI and _TEAM_BY_NICK: - if arg.upper() in _TEAM_BY_TRI: - team = str(_TEAM_BY_TRI[arg.upper()]) - elif arg.lower() in _TEAM_BY_NICK: - abbr = str(_TEAM_BY_NICK[arg.lower()]) - team = str(_TEAM_BY_TRI[abbr]) - #else: - # team = arg.upper() - - print(team) - - return team, date, tz \ No newline at end of file diff --git a/MLBScores/plugin.py b/MLBScores/plugin.py deleted file mode 100644 index 8cddfda..0000000 --- a/MLBScores/plugin.py +++ /dev/null @@ -1,4049 +0,0 @@ -# MLBScores -### -# Copyright (c) 2018, cottongin -# 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 supybot.utils as utils -from supybot.commands import * -import supybot.plugins as plugins -import supybot.ircutils as ircutils -import supybot.callbacks as callbacks -import supybot.ircmsgs as ircmsgs -import supybot.schedule as schedule -try: - from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('MLBScores') -except ImportError: - # Placeholder that allows to run the plugin on a bot - # without the i18n module - _ = lambda x: x - -import requests -import httplib2 -import pendulum -import re -import datetime -import pytz -import time -import dateutil.parser -import urllib -import collections -import jellyfish -from operator import itemgetter - -from . import inputParser -# from pprint import pprint -# from pybaseball import playerid_lookup -# from pybaseball import pitching_stats_bref -# from pybaseball import batting_stats_bref - - -class MLBScores(callbacks.Plugin): - """Plugin to fetch MLB scores from the MLB.com API""" - threaded = True - - def dprint(self, thing, override=False): - """debug print""" - if self._DEBUG == True or override: - print(thing) - return - - def __init__(self, irc): - self.__parent = super(MLBScores, self) - self.__parent.__init__(irc) - - self._DEBUG = False - - try: - self.GOOG = irc.getCallback('Google') - except: - self.GOOG = None - - self._HTTP = httplib2.Http('.cache') - - self._SCOREBOARD_ENDPOINT = ('https://statsapi.mlb.com/api/v1/schedule' - '?sportId=1,51&date={}' - '&hydrate=team(leaders(showOnPreview(' - 'leaderCategories=[homeRuns,runsBattedIn,' - 'battingAverage],statGroup=[pitching,' - 'hitting]))),linescore(matchup,runners),' - 'flags,liveLookin,review,broadcasts(all),' - 'decisions,person,probablePitcher,stats,' - 'homeRuns,previousPlay,game(content(' - 'media(featured,epg),summary),tickets),' - 'seriesStatus(useOverride=true)') - - self._FUZZY_DAYS = ['yesterday', 'tonight', 'today', 'tomorrow', - 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'] - - #pendulum.set_formatter('alternative') - - self._TEAM_BY_TRI, self._TEAM_BY_ID = self._getTeams() - self._51_BY_TRI, self._51_BY_ID = self._get51Teams() - - self._STATUSES = self._getStatuses() - #self._ACTIVE_PLAYERS = self._fetchActivePlayers() - - self._TEAM_BY_NICK = {'fish': 'MIA', 'poop': 'NYY', 'goat': 'BOS', - 'best': 'BOS', 'worst': 'NYY', '💩': 'NYY'} - - self._player_aliases = {'buttholz': 'Clay Buchholz', - 'sucker punch': 'Gary Sanchez', - 'sucker puncher': 'Gary Sanchez', - 'big sexy': 'Bartolo Colon', - 'sexx dragon': 'Joe Mauer', - 'big papi': 'David Ortiz', - 'dp': 'dustin pedroia', - 'lil dp': 'dustin pedroia', - 'panda': 'pablo sandoval', - 'gap tooth': 'aaron judge', - 'jv': 'justin verlander', - 'comebacker': 'justin verlander', - 'justdongs': 'jd martinez', - 'justdongers': 'jd martinez', - 'erod': 'eduardo rodriguez', - 'jdmart': 'jd martinez', - 'starlord': 'alex wilson', - 'machado': 'dixon machado', - 'douchebag': 'manny machado', - 'strikeouts mcgee': 'giancarlo stanton', - 'k machine': 'giancarlo stanton', - 'swings and misses': 'giancarlo stanton', - 'calendario': 'candelario', - 'scrabble': 'marc rzepczynski', - 'mr_pink': 'Enyel De Los Santos', - 'jbj': 'jackie bradley jr.', - 'mvp': 'mookie betts', - 'tyler austin\'s daddy': 'joe kelly', - 'tyler austins daddy': 'joe kelly', - 'joe kelly\'s son': 'tyler austin', - 'joe kellys son': 'tyler austin', - 'joe kelly\'s daughter': 'tyler austin', - 'joe kellys daughter': 'tyler austin', - } - - def periodicCheckGames(): - #print('MLBScores: Periodic check') - self.MLB_GAMES = self._fetchGames(None, None) - #print(self.CFB_GAMES) - - def periodicCheckPlayers(): - self._PLAYERS = {} - self._PLAYERS['active'] = self._fetchPlayers() - self._PLAYERS['allTime'] = self._fetchPlayers('allTime') - - periodicCheckGames() - periodicCheckPlayers() - - try: # check scores. - schedule.addPeriodicEvent(periodicCheckGames, 20, now=False, name='fetchMLBscores') - except AssertionError: - try: - schedule.removeEvent('fetchMLBscores') - except KeyError: - pass - schedule.addPeriodicEvent(periodicCheckGames, 20, now=False, name='fetchMLBscores') - - try: # check active rosters. - schedule.addPeriodicEvent(periodicCheckPlayers, 3600, now=False, name='fetchMLBplayers') - except AssertionError: - try: - schedule.removeEvent('fetchMLBplayers') - except KeyError: - pass - schedule.addPeriodicEvent(periodicCheckPlayers, 3600, now=False, name='fetchMLBplayers') - - try: - schedule.removeEvent('fetchALLMLBplayers') - except KeyError: - pass - - def _shortenUrl(self, url): - """Shortens a long URL into a short one.""" - - # Get a API key from bit.ly - api_key = self.registryValue('bitlyAPIKey') - - url_enc = urllib.parse.quote_plus(url) - api_url = 'https://api-ssl.bitly.com/v3/shorten?access_token={}&longUrl={}&format=txt' - - try: - url = requests.get(api_url.format(api_key, url_enc)) - return url.text.strip() - except: - return url - - def _getTeams(self, league=None): - """fetches teams and tricodes""" - - if not league: - url = 'https://statsapi.mlb.com/api/v1/teams?sportId=1' - else: - url = 'https://statsapi.mlb.com/api/v1/teams?sportIds={}&leagueId={}'.format(league[0], league[1]) - - data = requests.get(url).json() - - tmp1 = {} - tmp2 = {} - for team in data['teams']: - tmp1[team['abbreviation']] = team['id'] - tmp2[str(team['id'])] = team['abbreviation'] - - return tmp1, tmp2 - - def _get51Teams(self): - """fetches teams and tricodes""" - - url = 'https://statsapi.mlb.com/api/v1/teams?sportId=51' - - data = requests.get(url).json() - - tmp1 = {} - tmp2 = {} - for team in data['teams']: - tmp1[team['abbreviation']] = team['id'] - tmp2[str(team['id'])] = team['abbreviation'] - - return tmp1, tmp2 - - def _getStatuses(self): - - url = 'http://statsapi.mlb.com/api/v1/gameStatus' - - data = requests.get(url).json() - - tmp = {} - for status in data: - tmp[status['statusCode']] = status['detailedState'] - - return tmp - - @wrap(['text']) - def recap(self, irc, msg, args, irc_args): - """ [] - Returns MLB Recap Videos - """ - - team, date, tz = self._parseInput(irc_args) - date = pendulum.parse(date) - if date is None: - date = datetime.datetime.now().strftime("%y-%m-%d") - hdate = datetime.datetime.now().strftime("%m/%d/%y") - else: -# team, date, tz = self._parseInput(irc_args) -# for form in ["%d%b", "%d %b", "%b%d", "%b %d", "%d%B", "%d %B", "%b%B", "%b %B", "%B %d", "%B%d", "%Y%m%d", "%Y-%m-%d", "%m%d"]: -# result = self.api_get_date(date, form) -# if result is not None: -# break -# if result is None: -# return("Use the following format: Apr10 or 10Apr or YYYYMMDD") - - day = str(date.day) - month = str(date.month) - year = date.year - - if year == 1900: - year = 2019 - - if (year < 2016): - irc.reply("Sorry, the API only back dates until 2016") - return - if len(day) == 1: - day = "0{}".format(day) - if len(month) == 1: - month = "0{}".format(month) - - date = "{}-{}-{}".format(year, month, day) - hdate = "{}/{}/{}".format(month, day, str(year)[2:]) - - #team = self.MLBFindTeam(team.upper(), 0) -# if len(team) > 3: -# irc.reply(team) -# return - #print(team) - url = "https://statsapi.mlb.com/api/v1/schedule?sportId=1&date={}&hydrate=linescore(matchup,runners),game(content(media(featured,epg),summary),tickets)&teamId={}".format(date, team) - content = requests.get(url).json() - recap = False - try: - for each in content['dates'][0]['games']: - home = int(each['teams']['home']['team']['id']) - away = int(each['teams']['away']['team']['id']) - #print(team, home, away) - if int(team) == home or int(team) == away: - newurl = "https://statsapi.mlb.com/api/v1/game/{}/content".format(each['gamePk']) - newcontent = requests.get(newurl).json() - url = newcontent['media']['epgAlternate'][4]['items'][0]['playbacks'][3]['url'] - duration = newcontent['media']['epgAlternate'][4]['items'][0]['duration'] - duration = datetime.datetime.strptime(duration, "%H:%M:%S").strftime("%Mm%Ss").lstrip("0").lstrip("m") - away_s = each['teams']['away']['score'] - home_s = each['teams']['home']['score'] - headline = "{} {} @ {} {}".format(self._TEAM_BY_ID[str(away)], away_s, self._TEAM_BY_ID[str(home)], home_s) - blurb = newcontent['media']['epgAlternate'][4]['items'][0]['blurb'] - date, info = blurb.split(":") - url = self._shortenUrl(url) - irc.reply("\x02Recap: {}\x02 |{}".format(headline, info)) - recap = True - for items in newcontent['media']['epgAlternate'][4]['items'][0]['playbacks']: - if items['name'] == 'FLASH_2500K_1280X720': - mp4 = self._shortenUrl(items['url']) - if items['name'] == 'HTTP_CLOUD_WIRED_WEB': - hls = self._shortenUrl(items['url']) - irc.reply("\x02MP4\x02: {} | \x02HLS\x02: {} | \x02{}\x02".format(mp4, hls, duration)) - except Exception as e: - #print(e) - irc.reply("\x02{}\x02: No recap video available for {}".format(hdate, self._TEAM_BY_ID[team])) - - @wrap - def mlbwildcard(self, irc, msg, args): - """Fetches wildcard standings for MLB""" - - url = 'https://statsapi.mlb.com/api/v1/standings?leagueId=103,104&season={season}&standingsTypes=wildCard&hydrate=division,conference,sport,league,team(nextSchedule(team,gameType=[R,F,D,L,W,C],inclusive=false),previousSchedule(team,gameType=[R,F,D,L,W,C],inclusive=true))' - season = pendulum.now().year - url = url.format(season=season) - - try: - data = requests.get(url) - data = data.json() - except: - irc.reply('Error fetching standings') - return - - al_data = data['records'][0] - nl_data = data['records'][1] - - alwc = [] - nlwc = [] - - al = self._blue(self._bold(al_data['league']['abbreviation'] + 'WC')) - nl = self._red(self._bold(nl_data['league']['abbreviation'] + 'WC')) - - # BOS +2.5 (W-L) W2 | NYY - (W-L) W2 | - - for team in al_data['teamRecords']: - string = '{} {} {} {}{}' - string = string.format( - self._bold('{:3}'.format(team['team']['abbreviation'])), - '-' + team['wildCardGamesBack'] if ('-' not in team['wildCardGamesBack'] and '+' not in team['wildCardGamesBack']) else team['wildCardGamesBack'], - '({}-{})'.format(team['wins'], team['losses']), - self._green(team['streak']['streakCode']) if 'W' in team['streak']['streakCode'] else self._red(team['streak']['streakCode']), - ' E#{}'.format(team['wildCardEliminationNumber']) if '-' not in team['wildCardEliminationNumber'] else '' - ) - if team['wildCardEliminationNumber'] != 'E': - alwc.append(string) - - for team in nl_data['teamRecords']: - string = '{} {} {} {}{}' - string = string.format( - self._bold('{:3}'.format(team['team']['abbreviation'])), - '-' + team['wildCardGamesBack'] if ('-' not in team['wildCardGamesBack'] and '+' not in team['wildCardGamesBack']) else team['wildCardGamesBack'], - '({}-{})'.format(team['wins'], team['losses']), - self._green(team['streak']['streakCode']) if 'W' in team['streak']['streakCode'] else self._red(team['streak']['streakCode']), - ' E#{}'.format(team['wildCardEliminationNumber']) if '-' not in team['wildCardEliminationNumber'] else '' - ) - if team['wildCardEliminationNumber'] != 'E': - nlwc.append(string) - - al_string = '{}: {}'.format(al, ' | '.join(string for string in alwc)) - nl_string = '{}: {}'.format(nl, ' | '.join(string for string in nlwc)) - irc.reply(al_string) - irc.reply(nl_string) - - - @wrap([optional('text')]) - def mlbstandings(self, irc, msg, args, irc_args=None): - """[] - Fetches standings for given division, defaults to all divisions if not provided - """ - - valid_leagues = ['ALE', 'ALW', 'ALC', - 'NLE', 'NLW', 'NLC'] - table = False - if irc_args: - if '--table' in irc_args: - table = True - irc_args = irc_args.replace('--table', '') - irc_args = irc_args.strip() - if irc_args.upper() not in valid_leagues: - irc.reply('Error: invalid league') - return - - now = pendulum.now().year - url = ('https://statsapi.mlb.com/api/v1/standings?leagueId=103,104' - '&season={season}&standingsTypes=regularSeason' - '&hydrate=division,conference,sport,league,team' - '(nextSchedule(team,gameType=[R,F,D,L,W,C],inclusive=false),' - 'previousSchedule(team,gameType=[R,F,D,L,W,C],inclusive=true))') - url = url.format(season=now) - - try: - data = requests.get(url) - data = data.json() - except: - irc.reply('Error fetching standings') - return - - #print(data['records'][0]) - - data = data['records'] - - # ALE: BOS - (103-50) L2 | NYY -10 (94-50) W2 | - - standings = collections.OrderedDict() - divisions = {} - for league in data: - abbrv = league['division']['abbreviation'] - short_name = league['division']['nameShort'] - divisions[abbrv] = short_name - standings[abbrv] = [] - for team in league['teamRecords']: - tmp = collections.OrderedDict() - tmp['team_abbrv'] = team['team']['abbreviation'] - tmp['games_back'] = team['divisionGamesBack'] - tmp['record'] = '({}-{})'.format(team['wins'], team['losses']) - tmp['wins'] = team['wins'] - tmp['losses'] = team['losses'] - tmp['streak'] = team['streak']['streakCode'] - tmp['clinched'] = team['clinchIndicator'] if team['clinched'] else '' - tmp['pct'] = team['leagueRecord']['pct'] - tmp['enum'] = team['eliminationNumber'] - tmp['wcgb'] = team['wildCardGamesBack'] - for split in team['records']['splitRecords']: - if 'lastTen' in split['type']: - tmp['last10'] = '{}-{}'.format(split['wins'], split['losses']) - tmp['rs'] = team['runsScored'] - tmp['ra'] = team['runsAllowed'] - tmp['diff'] = team['runDifferential'] - tmp['xwl'] = '{}-{}'.format(team['records']['expectedRecords'][0]['wins'], team['records']['expectedRecords'][0]['losses']) - tmp['home'] = '{}-{}'.format(team['records']['splitRecords'][0]['wins'], team['records']['splitRecords'][0]['losses']) - tmp['away'] = '{}-{}'.format(team['records']['splitRecords'][1]['wins'], team['records']['splitRecords'][1]['losses']) - tmp['.500'] = '{}-{}'.format(team['records']['splitRecords'][7]['wins'], team['records']['splitRecords'][7]['losses']) - try: - if team['team']['abbreviation'] == team['team']['nextGameSchedule']['dates'][0]['games'][0]['teams']['away']['team']['abbreviation']: - nextStr = 'at {}'.format(team['team']['nextGameSchedule']['dates'][0]['games'][0]['teams']['home']['team']['abbreviation']) - else: - nextStr = 'vs {}'.format(team['team']['nextGameSchedule']['dates'][0]['games'][0]['teams']['away']['team']['abbreviation']) - tmp['next'] = '{} {}'.format( - pendulum.parse(team['team']['nextGameSchedule']['dates'][0]['date']).format('MMM D'), - nextStr - ) - except: - tmp['next'] = '-' - tmp['team'] = team['team']['shortName'] - standings[abbrv].append(tmp) - - #print(standings['ALE'][0]) - #print(divisions) - #irc.reply(standings['ALE'] - for league in standings: - if not irc_args or (irc_args and not table): - reply_string = '{}: '.format(self._bold(self._blue(league)) if 'A' in league else self._bold(self._red(league))) - tmp_strings = [] - for idx, team in enumerate(standings[league]): - tmp_string = '{} {} {} {}'.format( - self._bold('{:3}'.format(team['team_abbrv'])), - '-' + '{:4}'.format(team['games_back']) if '-' not in team['games_back'] else team['games_back'], - team['record'], - self._green(team['streak']) if 'W' in team['streak'] else self._red(team['streak'])) - tmp_strings.append(tmp_string) - - reply_string += ' | '.join(string for string in tmp_strings) - if irc_args: - if irc_args.upper() == league: - irc.reply(reply_string) - return - else: - irc.reply(reply_string) - else: - if irc_args.upper() == league: - max_width = 0 - for team in standings[league]: - if max_width < len(team['clinched'] + team['team']): - max_width = len(team['clinched'] + team['team']) - league_width = max_width - len(divisions[irc_args.upper()]) + 2 - header = '{}{:{width}} W L PCT GB E# WCGB L10 STRK RS RA DIFF X-W/L Home Away >.500 Next Game' - header = header.format(divisions[irc_args.upper()], ' ', width=league_width) - irc.reply(header) - for team in standings[league]: - reply_string = '{:{width}} {:3} {:3} {} {:^4} {} {:^4} {} {} {} {} {:^4} {:7} {} {} {} {}' - reply_string = reply_string.format( - team['clinched'] + team['team'], - team['wins'], team['losses'], - team['pct'], - team['games_back'], - team['enum'], - team['wcgb'], - team['last10'], - team['streak'], - team['rs'], - team['ra'], - team['diff'], - team['xwl'], - team['home'], - team['away'], - team['.500'], - team['next'], - width=max_width - ) - irc.reply(reply_string) - - @wrap([optional('text')]) - def offseason(self, irc, msg, args, irc_args=None): - """[] [] - Fetches scores for given team and/or date. Defaults to today and all - teams if no input provided""" - - tv = False - if irc_args: - if '--tv' in irc_args: - tv = True - irc_args = irc_args.replace('--tv','') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - team_codes, _ = self._getTeams(league=[17, '119,131,132,133,135,162,516,595']) - - try: - team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - - #print('MLBScores: No cached scores, pulling fresh') - GAMES = self._fetchGames(team, date, league=[17, '119,131,132,133,135,162,516,595']) - - if not GAMES: - irc.reply('No games found') - return - - games = self._parseGames(GAMES, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - reply_string = self._replyAsString(team, games, tz, tv) - - # what = type(reply_string) - # print(what) - - # print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - @wrap([optional('text')]) - def cs(self, irc, msg, args, irc_args=None): - """[] [] - Fetches scores for given team and/or date. Defaults to today and all - teams if no input provided""" - - tv = False - if irc_args: - if '--tv' in irc_args: - tv = True - irc_args = irc_args.replace('--tv','') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - team_codes, _ = self._getTeams(league=[17, 162]) - - try: - team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - - #print('MLBScores: No cached scores, pulling fresh') - GAMES = self._fetchGames(team, date, league=[17, 162]) - - if not GAMES: - irc.reply('No games found') - return - - games = self._parseGames(GAMES, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - reply_string = self._replyAsString(team, games, tz, tv) - - # what = type(reply_string) - # print(what) - - # print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - @wrap([optional('text')]) - def abl(self, irc, msg, args, irc_args=None): - """[] [] - Fetches scores for given team and/or date. Defaults to today and all - teams if no input provided""" - - tv = False - if irc_args: - if '--tv' in irc_args: - tv = True - irc_args = irc_args.replace('--tv','') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - team_codes, _ = self._getTeams(league=[17, 595]) - - try: - team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - - #print('MLBScores: No cached scores, pulling fresh') - GAMES = self._fetchGames(team, date, league=[17, 595]) - - if not GAMES: - irc.reply('No games found') - return - - games = self._parseGames(GAMES, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - reply_string = self._replyAsString(team, games, tz, tv) - - # what = type(reply_string) - # print(what) - - # print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - @wrap([optional('text')]) - def winl(self, irc, msg, args, irc_args=None): - """[] [] - Fetches scores for given team and/or date. Defaults to today and all - teams if no input provided""" - - tv = False - if irc_args: - if '--tv' in irc_args: - tv = True - irc_args = irc_args.replace('--tv','') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - team_codes, _ = self._getTeams(league=[17, 516]) - - try: - team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - - #print('MLBScores: No cached scores, pulling fresh') - GAMES = self._fetchGames(team, date, league=[17, 516]) - - if not GAMES: - irc.reply('No games found') - return - - games = self._parseGames(GAMES, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - reply_string = self._replyAsString(team, games, tz, tv) - - # what = type(reply_string) - # print(what) - - # print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - @wrap([optional('text')]) - def vwl(self, irc, msg, args, irc_args=None): - """[] [] - Fetches scores for given team and/or date. Defaults to today and all - teams if no input provided""" - - tv = False - if irc_args: - if '--tv' in irc_args: - tv = True - irc_args = irc_args.replace('--tv','') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - team_codes, _ = self._getTeams(league=[17, 135]) - - try: - team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - - #print('MLBScores: No cached scores, pulling fresh') - GAMES = self._fetchGames(team, date, league=[17, 135]) - - if not GAMES: - irc.reply('No games found') - return - - games = self._parseGames(GAMES, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - reply_string = self._replyAsString(team, games, tz, tv) - - # what = type(reply_string) - # print(what) - - # print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - @wrap([optional('text')]) - def pwl(self, irc, msg, args, irc_args=None): - """[] [] - Fetches scores for given team and/or date. Defaults to today and all - teams if no input provided""" - - tv = False - if irc_args: - if '--tv' in irc_args: - tv = True - irc_args = irc_args.replace('--tv','') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - team_codes, _ = self._getTeams(league=[17, 133]) - - try: - team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - - #print('MLBScores: No cached scores, pulling fresh') - GAMES = self._fetchGames(team, date, league=[17, 133]) - - if not GAMES: - irc.reply('No games found') - return - - games = self._parseGames(GAMES, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - reply_string = self._replyAsString(team, games, tz, tv) - - # what = type(reply_string) - # print(what) - - # print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - @wrap([optional('text')]) - def lmp(self, irc, msg, args, irc_args=None): - """[] [] - Fetches scores for given team and/or date. Defaults to today and all - teams if no input provided""" - - tv = False - if irc_args: - if '--tv' in irc_args: - tv = True - irc_args = irc_args.replace('--tv','') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - team_codes, _ = self._getTeams(league=[17, 132]) - - try: - team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - - #print('MLBScores: No cached scores, pulling fresh') - GAMES = self._fetchGames(team, date, league=[17, 132]) - - if not GAMES: - irc.reply('No games found') - return - - games = self._parseGames(GAMES, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - reply_string = self._replyAsString(team, games, tz, tv) - - # what = type(reply_string) - # print(what) - - # print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - @wrap([optional('text')]) - def dwl(self, irc, msg, args, irc_args=None): - """[] [] - Fetches scores for given team and/or date. Defaults to today and all - teams if no input provided""" - - tv = False - if irc_args: - if '--tv' in irc_args: - tv = True - irc_args = irc_args.replace('--tv','') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - team_codes, _ = self._getTeams(league=[17, 131]) - - try: - team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - - #print('MLBScores: No cached scores, pulling fresh') - GAMES = self._fetchGames(team, date, league=[17, 131]) - - if not GAMES: - irc.reply('No games found') - return - - games = self._parseGames(GAMES, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - reply_string = self._replyAsString(team, games, tz, tv) - - # what = type(reply_string) - # print(what) - - # print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - @wrap([optional('text')]) - def azfl(self, irc, msg, args, irc_args=None): - """[] [] - Fetches scores for given team and/or date. Defaults to today and all - teams if no input provided""" - - tv = False - if irc_args: - if '--tv' in irc_args: - tv = True - irc_args = irc_args.replace('--tv','') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - team_codes, _ = self._getTeams(league=[17, 119]) - - try: - team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - - #print('MLBScores: No cached scores, pulling fresh') - GAMES = self._fetchGames(team, date, league=[17, 119]) - - if not GAMES: - irc.reply('No games found') - return - - games = self._parseGames(GAMES, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - reply_string = self._replyAsString(team, games, tz, tv) - - # what = type(reply_string) - # print(what) - - # print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - - @wrap([optional('text')]) - def mlb(self, irc, msg, args, irc_args=None): - """[] [] - Fetches scores for given team and/or date. Defaults to today and all - teams if no input provided""" - - tv = False - if irc_args: - if '--tv' in irc_args: - tv = True - irc_args = irc_args.replace('--tv','') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - team_codes, _ = self._getTeams() - #print(team_codes) - - try: - team, date, tz = inputParser.parseInput(irc_args, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - if not self.MLB_GAMES or date: - #print('MLBScores: No cached scores, pulling fresh') - self.MLB_GAMES = self._fetchGames(team, date) - - if not self.MLB_GAMES: - irc.reply('No games found') - return - - games = self._parseGames(self.MLB_GAMES, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - reply_string = self._replyAsString(team, games, tz, tv) - - # what = type(reply_string) - # print(what) - - # print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - if date: - self.MLB_GAMES = self._fetchGames(team) - - - @wrap(['text']) - def currentab(self, irc, msg, args, irc_args): - """[] - Fetches details for current at bat for the given team.""" - - if irc_args: - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - try: - team, date, tz = inputParser.parseInput(irc_args, self._TEAM_BY_TRI, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - games = self._fetchGames(team, date) - - if not games: - irc.reply('No games found') - return - - games = self._parseGames(games, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - for game in games: - at_bat = game['atBat'] - - if not at_bat: - irc.reply('ERROR: No current at bat found, game active?') - return - - irc.reply(at_bat) - - @wrap(['positiveInt','text']) - def findab(self, irc, msg, args, ab_index, irc_args): - """ - Fetches details for current at bat for the given team.""" - - if irc_args: - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - try: - team, date, tz = inputParser.parseInput(irc_args, self._TEAM_BY_TRI, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - games = self._fetchGames(team, date) - - if not games: - irc.reply('No games found') - return - - games = self._parseGames(games, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - ab_index = str(ab_index-1) - for game in games: - at_bat = game['atBats'].get(ab_index) - - if not at_bat: - irc.reply('ERROR: No at bat found, game active?') - return - - at_bat = at_bat[0] - - irc.reply(at_bat) - - @wrap(['text']) - def atbats(self, irc, msg, args, irc_args): - """ - Fetches details for current at bat for the given team.""" - - if irc_args: - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - try: - team, date, tz = inputParser.parseInput(irc_args, self._TEAM_BY_TRI, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - games = self._fetchGames(team, date) - - if not games: - irc.reply('No games found') - return - - games = self._parseGames(games, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - #ab_index = str(ab_index-1) - at_bats = [] - for game in games: - for k,v in game['atBats'].items(): - #print(k) - at_bats.append([v[1], v[2]]) - - - if not at_bats: - irc.reply('ERROR: No at bats found, game active?') - return - - at_bats = sorted(at_bats, key=lambda k: k[0], reverse=True) - - irc.reply(', '.join(str(a[0]) + '-' + a[1] for a in at_bats)) - - @wrap(['text']) - def lastatbat(self, irc, msg, args, irc_args): - """ - Fetches details for last at bat for the given team and player.""" - - if irc_args: - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - - player = irc_args.split()[1:] - player = ' '.join(n for n in player).strip() - irc_args = irc_args.split()[0] - - try: - team, date, tz = inputParser.parseInput(irc_args, self._TEAM_BY_TRI, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(irc_args) - print('internal parser worked') - #print(team) - #print(date) - - games = self._fetchGames(team, date) - - if not games: - irc.reply('No games found') - return - - games = self._parseGames(games, date, team) - if not games: - irc.reply('No games found') - return - games = self._sortGames(games) - - #ab_index = str(ab_index-1) - at_bats = [] - for game in games: - for k,v in game['atBats'].items(): - #print(k) - at_bats.append([v[1], v[2]]) - - - if not at_bats: - irc.reply('ERROR: No at bats found, game active?') - return - - at_bats = sorted(at_bats, key=lambda k: k[0], reverse=True) - - for at_bat in at_bats: - #print(player.lower(), at_bat[1].lower()) - if player.lower() == at_bat[1].lower(): - print('hi') - idx = str(at_bat[0]-1) - for game in games: - print(game['atBats'].get(idx), idx) - ab = game['atBats'].get(idx) - if ab: - ab = ab[0] - break - - irc.reply(ab) - - - def _sanitizeName(self, name): - """ Sanitize name. """ - - name = name.lower() # lower. - #name = name.strip('.') # remove periods. - name = name.strip('-') # remove dashes. - name = name.strip("'") # remove apostrophies. - # possibly strip jr/sr/III suffixes in here? - return name - - def _pf(self, db, pname): - """ - - Find a player's page via google ajax. Specify DB based on site. - """ - - # check for aliases first - if pname.lower() in self._player_aliases: - pname = self._player_aliases[pname.lower()] - # sanitize. - pname = self._sanitizeName(pname) - - # db. - if db == "e": # espn. - #splitsfix = '-site:espn.go.com/mlb/player/splits/' - burl = "site:espn.go.com/mlb/player/ {0}".format(pname) - elif db == "r": # rworld. - burl = "site:www.rotoworld.com/player/mlb/ %s" % pname - elif db == "s": # st. - burl = "site:www.spotrac.com/mlb/ %s" % pname - elif db == "br": # br. - burl = "site:www.baseball-reference.com/ %s" % pname - - # now actually search - try: - #goog = self.GOOG - if self.GOOG: - try: - search = self.GOOG.search('{0}'.format(burl),'#reddit-baseball',{'smallsearch': True}) - search = self.GOOG.decode(search) - if search: - url = search[0]['url'] -# title = search[0]['title'] -# title = title.replace('', '') -# title = title.replace('', '') -# title = title.strip() -# if pname.title() in title: -# title = title.split(pname.title())[0] -# title += pname.title() -# else: -# title = title.split('-')[0] -# title = title.strip() - title = url.split('/')[-1] - title = title.replace('-', ' ') - print(title) - return title - except: - self.log.exception("ERROR :: _pf :: failed to get link for {0}".format(burl)) - return None - except Exception as e: - self.log.info("ERROR :: _pf :: {0}".format(e)) - return None - - def _similarPlayers(self, optname): - """Return a dict containing the five most similar players based on optname.""" - - activeplayers = self._PLAYERS['active'] - # test length as sanity check. - if len(activeplayers) == 0: - self.log.info("ERROR: _similarPlayers :: length 0. Could not find any players in players source") - return None - # ok, finally, lets go. - optname = str(self._sanitizeName(optname)) # sanitizename. - - jaro, damerau = [], [] # empty lists to put our results in. - # now we create the container to iterate over. - names = [{'fullname': str(self._sanitizeName(k)), 'id':v['id']} for k,v in activeplayers.items()] # full_name # last_name # first_name - #print(type(optname)) - # iterate over the entries. - for row in names: # list of dicts. - jaroscore = jellyfish.jaro_distance(optname, row['fullname']) # jaro. - damerauscore = jellyfish.damerau_levenshtein_distance(optname, row['fullname']) # dld - jaro.append({'jaro': jaroscore, 'fullname': row['fullname'], 'id': row['id']}) # add dict to list. - damerau.append({'damerau': damerauscore, 'fullname': row['fullname'], 'id': row['id']}) # ibid. - # now, we do two "sorts" to find the "top5" matches. reverse is opposite on each. - jarolist = sorted(jaro, key=itemgetter('jaro'), reverse=True)[0:5] # bot five. - dameraulist = sorted(damerau, key=itemgetter('damerau'), reverse=False)[0:5] # top five. - # we now have two lists, top5 sorted, and need to do some further things. - # now, lets iterate through both lists. match if both are in it. (better matches) - matching = [k for k in jarolist if k['id'] in [f['id'] for f in dameraulist]] - # now, test if we have anything. better matches will have more. - if len(matching) == 0: # we have NO matches. grab the top two from jaro/damerau (for error str) - matching = [jarolist[0], dameraulist[0], jarolist[1], dameraulist[1]] - self.log.info("_similarPlayers :: NO MATCHES for {0} :: {1}".format(optname, matching)) - match = False - else: - match = True - # return matching now. - return matching, match - -# def _fetchActivePlayers(self): - -# api_base = 'http://statsapi.mlb.com' -# roster_url = '/api/v1/teams/{team}/roster/active' - -# players = {} -# for team in self._TEAM_BY_ID: -# url = api_base + roster_url.format(team=team) -# #print(url) -# tmp = requests.get(url).json() -# for player in tmp['roster']: -# if 'Pitcher' in player['position']['type']: -# stat_type = 'pitching' -# else: -# stat_type = 'hitting' -# players[player['person']['fullName']] = {'id': player['person']['id'], -# 'url': player['person']['link'], -# 'team': player['parentTeamId'], -# 'stat': stat_type} -# self._ACTIVE_PLAYERS = players -# return players - - def _fetchPlayers(self, search_type=None): - - # default to active rosters only - if not search_type: - search_type = 'active' - - api_base = 'http://statsapi.mlb.com' - roster_url = '/api/v1/teams/{team}/roster/{search_type}' - - # build db - players = {} - for team in self._TEAM_BY_ID: - url = api_base + roster_url.format(team=team, search_type=search_type) - tmp = requests.get(url).json() - for player in tmp['roster']: - # assign stat category to fetch - if 'Pitcher' in player['position']['type']: - stat_type = 'pitching' - else: - stat_type = 'hitting' - # active players will have a team, inactive will not - try: - team = player['parentTeamId'] - except: - team = None - # finally assign the player and info - players[player['person']['fullName'].lower()] = {'id': player['person']['id'], - 'url': player['person']['link'], - 'team': team, - 'stat': stat_type, - 'disp_name': player['person']['fullName'], - } - return players - - def _playerSearch(self, optplayer, search_type): - - similar_players = None - match = False - - if not self._PLAYERS[search_type]: - players = self._fetchPlayers(search_type) - else: - players = self._PLAYERS[search_type] - - if optplayer.lower() not in players: - test = self._pf('e', optplayer) - if test: - optplayer = test - if optplayer.lower() not in players: - similar_players, match = self._similarPlayers(optplayer.lower()) - #print(similar_players) - if match: - for item in similar_players: - if item['fullname'].title() in players: - optplayer = item['fullname'] - break - if optplayer.lower() not in players: - #irc.reply('ERROR: {} not found on any active roster, check spelling/input'.format(optplayer.title())) - return None, similar_players - #print(optplayer) - if optplayer.lower() not in players: - #irc.reply('ERROR: {} not found on any active roster, check spelling/input'.format(optplayer.title())) - return None, similar_players - - player = players[optplayer.lower()] - player['name'] = player['disp_name'] - - return player, similar_players - - @wrap([getopts({'career': '', 'season': 'somethingWithoutSpaces', - 'postseason': '', 'stattype': 'somethingWithoutSpaces'}), 'text']) - def mlbstats(self, irc, msg, args, options, optplayer): - """ - Fetches stats for given player. Options: --season , --career, --postseason""" - - api_base = 'http://statsapi.mlb.com' - roster_url = '/api/v1/teams/{team}/roster/allTime' - stats_url = ('/api/v1/people?' - 'personIds={personId}' - '&season={year}' - '&hydrate=stats(group={group},season={year},type={statType},gameType={reg_or_post})') - - options = dict(options) - # defaults - statType = 'season' - year = pendulum.now().year - reg_or_post = 'R' - blurb = '{} Season Stats'.format(year) - if not options: - statType = 'season' - year = pendulum.now().year - reg_or_post = 'R' - blurb = '{} Season Stats'.format(year) - # parse our options - else: - if 'career' in options and 'postseason' in options: - # we want career postseason stats - reg_or_post = 'P' - statType = 'career' - year = pendulum.now().year - blurb = '{} Postseason Stats'.format(statType.title()) - elif 'career' in options and 'postseason' not in options: - # we want career regular season stats - reg_or_post = 'R' - statType = 'career' - year = pendulum.now().year - blurb = '{} Stats'.format(statType.title()) - elif 'postseason' in options and 'career' not in options and 'season' not in options: - # we want current season postseason stats - statType = 'season' - year = pendulum.now().year - reg_or_post = 'P' - blurb = '{} Postseason Stats'.format(year, statType.title()) - elif 'season' in options and 'postseason' in options: - # we want custom season postseason stats - if not options['season'].isdigit(): - year = pendulum.now().year - optplayer = '{} {}'.format(options['season'], optplayer) - else: - year = options['season'] - statType = 'season' - reg_or_post = 'P' - blurb = '{} Postseason Stats'.format(year, statType.title()) - elif 'season' in options and 'postseason' not in options: - # we want custom season regular season stats - if not options['season'].isdigit(): - # this is a workaround for the @aka/alias functionality - year = pendulum.now().year - optplayer = '{} {}'.format(options['season'], optplayer) - else: - year = options['season'] - statType = 'season' - reg_or_post = 'R' - blurb = '{} {} Stats'.format(year, statType.title()) - - print(options) - # now let's try to find our player - player, possibles = self._playerSearch(optplayer, 'allTime') - if not player and possibles: - irc.reply("I couldn't find stats for {}".format(optplayer)) - irc.reply("Possible suggestions: {0}".format(" | ".join([i['fullname'].title() for i in possibles]))) - return - - optplayer = player['name'] - group = options.get('stattype') or player['stat'] - print(group) - tmp = requests.get('{}{}'.format(api_base, stats_url.format(personId=player['id'], - year=year, - statType=statType, - group=group, - reg_or_post=reg_or_post))) - print(tmp.url) - tmp = tmp.json() - - if 'stats' not in tmp['people'][0]: - irc.reply('ERROR: No stats found for {}'.format(optplayer.title())) - return - - stats = tmp['people'][0]['stats'] - try: - plyr_info = ' (#{} {})'.format(tmp['people'][0]['primaryNumber'], - tmp['people'][0]['primaryPosition']['abbreviation']) - except: - plyr_info = '' - - try: - if not tmp['people'][0].get('active'): - years = ' ({}-{})'.format(tmp['people'][0]['mlbDebutDate'].split('-')[0], - tmp['people'][0]['lastPlayedDate'].split('-')[0]) - else: - years = ' ({}-)'.format(tmp['people'][0]['mlbDebutDate'].split('-')[0]) #, - #tmp['people'][0]['lastPlayedDate'].split('-')[0]) - except: - years = '' - - blurb += years - - hitting_stat_headers, pitching_stat_headers, _ = self._generateStatHeaders('mlbstats') - - out_stats = [] - stats = stats[0]['splits'] - for thing in stats: - #print(thing) - stat_line = collections.OrderedDict({}) - if 'numTeams' not in thing: - try: - team = '{}'.format(self._TEAM_BY_ID[str(thing['team']['id'])]) - except: - team = '' - else: - team = 'Total' - if team: - team = '{} :: '.format(self._bu(team)) - if not thing['stat']: - stat_line['ERROR'] = 'No stats available for {}'.format(optplayer.title()) - break - if group == 'hitting': - for s in hitting_stat_headers: - #print(s) - if s in thing['stat']: - try: - stat_line[hitting_stat_headers[s]] = thing['stat'][s] - except: - stat_line[hitting_stat_headers[s]] = None - elif group == 'pitching': - for s in pitching_stat_headers: - #print(s) - if s in thing['stat']: - try: - stat_line[pitching_stat_headers[s]] = thing['stat'][s] - except: - stat_line[pitching_stat_headers[s]] = None - - stat_string = ' '.join('{}: {}'.format(self._bold(k),v) for k,v in stat_line.items()) - out_stats.append('{}{}'.format(team, stat_string)) - - irc.reply('{}{} :: {}'.format(self._bold(self._blue(optplayer)), plyr_info, blurb)) - for line in out_stats: - irc.reply('{}'.format(line)) - - return - - - @wrap(['text']) - def fstats(self, irc, msg, args, optplayer): - """ - Fetches current/previous game fielding stats for given player""" - - api_base = 'http://statsapi.mlb.com' - roster_url = '/api/v1/teams/{team}/roster/active' - stats_url_current = '/api/v1/people/{personId}/stats/game/current' - stats_url_game = '/api/v1/people/{personId}/stats/game/{gamePk}' - sched_url = ('/api/v1/teams/{teamId}?hydrate=previousSchedule(' - 'gameType=[E,S,R,A,F,D,L,W]),nextSchedule(gameType=[E,S,R,A,F,D,L,W])') - - player, possibles = self._playerSearch(optplayer, 'active') - if not player and possibles: - irc.reply("I couldn't find stats for {}".format(optplayer)) - irc.reply("Possible suggestions: {0}".format(" | ".join([i['fullname'].title() for i in possibles]))) - return - - optplayer = player['name'] - - current = False - tmp = requests.get('{}{}'.format(api_base, stats_url_current.format(personId=player['id']))) - tmp = tmp.json() - if not tmp['stats']: - # no current game - tmp = requests.get('{}{}'.format(api_base, sched_url.format(teamId=player['team']))).json() - try: - if tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['status']['abstractGameState'] == 'Final': - gamePk = tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['gamePk'] - gameDate = pendulum.parse(tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['gameDate'], - strict=False).in_tz('US/Eastern').format('MMM Do') - else: - gamePk = tmp['teams'][0]['previousGameSchedule']['dates'][0]['games'][0]['gamePk'] - gameDate = pendulum.parse(tmp['teams'][0]['previousGameSchedule']['dates'][0]['games'][0]['gameDate'], - strict=False).in_tz('US/Eastern').format('MMM Do') - url = api_base + stats_url_game.format(personId=player['id'], gamePk=gamePk) - tmp = requests.get(url).json() - except: - irc.reply('ERROR: No current/previous game fielding stats found for {}'.format(optplayer.title())) - return - else: - current = True - #TBD - - - - - if not tmp['stats']: - irc.reply('ERROR: No current/previous game fielding stats found for {}'.format(optplayer.title())) - return - - stats = [] - for thing in tmp['stats']: - if 'type' not in thing: - stats = thing - break - - if not stats: - irc.reply('ERROR: No current/previous game fielding stats found for {}'.format(optplayer.title())) - return - - _, _, fielding_stat_headers = self._generateStatHeaders('fstats') - - stat_line = collections.OrderedDict({}) - for thing in stats['splits']: - if thing['group'] == 'fielding': - if not thing['stat']: - stat_line['ERROR'] = 'No fielding stats available for {} in current or previous game'.format(optplayer.title()) - break - for s in fielding_stat_headers: - if s in thing['stat']: - try: - stat_line[fielding_stat_headers[s]] = thing['stat'][s] - except: - stat_line[fielding_stat_headers[s]] = None - try: - pct = (stat_line['Put Outs'] + stat_line['Assists']) / stat_line['Chances'] - stat_line['Fielding'] = '{:.3f}'.format(pct) - except ZeroDivisionError: - pass - - stat_string = ' '.join('{}: {}'.format(self._bold(k),v) for k,v in stat_line.items()) - - irc.reply('{} ({}) {}'.format(self._bold(self._blue(optplayer.title())), gameDate, stat_string)) - - return - - @wrap(['text']) - def mlbgamestats(self, irc, msg, args, optplayer): - """ - Fetches current/previous game stats for given player""" - - api_base = 'http://statsapi.mlb.com' - roster_url = '/api/v1/teams/{team}/roster/active' - stats_url_current = '/api/v1/people/{personId}/stats/game/current' - stats_url_game = '/api/v1/people/{personId}/stats/game/{gamePk}' - sched_url = ('/api/v1/teams/{teamId}?hydrate=previousSchedule(' - 'gameType=[E,S,R,A,F,D,L,W]),nextSchedule(gameType=[E,S,R,A,F,D,L,W])') - - player, possibles = self._playerSearch(optplayer, 'active') - if not player and possibles: - irc.reply("I couldn't find stats for {}".format(optplayer)) - irc.reply("Possible suggestions: {0}".format(" | ".join([i['fullname'].title() for i in possibles]))) - return - - optplayer = player['name'] - - current = False - tmp = requests.get('{}{}'.format(api_base, stats_url_current.format(personId=player['id']))) - print(tmp.url) - tmp = tmp.json() - if not tmp['stats']: - # no current game - tmp = requests.get('{}{}'.format(api_base, sched_url.format(teamId=player['team']))) - print(tmp.url) - tmp = tmp.json() - statuses = ['Final', 'Live'] - if tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['status']['abstractGameState'] in statuses: - gamePk = tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['gamePk'] - gameDate = pendulum.parse(tmp['teams'][0]['nextGameSchedule']['dates'][0]['games'][0]['gameDate'], - strict=False).in_tz('US/Eastern').format('MMM Do') - else: - gamePk = tmp['teams'][0]['previousGameSchedule']['dates'][0]['games'][0]['gamePk'] - gameDate = pendulum.parse(tmp['teams'][0]['previousGameSchedule']['dates'][0]['games'][0]['gameDate'], - strict=False).in_tz('US/Eastern').format('MMM Do') - url = api_base + stats_url_game.format(personId=player['id'], gamePk=gamePk) - #irc.reply(url) - print(url) - tmp = requests.get(url).json() - else: - current = True - #TBD - gameDate = pendulum.now().in_tz('US/Eastern').format('MMM Do') - #print(gamePk) - - - - if not tmp['stats']: - irc.reply('ERROR: No current/previous game stats found for {}'.format(optplayer.title())) - return - - stats = [] - for thing in tmp['stats']: - if 'type' not in thing: - stats = thing - break - - #print(stats) - if not stats: - irc.reply('ERROR: No current/previous game stats found for {}'.format(optplayer.title())) - return - - hitting_stat_headers, pitching_stat_headers, _ = self._generateStatHeaders('mlbgamestats') - - stat_line = collections.OrderedDict({}) - for thing in stats['splits']: - #print(thing) - if player['stat'] == thing['group']: - if not thing['stat']: - stat_line['ERROR'] = 'No stats available for {} on {}'.format(optplayer.title(), gameDate) - break - if player['stat'] == 'hitting': - for s in hitting_stat_headers: - #print(s) - if s in thing['stat']: - try: - stat_line[hitting_stat_headers[s]] = thing['stat'][s] - except: - stat_line[hitting_stat_headers[s]] = None - try: - avg = stat_line['H'] / stat_line['AB'] - avg = '{:.3f}'.format(avg) - except ZeroDivisionError: - avg = '' - - stat_line['AVG'] = avg - elif player['stat'] == 'pitching': - for s in pitching_stat_headers: - #print(s) - if s in thing['stat']: - try: - if s == 'balls' or s == 'strikes': - stat_line['B-S'] = '{}-{}'.format(thing['stat']['balls'], thing['stat']['strikes']) - else: - stat_line[pitching_stat_headers[s]] = thing['stat'][s] - except: - stat_line[pitching_stat_headers[s]] = None - try: - era = '{:.2f}'.format((stat_line['ER']/float(stat_line['IP']))*9) - except: - if float(stat_line['IP']) == 0.0 and stat_line['ER'] > 0: - era = '∞' - else: - era = '0.00' - stat_line['gERA'] = era - - stat_string = ' '.join('{}: {}'.format(self._bold(k),v) for k,v in stat_line.items()) - - irc.reply('{} ({}) {}'.format(self._bold(self._blue(optplayer.title())), gameDate, stat_string)) - - return - - def _generateStatHeaders(self, called_by): - - if called_by == 'mlbstats': - hitting_stat_headers = collections.OrderedDict() - hitting_stat_headers['gamesPlayed'] = 'GP' - hitting_stat_headers['atBats'] = 'AB' - hitting_stat_headers['plateAppearances'] = 'PA' - hitting_stat_headers['hits'] = 'H' - hitting_stat_headers['runs'] = 'R' - hitting_stat_headers['doubles'] = '2B' - hitting_stat_headers['triples'] = '3B' - hitting_stat_headers['homeRuns'] = 'HR' - hitting_stat_headers['baseOnBalls'] = 'BB' - hitting_stat_headers['intentionalWalks'] = 'IBB' - hitting_stat_headers['hitByPitch'] = 'HBP' - hitting_stat_headers['strikeOuts'] = 'SO' - hitting_stat_headers['groundOuts'] = 'GO' - hitting_stat_headers['groundIntoDoublePlay'] = 'GIDP' - hitting_stat_headers['stolenBases'] = 'SB' - hitting_stat_headers['caughtStealing'] = 'CS' - hitting_stat_headers['stolenBasePercentage'] = 'SB%' - hitting_stat_headers['totalBases'] = 'TB' - hitting_stat_headers['leftOnBase'] = 'LOB' - hitting_stat_headers['sacBunts'] = 'sacB' - hitting_stat_headers['sacFlies'] = 'sacF' - hitting_stat_headers['babip'] = 'BABIP' - hitting_stat_headers['rbi'] = 'RBI' - hitting_stat_headers['avg'] = 'AVG' - hitting_stat_headers['obp'] = 'OBP' - hitting_stat_headers['slg'] = 'SLG' - hitting_stat_headers['ops'] = 'OPS' - - pitching_stat_headers = collections.OrderedDict() - pitching_stat_headers['gamesPlayed'] = 'GP' - pitching_stat_headers['gamesStarted'] = 'GS' - pitching_stat_headers['completeGames'] = 'CG' - pitching_stat_headers['shutouts'] = 'SHO' - pitching_stat_headers['inningsPitched'] = 'IP' - pitching_stat_headers['pitchesPerInning'] = 'PitPI' - pitching_stat_headers['battersFaced'] = 'BF' - pitching_stat_headers['hits'] = 'H' - pitching_stat_headers['baseOnBalls'] = 'BB' - pitching_stat_headers['intentionalWalks'] = 'IBB' - pitching_stat_headers['hitBatsmen'] = 'HBP' - pitching_stat_headers['balks'] = 'BLK' - pitching_stat_headers['wildPitches'] = 'WP' - pitching_stat_headers['caughtStealing'] = 'CS' - pitching_stat_headers['strikeOuts'] = 'K' - pitching_stat_headers['groundOuts'] = 'GO' - pitching_stat_headers['earnedRuns'] = 'ER' - pitching_stat_headers['runs'] = 'R' - pitching_stat_headers['homeRuns'] = 'HR' - pitching_stat_headers['flyOuts'] = 'FO' - pitching_stat_headers['groundOuts'] = 'GO' - pitching_stat_headers['era'] = 'ERA' - pitching_stat_headers['whip'] = 'WHIP' - pitching_stat_headers['avg'] = 'AVG' - pitching_stat_headers['obp'] = 'OBP' - pitching_stat_headers['slg'] = 'SLG' - pitching_stat_headers['ops'] = 'OPS' - pitching_stat_headers['strikeoutWalkRatio'] = 'K/W' - pitching_stat_headers['strikeoutsPer9Inn'] = 'K/9' - pitching_stat_headers['walksPer9Inn'] = 'W/9' - pitching_stat_headers['hitsPer9Inn'] = 'H/9' - pitching_stat_headers['wins'] = 'W' - pitching_stat_headers['losses'] = 'L' - pitching_stat_headers['winPercentage'] = 'W%' - pitching_stat_headers['saves'] = 'SV' - pitching_stat_headers['saveOpportunities'] = 'SVO' - pitching_stat_headers['holds'] = 'HLD' - - fielding_stat_headers = None - - return hitting_stat_headers, pitching_stat_headers, fielding_stat_headers - elif called_by == 'fstats': - fielding_stat_headers = collections.OrderedDict() - fielding_stat_headers['chances'] = 'Chances' - fielding_stat_headers['errors'] = 'Errors' - fielding_stat_headers['putOuts'] = 'Put Outs' - fielding_stat_headers['assists'] = 'Assists' - fielding_stat_headers['passedBall'] = 'Passed Balls' - fielding_stat_headers['fielding'] = 'Fielding' - - hitting_stat_headers = None - pitching_stat_headers = None - - return hitting_stat_headers, pitching_stat_headers, fielding_stat_headers - elif called_by == 'mlbgamestats': - hitting_stat_headers = collections.OrderedDict() - hitting_stat_headers['atBats'] = 'AB' - hitting_stat_headers['hits'] = 'H' - hitting_stat_headers['runs'] = 'R' - hitting_stat_headers['baseOnBalls'] = 'BB' - hitting_stat_headers['strikeOuts'] = 'SO' - hitting_stat_headers['doubles'] = '2B' - hitting_stat_headers['triples'] = '3B' - hitting_stat_headers['homeRuns'] = 'HR' - hitting_stat_headers['stolenBases'] = 'SB' - hitting_stat_headers['caughtStealing'] = 'CS' - hitting_stat_headers['totalBases'] = 'TB' - hitting_stat_headers['rbi'] = 'RBI' - hitting_stat_headers['avg'] = 'AVG' - - pitching_stat_headers = collections.OrderedDict() - pitching_stat_headers['inningsPitched'] = 'IP' - pitching_stat_headers['battersFaced'] = 'BF' - pitching_stat_headers['hits'] = 'H' - pitching_stat_headers['baseOnBalls'] = 'BB' - pitching_stat_headers['strikeOuts'] = 'K' - pitching_stat_headers['pitchesThrown'] = '#P' - pitching_stat_headers['balls'] = 'B-S' - pitching_stat_headers['strikes'] = 'B-S' - pitching_stat_headers['hitBatsmen'] = 'HBP' - pitching_stat_headers['earnedRuns'] = 'ER' - pitching_stat_headers['runs'] = 'R' - pitching_stat_headers['homeRuns'] = 'HR' - pitching_stat_headers['flyOuts'] = 'FO' - pitching_stat_headers['groundOuts'] = 'GO' - pitching_stat_headers['era'] = 'gERA' - - fielding_stat_headers = None - - return hitting_stat_headers, pitching_stat_headers, fielding_stat_headers - else: - return None, None, None - - @wrap([getopts({'active': '',}), 'text']) - def mlbroster(self, irc, msg, args, optlist, opttype): - """<--active> - Fetches roster for given filtered by """ - - optlist = dict(optlist) - positions = {'pitchers': 'Pitcher', 'infielders': 'Infielder', - 'catchers': 'Catcher', 'outfielders': 'Outfielder'} - - base_url = 'http://statsapi.mlb.com/api/v1/teams/{team}/roster/{roster}' - api_base = 'http://statsapi.mlb.com' - - try: - team = opttype.split()[0].upper() - except: - irc.reply('Invalid input') - return - try: - filter_ = opttype.split()[1] - except: - filter_ = None - #print(filter_) - try: - filter_ = filter_.lower() - filter_ = positions[filter_] - except: - if filter_: - filter_ = filter_.title() - - if team not in self._TEAM_BY_TRI: - irc.reply('ERROR: Invalid team. Valid teams: {}'.format(', '.join(i for i in self._TEAM_BY_TRI))) - return - team_id = self._TEAM_BY_TRI[team] - - url = base_url.format(team=team_id, roster='active') - - data = requests.get(url).json() - - #print(data.json()) - roster = [] - tmp = data['roster'] - tmp = sorted(tmp, key=lambda k: k['person']['fullName'].split()[-1]) - #print(tmp) - for player in tmp: - num = self._red('#{}'.format(player['jerseyNumber'])) - name = player['person']['fullName'] - info_url = player['person']['link'] - #print(api_base + info_url) - info = requests.get(api_base + info_url).json() - bats = info['people'][0]['batSide']['code'] - pits = info['people'][0]['pitchHand']['code'] - string = '{} {} (B:{} T:{})'.format(num, name, bats, pits) - if filter_: - if player['position']['type'] == filter_: - roster.append(string) - else: - roster.append(string) - - if not roster: - irc.reply('Nothing found for that query') - return - else: - irc.reply(', '.join(i for i in roster)) - return - - @wrap - def mlbdaysleft(self, irc, msg, args): - """How many days are left in the current MLB season""" - - now = pendulum.now() - end = pendulum.parse('201920-09-30') - left = end-now - - irc.reply("There are {} days left in the {} MLB season.".format(left.days, end.year)) - -# @wrap(['text']) -# def mlbstats(self, irc, msg, args, player): -# """ -# Fetches current season stats for the provided. -# """ - -# data = batting_stats_bref() - -# #print(data.head()) - - - @wrap(['text']) - def lineup2(self, irc, msg, args, team): - """ - Fetches lineup for the game is playing - """ - abbv = team.upper() - #team, date, tz = self._parseInput(team) - - team_codes, _ = self._getTeams(league=['1,17', '103,104,119,131,132,133,135,162,516,595']) - - try: - team, date, tz = inputParser.parseInput(team, team_codes, self._TEAM_BY_NICK) - print('external parser worked') - except: - team, date, tz = self._parseInput(team) - print('internal parser worked') - #print(team) - #print(date) - - - #print('MLBScores: No cached scores, pulling fresh') - - - - if date: - test = pendulum.parse(date) - now = pendulum.now().format('YYYY-MM-DD') - now = pendulum.parse(now) - k = (test > now) - #print(date, ' | ', k, ' | ', pendulum.now()) - if k: - #irc_args = '{} {}'.format(team, date) - #self.mlb(msg, args, irc_args) - irc.reply("Sorry I can't predict the future.") - return - - if not team: - irc.reply('No team provided.') - return - - games = self._fetchGames(team, date, league=['1,17', '103,104,119,131,132,133,135,162,516,595']) - - #games = self._fetchGames(team, date) - - if not games: - irc.reply('No games found') - return - - games = self._parseGames(games, date) - games = self._sortGames(games) - - lineup_url = 'http://statsapi.mlb.com/api/v1/game/{}/boxscore'.format(games[0]['id']) - lineup_url_2 = 'https://statsapi.mlb.com/api/v1/schedule?gamePk={}&language=en&hydrate=lineups,person,probablePitcher,team(leaders(showOnPreview(leaderCategories=[homeRuns,runsBattedIn,battingAverage],statGroup=[pitching,hitting])))'.format(games[0]['id']) - print(lineup_url, lineup_url_2) - - try: - data = requests.get(lineup_url).json() - data2 = requests.get(lineup_url_2).json() - except: - irc.reply('Something went wrong fetching game data.') - return - #print(team) - lineup = [] - tmp_plyr_data = [] - opp_id = None - #try: - teams = data['teams'] - lineups = data2['dates'][0]['games'][0]['lineups'] - #print(lineups) - ppitchers = data2['dates'][0]['games'][0]['teams'] - for item in teams: - if int(team) == teams[item]['team']['id']: - #print('h/a: ', item) - if item == 'home': - opp_t = 'away' - hora = item - elif item == 'away': - opp_t = 'home' - hora = item - #print('pitcher: ', opp_t) - battingOrder = teams[item]['battingOrder'] - tmp_plyr_data = teams[item]['players'] - vs_name = teams[opp_t]['team']['abbreviation'] - - #pprint(teams[opp_t]) - if teams[opp_t]['pitchers']: - opp_id = teams[opp_t]['pitchers'][-1] - hm_id = teams[item]['pitchers'][-1] - #print('teams') - else: - opp_id = ppitchers[opp_t]['probablePitcher']['id'] - hm_id = ppitchers[item]['probablePitcher']['id'] - #print('ppitchers') - break - #print(tmp_plyr_data) - if lineups: - #print('Got a lineup') - tstr = '{}Players'.format(hora) - #print(lineups) - try: - lineups = lineups[tstr] - except: - irc.reply('No lineup found') - return - for idx, player in enumerate(lineups): - if battingOrder: - if int(player['id']) != int(battingOrder[idx]): - player['id'] = int(battingOrder[idx]) - #print(idx, player) - plyr_url = 'http://statsapi.mlb.com/api/v1/people/{}'.format(player['id']) - #print(plyr_url) - n_player_data = requests.get(plyr_url).json() - for pid in tmp_plyr_data: - if str(player['id']) in str(pid): - player_data = tmp_plyr_data[pid] - bats = n_player_data['people'][0]['batSide']['code'] - name = player_data['person']['fullName'] - try: - post = lineups[idx]['primaryPosition']['abbreviation'] - except: - post = player_data['position']['abbreviation'] - if idx == 9: - bats = n_player_data['people'][0]['pitchHand']['code'] - tmp = '\x02\x0312{}\x03\x02 {} ({})'.format('P', name, bats) - else: - tmp = '\x02\x0312{}\x03\x02 {} ({}) {}'.format(idx+1, name, bats, post) - lineup.append(tmp) - - #umps = item['value'] - if opp_id: - pitcher_url = 'http://statsapi.mlb.com/api/v1/people/{}'.format(opp_id) - #print(pitcher_url) - pitcher_data = requests.get(pitcher_url).json() - pitch_name = pitcher_data['people'][0]['fullName'] - pitches = pitcher_data['people'][0]['pitchHand']['code'] - for pplayer in data['teams'][opp_t]['players']: - if str(opp_id) in pplayer: - era = data['teams'][opp_t]['players'][pplayer]['seasonStats']['pitching']['era'] - pitcher = '{} ({}) {}'.format(pitch_name, pitches, era) - else: - pitcher = '' - - if hm_id and len(lineup) == 9: - pitcher_url = 'http://statsapi.mlb.com/api/v1/people/{}'.format(hm_id) - #print(pitcher_url) - pitcher_data = requests.get(pitcher_url).json() - pitch_name = pitcher_data['people'][0]['fullName'] - pitches = pitcher_data['people'][0]['pitchHand']['code'] - for pplayer in data['teams'][hora]['players']: - if str(hm_id) in pplayer: - era = data['teams'][hora]['players'][pplayer]['seasonStats']['pitching']['era'] - hm_pitcher = ' :: \x02\x0312{}\x03\x02 {} ({}) {}'.format('P', pitch_name, pitches, era) - else: - hm_pitcher = '' -# except: -# irc.reply('Something went wrong parsing game data.') -# return - - if not lineup: - irc.reply('No lineup found yet, game active?') - return - - irc.reply('{} Lineup vs {} - \x02{}\x02 :: {}{}'.format(abbv, vs_name, pitcher, ', '.join(plr for plr in lineup), hm_pitcher)) - - - @wrap(['text']) - def umps(self, irc, msg, args, team): - """ - Fetches umpires for the game is playing - """ - team, date, tz = self._parseInput(team) - - if date: - test = pendulum.parse(date) - now = pendulum.now().format('YYYY-MM-DD') - now = pendulum.parse(now) - k = (test > now) - #print(date, ' | ', k, ' | ', pendulum.now()) - if k: - #irc_args = '{} {}'.format(team, date) - #self.mlb(msg, args, irc_args) - irc.reply("Sorry I can't predict the future.") - return - - if not team: - irc.reply('No team provided.') - return - - games = self._fetchGames(team, date) - - if not games: - irc.reply('No games found') - return - - games = self._parseGames(games, date) - games = self._sortGames(games) - - ump_url = 'http://statsapi.mlb.com/api/v1/game/{}/boxscore'.format(games[0]['id']) - #print(ump_url) - - try: - data = requests.get(ump_url).json() - except: - irc.reply('Something went wrong fetching game data.') - return - - umps = None - try: - for item in data['info']: - if item['label'] == 'Umpires': - umps = item['value'] - break - except: - irc.reply('Something went wrong parsing game data.') - return - - if not umps: - irc.reply('No umpires found yet, game active?') - return - - irc.reply('Umpires: {}'.format(umps)) - - - @wrap([optional('text')]) - def mlbpitcher(self, irc, msg, args, irc_args=None): - """ [] - Fetches pitcher(s) for given team and/or date. Defaults to today - if no input provided""" - - override = False - starter_only = False - if irc_args: - if '--all' in irc_args: - override = True - irc_args = irc_args.replace('--all', '') - if 'was' in irc_args: - irc_args = irc_args.replace('was', 'wsh') - if '--starter' in irc_args: - starter_only = True - override = True - irc_args = irc_args.replace('--starter', '') - - - team, date, tz = self._parseInput(irc_args) - - if date: - test = pendulum.parse(date) - now = pendulum.now().format('YYYY-MM-DD') - now = pendulum.parse(now) - k = (test > now) - #print(date, ' | ', k, ' | ', pendulum.now()) - if k: - #irc_args = '{} {}'.format(team, date) - #self.mlb(msg, args, irc_args) - irc.reply("Sorry I can't predict the future.") - return - - if not team: - irc.reply('No team provided.') - return - - games = self._fetchGames(team, date) - - if not games: - irc.reply('No games found') - return - - games = self._parseGames(games, date) - games = self._sortGames(games) - - pitchers = self._fetchPitchers(games, team, override) - - if not pitchers: - irc.reply('No pitchers found, has game started yet?') - return - - #print(pitchers) - - # if len(pitchers) == 2: - # if 'Game 2' in pitchers[1]: - # irc.reply('No pitchers found, has game started yet?') - # return - - reply_string = self._replyPitchersAsString(pitchers) - - # if len(reply_string) > 3: - # print(reply_string) - # if 'Game 2' in reply_string[-1]: - # reply_string.append('Not started yet') - - # what = type(reply_string) - # print(what) - - #print(reply_string) - - if type(reply_string) is tuple or type(reply_string) is list or type(reply_string) is dict: - if type(reply_string) is dict: - for string in reply_string: - irc.reply('\x02{}\x02'.format(string)) - if starter_only: - irc.reply(reply_string[string][0]) - else: - for pit in reply_string[string]: - irc.reply(pit) - else: - if starter_only: - irc.reply(reply_string[0]) - else: - for string in reply_string: - irc.reply(string) - else: - irc.reply(reply_string) - - @wrap(['text']) - def mlbinjuries(self, irc, msg, args, optteam): - """ - Returns injuries for given . - """ - - # get team id for matching - team, _, _ = self._parseInput(optteam) - - # url to get data - url = 'http://mlb.mlb.com/fantasylookup/json/named.wsfb_news_injury.bam' - - # try to get the data - try: - data = requests.get(url).json() - except: - irc.reply('Something went wrong fetching the data.') - return - - # pull out the relevant data - injuries = data['wsfb_news_injury']['queryResults']['row'] - - # build output - output = [] - - for injury in injuries: - #print(team, int(injury['team_id'])) - if not team: - if optteam.lower() in '{} {}'.format(injury['name_first'].lower(), injury['name_last'].lower()): - name = '\x02\x0312{} {}\x03\x02 ({})'.format(injury['name_first'], - injury['name_last'], - injury['position']) - inj = '{} on {} ({})'.format(injury['injury_status'], - injury['insert_ts'], - injury['injury_desc']) - upd = '\x02Latest:\x02 {}'.format(injury['injury_update']) - due = '\x02Returning:\x02 {}'.format(injury['due_back']) - output.append('{} :: {} | {} | {}'.format(name, inj, upd, due)) - else: - if int(team) == int(injury['team_id']): - # our team query matches let's go - name = '\x02\x0312{} {}\x03\x02 ({})'.format(injury['name_first'], - injury['name_last'], - injury['position']) - inj = '{} on {}'.format(injury['injury_status'], - injury['insert_ts']) - output.append('{} {}'.format(name, inj)) - - if not output: - irc.reply('ERROR: Team or player not found or no injuries found for provided team or player.') - return - - if team: - team_name = '\x02{}:\x02 '.format(self._TEAM_BY_ID['{}'.format(team)]) - irc.reply('{}{}'.format(team_name, ', '.join(i for i in output))) - else: - irc.reply(' || '.join(i for i in output)) - - @wrap([optional('int'), 'somethingwithoutspaces', optional('somethingwithoutspaces')]) - def next(self, irc, msg, args, optdays, optteam, optteam2): - """[<#>] [] - Returns the next # of games for team (or team vs team), defaults to 1 if not given - """ - - tids = self._TEAM_BY_TRI - - if not optdays: - optdays = 1 - - if optdays == 0: - optdays = 1 - - if optdays < 0: - optdays = optdays * -1 - - if optdays > 10: - irc.reply('ERROR: Too many games, has to be less than 10') - return - - - optteam = optteam.upper() - - if optteam not in tids: - irc.reply('ERROR: Invalid team, must be team abbreviation (ex: BOS)') - return - - if optteam2: - optteam2 = optteam2.upper() - if optteam == optteam2: - irc.reply('ERROR: Both provided teams are the same') - return - if optteam2 not in tids: - irc.reply('ERROR: Invalid team, must be team abbreviation (ex: BOS)') - return - - today = self._getTodayDate() - end = '2019-11-01' - try: - tid = tids[optteam] - except: - irc.reply('ERROR: Something went wrong parsing data') - return - #print(optdays, optteam) - # TBD switch out season=YYYYYYYY automatically - if optteam2: - try: - tid2 = tids[optteam2] - except: - irc.reply('ERROR: Something went wrong parsing data') - return - # url = ("https://statsapi.web.nhl.com/api/v1/schedule?startDate={}&endDate={}" + - # "&expand=schedule.teams,schedule.linescore,schedule.broadcasts.all,schedule.ticket,schedule.game.content.media.epg" + - # "&leaderCategories=&site=en_nhl&teamId={}&teamId={}") - url = ('https://statsapi.mlb.com/api/v1/schedule' - '?sportId=1&startDate={}&endDate={}' - '&hydrate=linescore,team,probablePitcher' - '&teamId={}&teamId={}') - - # Fetch content - content = requests.get(url.format(today, end, tid, tid2)) - content_json = content.json() - #print(url.format(today, end, tid)) - else: - url = ('https://statsapi.mlb.com/api/v1/schedule' - '?sportId=1&startDate={}&endDate={}' - '&hydrate=linescore,team,probablePitcher' - '&teamId={}') - - # Fetch content - content = requests.get(url.format(today, end, tid)) - content_json = content.json() - #print(url.format(today, end, tid)) - - games = [] - - if optteam2: - for idx, item in enumerate(content_json['dates']): - for gidx, _ in enumerate(item['games']): - if optteam in item['games'][gidx]['teams']['away']['team']['abbreviation'] and optteam2 in item['games'][gidx]['teams']['home']['team']['abbreviation']: - string1 = '{}'.format(self._ISODateToEasternTimeNext(item['games'][gidx]['gameDate'])) - string2 = '{} @ {}'.format(self._bold(item['games'][gidx]['teams']['away']['team']['abbreviation']), item['games'][gidx]['teams']['home']['team']['abbreviation']) - ppitchers = '' - if 'probablePitcher' in item['games'][gidx]['teams']['away'] and 'probablePitcher' in item['games'][gidx]['teams']['home']: - ppitchers = ' - {} vs {}'.format(item['games'][gidx]['teams']['away']['probablePitcher']['fullName'].split(',')[0], item['games'][gidx]['teams']['home']['probablePitcher']['fullName'].split(',')[0]) - games.append(string1 + ' | ' + string2 + ppitchers) - elif optteam2 in item['games'][gidx]['teams']['away']['team']['abbreviation'] and optteam in item['games'][gidx]['teams']['home']['team']['abbreviation']: - string1 = '{}'.format(self._ISODateToEasternTimeNext(item['games'][gidx]['gameDate'])) - string2 = '{} @ {}'.format(item['games'][gidx]['teams']['away']['team']['abbreviation'], self._bold(item['games'][gidx]['teams']['home']['team']['abbreviation'])) - ppitchers = '' - if 'probablePitcher' in item['games'][gidx]['teams']['away'] and 'probablePitcher' in item['games'][gidx]['teams']['home']: - ppitchers = ' - {} vs {}'.format(item['games'][gidx]['teams']['away']['probablePitcher']['fullName'].split(',')[0], item['games'][gidx]['teams']['home']['probablePitcher']['fullName'].split(',')[0]) - games.append(string1 + ' | ' + string2 + ppitchers) - - else: - pass - - if len(games) == 0: - irc.reply('No future games found for {} vs {}'.format(optteam, optteam2)) - return - #print(games) - games = games[:optdays] - - if len(games) <= 4: - for game in games: - irc.sendMsg(ircmsgs.privmsg(msg.args[0], game)) - else: - #m = len(games) - for game in games[:4]: - irc.sendMsg(ircmsgs.privmsg(msg.args[0], game)) - for game in games[4:]: - irc.reply(game) - else: - for idx, item in enumerate(content_json['dates'][:optdays]): - for gidx, _ in enumerate(item['games']): - #print(item['games'][gidx]['teams']['away']['team']['id']) - string1 = '{}'.format(self._ISODateToEasternTimeNext(item['games'][gidx]['gameDate'])) - necessary = '' - if item['games'][gidx]['ifNecessary'] == 'Y': - necessary = ' - If Necessary' - #string2 = '{}'.format('{} {}'.format('at', item['games'][gidx]['teams']['home']['team']['abbreviation']) if int(tid) == item['games'][gidx]['teams']['away']['team']['id'] else '{} {}'.format('vs', item['games'][gidx]['teams']['away']['team']['abbreviation'])) - if optteam in item['games'][gidx]['teams']['away']['team']['abbreviation']: - string2 = '{} @ {}'.format(self._bold(item['games'][gidx]['teams']['away']['team']['abbreviation']), item['games'][gidx]['teams']['home']['team']['abbreviation']) - else: - string2 = '{} @ {}'.format(item['games'][gidx]['teams']['away']['team']['abbreviation'], self._bold(item['games'][gidx]['teams']['home']['team']['abbreviation'])) - ppitchers = '' - if 'probablePitcher' in item['games'][gidx]['teams']['away'] and 'probablePitcher' in item['games'][gidx]['teams']['home']: - ppitchers = ' - {} vs {}'.format(item['games'][gidx]['teams']['away']['probablePitcher']['fullName'].split(',')[0], item['games'][gidx]['teams']['home']['probablePitcher']['fullName'].split(',')[0]) - games.append(string1 + ' | ' + string2 + ppitchers + necessary) - if len(games) <= 4: - for game in games: - irc.sendMsg(ircmsgs.privmsg(msg.args[0], game)) - else: - #m = len(games) - for game in games[:4]: - irc.sendMsg(ircmsgs.privmsg(msg.args[0], game)) - for game in games[4:]: - irc.reply(game) - - - @wrap([optional('int'), 'somethingwithoutspaces', optional('somethingwithoutspaces')]) - def last(self, irc, msg, args, optdays, optteam, optteam2): - """[<#>] [] - Returns the last # of games for team (or team vs team), defaults to 1 if not given - """ - - tids = self._TEAM_BY_TRI - - if not optdays: - optdays = -1 - numdays = 1 - else: - if optdays > 10: - irc.reply('ERROR: Too many games, has to be less than 10') - return - if optdays == 0: - optdays = 1 - if optdays < 0: - optdays = optdays * -1 - if optdays > 10: - irc.reply('ERROR: Too many games, has to be less than 10') - return - numdays = optdays - optdays = optdays * -1 - - optteam = optteam.upper() - - if optteam not in tids: - irc.reply('ERROR: Invalid team, must be team abbreviation (ex: BOS)') - return - - if optteam2: - optteam2 = optteam2.upper() - if optteam == optteam2: - irc.reply('ERROR: Both provided teams are the same') - return - if optteam2 not in tids: - irc.reply('ERROR: Invalid team, must be team abbreviation (ex: BOS)') - return - - today = self._getTodayDate() - dt_today = datetime.datetime.strptime(today, "%Y-%m-%d") - dt_yesterday = dt_today - datetime.timedelta(1) - yesterday = dt_yesterday.strftime('%Y-%m-%d') - #last_date = datetime.datetime.today() - datetime.timedelta(days=optdays) - #print(last_date) - end = '2019-03-01' - try: - tid = tids[optteam] - except: - irc.reply('ERROR: Something went wrong parsing data') - return - #print(optdays, optteam) - # TBD switch out season=YYYYYYYY automatically - if optteam2: - try: - tid2 = tids[optteam2] - except: - irc.reply('ERROR: Something went wrong parsing data') - return - url = ('https://statsapi.mlb.com/api/v1/schedule' - '?sportId=1&startDate={}&endDate={}' - '&hydrate=linescore,team,decisions' - '&teamId={}&teamId={}') - - # Fetch content - content = requests.get(url.format(end, yesterday, tid, tid2)) - content_json = content.json() - - #print(url.format(today, end, tid, tid2)) - else: - url = ('https://statsapi.mlb.com/api/v1/schedule' - '?sportId=1&startDate={}&endDate={}' - '&hydrate=linescore,team,decisions' - '&teamId={}') - - # Fetch content - content = requests.get(url.format(end, yesterday, tid)) - content_json = content.json() - #print(url.format(end, yesterday, tid)) - - games = [] - - if optteam2: # team vs team - for idx, item in enumerate(content_json['dates']): - for gidx, _ in enumerate(item['games']): - if (optteam in item['games'][gidx]['teams']['away']['team']['abbreviation'] and optteam2 in item['games'][gidx]['teams']['home']['team']['abbreviation']) or (optteam2 in item['games'][gidx]['teams']['away']['team']['abbreviation'] and optteam in item['games'][gidx]['teams']['home']['team']['abbreviation']): - date = self._ISODateToEasternTimeNext(item['games'][gidx]['gameDate'])[:-3] - - status_codes = ['DI', 'DC', 'DR', 'DS', 'PI'] - #print(item['games'][gidx]['status']['statusCode']) - if item['games'][gidx]['status']['statusCode'] in status_codes: - #print('hi ppd') - home = item['games'][gidx]['teams']['home']['team']['abbreviation'] - away = item['games'][gidx]['teams']['away']['team']['abbreviation'] - #ppd = ' \x037P\x03' - ppd = ' ' - reason = item['games'][gidx]['status']['reason'] - str_reply = '{} @ {} \x034PPD\x03 ({})'.format(away, home, reason) - string1 = '{}'.format(date.split(',')[0]) - games.append(string1 + ppd + ' | ' + str_reply) - continue - - if int(item['games'][gidx]['linescore']['currentInning']) > 9: - ot_type = ' (' + item['games'][gidx]['linescore']['currentInningOrdinal'] + ')' - else: - ot_type = '' - - string1 = '{}'.format(date.split(',')[0]) - - if int(item['games'][gidx]['teams']['away']['score']) > int(item['games'][gidx]['teams']['home']['score']): - away = self._bold(item['games'][gidx]['teams']['away']['team']['abbreviation']) - away_s = self._bold(item['games'][gidx]['teams']['away']['score']) - home = item['games'][gidx]['teams']['home']['team']['abbreviation'] - home_s = item['games'][gidx]['teams']['home']['score'] - if optteam in away: - result = self._green(' W') - try: - pitcher = ' - {}'.format(item['games'][gidx]['decisions']['winner']['fullName']) - except: - pitcher = '' - else: - result = self._red(' L') - try: - pitcher = ' - {}'.format(item['games'][gidx]['decisions']['loser']['fullName']) - except: - pitcher = '' - else: - home = self._bold(item['games'][gidx]['teams']['home']['team']['abbreviation']) - home_s = self._bold(item['games'][gidx]['teams']['home']['score']) - away = item['games'][gidx]['teams']['away']['team']['abbreviation'] - away_s = item['games'][gidx]['teams']['away']['score'] - if optteam in home: - result = self._green(' W') - try: - pitcher = ' - {}'.format(item['games'][gidx]['decisions']['winner']['fullName']) - except: - pitcher = '' - else: - result = self._red(' L') - try: - pitcher = ' - {}'.format(item['games'][gidx]['decisions']['loser']['fullName']) - except: - pitcher = '' - - string3 = '{} {} @ {} {}{}{}'.format(away, away_s, home, home_s, ot_type, pitcher) - - games.append(string1 + result + ' | ' + string3) - else: - pass - - #games = games[::-1] - games_r = games[optdays:] - games_r.reverse() - - if len(games) <= 4: - for game in games_r: - irc.sendMsg(ircmsgs.privmsg(msg.args[0], game)) - else: - for game in games_r[:4]: - irc.sendMsg(ircmsgs.privmsg(msg.args[0], game)) - for game in games_r[4:]: - irc.reply(game) - - else: # just team - for idx, item in enumerate(content_json['dates'][optdays:]): - for gidx, _ in enumerate(item['games']): - date = self._ISODateToEasternTimeNext(item['games'][gidx]['gameDate'])#[:-3] - - status_codes = ['DI', 'DC', 'DR', 'DS'] - #print(item['games'][gidx]['status']['statusCode']) - if item['games'][gidx]['status']['statusCode'] in status_codes: - #print('hi ppd') - home = item['games'][gidx]['teams']['home']['team']['abbreviation'] - away = item['games'][gidx]['teams']['away']['team']['abbreviation'] - #ppd = ' \x037P\x03' - ppd = ' ' - reason = item['games'][gidx]['status']['reason'] - str_reply = '{} @ {} \x034PPD\x03 ({})'.format(away, home, reason) - string1 = '{}'.format(date.split(',')[0]) - games.append(string1 + ppd + ' | ' + str_reply) - continue - - if int(item['games'][gidx]['linescore']['currentInning']) > 9: - ot_type = ' (F/' + item['games'][gidx]['linescore']['currentInningOrdinal'] + ')' - else: - ot_type = '' - - string1 = '{}'.format(date.split(',')[0]) - - if int(item['games'][gidx]['teams']['away']['score']) > int(item['games'][gidx]['teams']['home']['score']): - away = self._bold(item['games'][gidx]['teams']['away']['team']['abbreviation']) - away_s = self._bold(item['games'][gidx]['teams']['away']['score']) - home = item['games'][gidx]['teams']['home']['team']['abbreviation'] - home_s = item['games'][gidx]['teams']['home']['score'] - if optteam in away: - result = self._green(' W') - try: - pitcher = ' - {}'.format(item['games'][gidx]['decisions']['winner']['fullName']) - except: - pitcher = '' - else: - result = self._red(' L') - try: - pitcher = ' - {}'.format(item['games'][gidx]['decisions']['loser']['fullName']) - except: - pitcher = '' - else: - home = self._bold(item['games'][gidx]['teams']['home']['team']['abbreviation']) - home_s = self._bold(item['games'][gidx]['teams']['home']['score']) - away = item['games'][gidx]['teams']['away']['team']['abbreviation'] - away_s = item['games'][gidx]['teams']['away']['score'] - if optteam in home: - result = self._green(' W') - try: - pitcher = ' - {}'.format(item['games'][gidx]['decisions']['winner']['fullName']) - except: - pitcher = '' - else: - result = self._red(' L') - try: - pitcher = ' - {}'.format(item['games'][gidx]['decisions']['loser']['fullName']) - except: - pitcher = '' - - string3 = '{} {} @ {} {}{}{}'.format(away, away_s, home, home_s, ot_type, pitcher) - - games.append(string1 + result + ' | ' + string3) - - games_r = games[::-1] - - if len(games) <= 4: - for game in games_r: - irc.sendMsg(ircmsgs.privmsg(msg.args[0], game)) - else: - for game in games_r[:4]: - irc.sendMsg(ircmsgs.privmsg(msg.args[0], game)) - for game in games_r[4:]: - irc.reply(game) - -# @wrap(["text"]) -# def recap(self, irc, msg, args, optargs): -# """ [] -# Returns a video recap from optionally on . -# """ - -# # hq = False -# # if '--hq' in optargs or '--HQ' in optargs: -# # hq = True -# # optargs = optargs.strip('--hq') -# # optargs = optargs.strip('--HQ') -# # optargs = optargs.strip() - -# # print(optargs) - -# tids = self._TEAM_BY_TRI - -# # try: -# # gamepk = self._findGamepk("summary", optargs) -# # except: -# # # try looking for yesterday's game -# # #optargs += ' yesterday' - -# # try: -# api_url = 'https://statsapi.mlb.com/api/v1/teams/{}/?expand=team.schedule.previous'.format(tids[optargs.upper()]) -# print(api_url) -# data = requests.get(api_url) -# data = data.json() -# gamepk = str(data['teams'][0]['previousGameSchedule']['dates'][0]['games'][gidx]['gamePk']) -# # except: -# # irc.reply('Nothing found for given input') -# # return - -# if not gamepk: -# irc.reply('Nothing found, check your input') -# return -# url = ("http://statsapi.mlb.com/api/v1/schedule?expand=schedule.game.content.media.epg&leaderCategories=&site=en_nhl&gamePk=" + gamepk) -# content = requests.get(url) -# content_json = content.json() - -# print(url) - -# info = {} -# #print(gamepk) - -# VIDEOurl = {} -# try: -# for item in content_json['dates'][0]['games'][gidx]['content']['media']['epg']: -# if item['title'] == 'Recap': -# info['title'] = item['items'][0]['title'].strip('Recap: ') -# info['blurb'] = item['items'][0]['blurb'] -# info['description'] = item['items'][0]['description'] -# info['duration'] = "{}m{}s".format(item['items'][0]['duration'].split(':')[0].lstrip('0'), item['items'][0]['duration'].split(':')[1]) -# for video in item['items'][0]['playbacks']: -# if 'HTTP_CLOUD_WIRED_60' in video['name']: -# VIDEOurl['hls'] = self._shortenUrl(video['url']) -# if '1800K' in video['name']: -# VIDEOurl['mp4'] = self._shortenUrl(video['url']) -# # if not VIDEOurl: -# # VIDEOurl = 'No video recap available' -# # else: -# # VIDEOurl = self._shortenUrl(VIDEOurl) -# # info['url'] = VIDEOurl -# except: -# VIDEOurl = 'No video recap available' - -# if not VIDEOurl: -# VIDEOurl = 'No video recap available' - -# #test = {} -# #test['url'] = 'hi this is a test' - -# #print(len(test)) - -# if len(info) <= 1: -# irc.reply('No video recap available.') -# return - -# reply_string = ["\x02{}\x02 :: {}".format(info['title'], -# info['blurb']), -# "{}".format(info['description']), -# "\x02MP4:\x02 {} | \x02HLS:\x02 {} | {}".format(VIDEOurl['mp4'], VIDEOurl['hls'], info['duration'])] - -# for item in reply_string: -# irc.sendMsg(ircmsgs.privmsg(msg.args[0], item)) - - def _red(self, string): - """Returns a red string.""" - return ircutils.mircColor(string, 'red') - - def _yellow(self, string): - """Returns a yellow string.""" - return ircutils.mircColor(string, 'yellow') - - def _green(self, string): - """Returns a green string.""" - return ircutils.mircColor(string, 'green') - - def _blue(self, string): - """Returns a blue string.""" - return ircutils.mircColor(string, 'blue') - - def _bold(self, string): - """Returns a bold string.""" - return ircutils.bold(string) - - def _ul(self, string): - """Returns an underline string.""" - return ircutils.underline(string) - - def _bu(self, string): - """Returns a bold/underline string.""" - return ircutils.bold(ircutils.underline(string)) - -############################ -# Date-manipulation helpers -############################ - def _getTodayDate(self): - """Get the current date formatted as "YYYYMMDD". - Because the API separates games by day of start, we will consider and - return the date in the Pacific timezone. - The objective is to avoid reading future games anticipatedly when the - day rolls over at midnight, which would cause us to ignore games - in progress that may have started on the previous day. - Taking the west coast time guarantees that the day will advance only - when the whole continental US is already on that day.""" - today = self._pacificTimeNow().date() - today_iso = today.isoformat() - return today_iso #.replace('-', '') - - def _easternTimeNow(self): - return datetime.datetime.now(pytz.timezone('US/Eastern')) - - def _pacificTimeNow(self): - return datetime.datetime.now(pytz.timezone('US/Pacific')) - - def _ISODateToEasternTimeNext(self, iso): - """Convert the ISO date in UTC time that the API outputs into an - Eastern time formatted with am/pm. (The default human-readable format - for the listing of games).""" - date = dateutil.parser.parse(iso) - date_eastern = date.astimezone(pytz.timezone('US/Eastern')) - eastern_time = date_eastern.strftime('%a %m/%d, %I:%M %p %Z') - return "{}".format(eastern_time) # Strip the seconds - - def _fetchPitchers(self, games, team, override): - """fetch pitchers""" - - data = {} - current_only = False - ss_dh = False - test_status = 'I' - #print(games) - for idx, game in enumerate(games): - data['Game {}'.format(idx+1)] = [] - # if len(games) > 1: - # ss_dh = True - # data.append('\x02Game {}\x02'.format(idx+1)) - gpk = game['id'] - #print(game['status']) - if 'I' in game['status']: - current_only = True if not override else False - if 'S' == game['status']: - data['Game {}'.format(idx+1)] = False - break - url = 'https://statsapi.mlb.com/api/v1/game/{}/boxscore'.format(gpk) - #print(url) - temp = requests.get(url).json() - for teams in temp['teams']: - #print(temp['teams'][teams]['team']['id']) - if int(team) == temp['teams'][teams]['team']['id']: - pitcher_ids = temp['teams'][teams]['pitchers'] - for pitcher_id in pitcher_ids: - for player in temp['teams'][teams]['players']: - if int(pitcher_id) == temp['teams'][teams]['players'][player]['person']['id']: - if current_only: - #if temp['teams'][teams]['players'][player]['gameStatus']['isCurrentPitcher']: - data['Game {}'.format(idx+1)] = [temp['teams'][teams]['players'][player]] - else: - data['Game {}'.format(idx+1)].append(temp['teams'][teams]['players'][player]) - #print(data) - - #print(data) - #print(current_only, data) - if current_only and not data: - return ['No current pitcher for {} (use --all to see every pitcher)'.format(self._TEAM_BY_ID[team])] - - if not data: - return None - - if len(data) > 1: - for d in data: - if not data[d]: - data[d] = ['No current pitcher for {} in {} (use --all to see every pitcher)'.format(self._TEAM_BY_ID[team], d)] - else: - for d in data: - if not data[d]: - data[d] = ['No current pitcher for {} (use --all to see every pitcher)'.format(self._TEAM_BY_ID[team])] - - return data - - def _replyPitchersAsString(self, pitchers): - """parses and returns pitchers""" - - resp = [] - width = 0 - - def _iteratePitchers(pitchers): - - resp = [] - width = 0 - - #print(pitchers) - for idx, pitcher in enumerate(pitchers): - #print(pitcher) - if type(pitcher) == str: - continue - name = pitcher['person']['fullName'] - name = ' '.join(name.split()) - suffixes = ['jr.'] - lname = -1 - for suffix in suffixes: - if name.split(' ')[lname].lower() in suffix: - lname = -2 - else: - lname = -1 - if len(name.split(' ')[lname]) > width: - width = len(name.split(' ')[lname]) - - for pitcher in pitchers: - if type(pitcher) == str: - resp.append(pitcher) - continue - name = pitcher['person']['fullName'] - name = ' '.join(name.split()) - stats = pitcher['stats']['pitching'] - try: - era = '{:.2f}'.format((stats['earnedRuns']/float(stats['inningsPitched']))*9) - except: - if float(stats['inningsPitched']) == 0.0 and stats['earnedRuns'] > 0: - era = '∞' - else: - era = '0.00' - try: - opBA = '{:.3f}'.format((stats['hits'])/(stats['battersFaced'] - stats['baseOnBalls'])) - except: - opBA = '.000' - - suffixes = ['jr.'] - lname = -1 - #print(name.split(' ')[lname].lower()) - for suffix in suffixes: - #print(suffix) - if name.split(' ')[lname].lower() in suffix: - #print('hi') - lname = -2 - else: - lname = -1 - string = ('\x02\x0312{}. {:{width}}\x03 IP:\x02 {} ' - '\x02H:\x02 {} ' - '\x02R:\x02 {} ' - '\x02ER:\x02 {} ' - '\x02BB:\x02 {} ' - '\x02K:\x02 {} ' - '\x02HR:\x02 {} ' - '\x02BF:\x02 {:>2} ' - '\x02Pit:\x02 {:>3} ' - '\x02B-S:\x02 {:>2}-{:<2} ' - '\x02ERA:\x02 {:>6} ' - '\x02OpBA:\x02 {}').format( - name[0], - name.split(' ')[lname], - '0' if not stats.get('inningsPitched') else stats.get('inningsPitched'), - '0' if not stats.get('hits') else stats.get('hits'), - '0' if not stats.get('runs') else stats.get('runs'), - '0' if not stats.get('earnedRuns') else stats.get('earnedRuns'), - '0' if not stats.get('baseOnBalls') else stats.get('baseOnBalls'), - '0' if not stats.get('strikeOuts') else stats.get('strikeOuts'), - '0' if not stats.get('homeRuns') else stats.get('homeRuns'), - '0' if not stats.get('battersFaced') else stats.get('battersFaced'), - '0' if not stats.get('pitchesThrown') else stats.get('pitchesThrown'), - '0' if not stats.get('balls') else stats.get('balls'), - '0' if not stats.get('strikes') else stats.get('strikes'), - era, - opBA, - width=str(width)) - resp.append(string) - return resp - - - #print(len(pitchers)) - - if len(pitchers) > 1: - # double header - #print('hi') - resp = {} - for game in pitchers: - #print(pitchers[game]) - if "No current pitcher" not in pitchers[game][0]: - resp[game] = _iteratePitchers(pitchers[game]) - else: - g1_pitchers = pitchers['Game 1'] - resp = _iteratePitchers(g1_pitchers) - - #print(resp) - - return resp - - def _sortGames(self, games): - """sort based on status""" - - #sorted_games = sorted(games, key=lambda k: k['timestamp']) - sorted_games = sorted(games, key=lambda k: k['ended']) - - return sorted_games - - def _replyAsString(self, team, games, tz='US/Eastern', tv=False): - """parse games and return a string""" - tmp_dt = '\x02{}\x02: '.format(games[0]['date']) - - def _parseStatus(state, inning): - if not state: - state = 'F' - #print(state) - if 'T' in state or 'B' in state: - if 'T' in state: - resp = '\x033{}{}\x03'.format('↑', inning) - else: - resp = '\x033{}{}\x03'.format('↓', inning) - elif 'M' in state: - resp = '\x037{}{}\x03'.format(state, inning) - elif 'E' in state or 'F' in state: - if inning == 9 and 'E' not in state: - resp = '\x034{}\x03'.format(state) - elif 'E' in state: - resp = '\x037{}{}\x03'.format(state, inning) - else: - resp = '\x034{}/{}\x03'.format(state, inning) - else: - resp = '{}{}'.format(state, inning) - return resp - - def _parseTimezone(time, tz='US/Eastern'): - if not tz: - tz = 'US/Eastern' - - if 'Game 2' == time: - return time - - def _checkTarget(target): - """check input among common tz""" - target2 = target.upper() - common = {'CT': 'US/Central', - 'CDT': 'US/Central', - 'CST': 'US/Central', - 'MT': 'US/Mountain', - 'MDT': 'US/Mountain', - 'MST': 'US/Mountain', - 'PT': 'US/Pacific', - 'PDT': 'US/Pacific', - 'PST': 'US/Pacific', - 'ET': 'US/Eastern', - 'EDT': 'US/Eastern', - 'EST': 'US/Eastern', - 'CENTRAL': 'US/Central', - 'EASTERN': 'US/Eastern', - 'PACIFIC': 'US/Pacific', - 'MOUNTAIN': 'US/Mountain'} - if target2 in common: - target = common[target2] - #print(target) - return target - tz = _checkTarget(tz) - - return pendulum.parse(time, strict=False).in_tz(tz).format('h:mm A zz') - - tmp = [] - if len(games) == 1: - team = True - for game in games: - #print(game['homeTeam'], game['status']) - if game['status'] == 'I': - status = _parseStatus(game['state'], game['inning']) - if '↓' in status and game['risp']: - if 'Corners' in game['runners'] or 'Loaded' in game['runners'] or '3rd' in game['runners']: - game['homeTeam']['abbr'] = '\x034{}\x03'.format(game['homeTeam']['abbr']) - game['homeTeam']['full'] = '\x034{}\x03'.format(game['homeTeam']['full']) - elif '2nd' in game['runners']: - game['homeTeam']['abbr'] = '\x037{}\x03'.format(game['homeTeam']['abbr']) - game['homeTeam']['full'] = '\x037{}\x03'.format(game['homeTeam']['full']) - else: - if 'Corners' in game['runners'] or 'Loaded' in game['runners'] or '3rd' in game['runners']: - game['awayTeam']['abbr'] = '\x034{}\x03'.format(game['awayTeam']['abbr']) - game['awayTeam']['full'] = '\x034{}\x03'.format(game['awayTeam']['full']) - elif '2nd' in game['runners']: - game['awayTeam']['abbr'] = '\x037{}\x03'.format(game['awayTeam']['abbr']) - game['awayTeam']['full'] = '\x037{}\x03'.format(game['awayTeam']['full']) - if team: - away_disp = game['awayTeam']['full'] - home_disp = game['homeTeam']['full'] - else: - away_disp = game['awayTeam']['abbr'] - home_disp = game['homeTeam']['abbr'] - if game['homeScore'] > game['awayScore']: - tmp_st = '{} {} \x02{} {}\x02 {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - elif game['awayScore'] > game['homeScore']: - tmp_st = '\x02{} {}\x02 {} {} {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - else: - tmp_st = '{} {} {} {} {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - if game['broadcasts'] and tv: - if game['broadcasts']['tv'] and game['broadcasts']['radio']: - watch = ' [\x02TV:\x02 {} | \x02Radio:\x02 {}]'.format( - ', '.join(tv for tv in game['broadcasts']['tv']), - ', '.join(radio for radio in game['broadcasts']['radio'])) - elif game['broadcasts']['tv'] and not game['broadcasts']['radio']: - watch = ' [\x02TV:\x02 {}]'.format( - ', '.join(tv for tv in game['broadcasts']['tv'])) - elif not game['broadcasts']['tv'] and game['broadcasts']['radio']: - watch = ' [\x02Radio:\x02 {}]'.format( - ', '.join(radio for radio in game['broadcasts']['radio'])) - else: - watch = ' [No TV or Radio broadcasts found]' - tmp_st += watch - elif not game['broadcasts'] and tv: - tmp_st += ' [No TV or Radio broadcasts found]' - if team and ('M' not in status and 'E' not in status) and not tv: - if game['pitcher'] and game['batter']: - pb = ' | \x02P:\x02 {}, \x02AB:\x02 {} '.format(game['pitcher'], game['batter']) - else: - pb = '' - if game['runners']: - ro = ' | \x037Runners\x03: {}'.format(game['runners']) - else: - ro = '' - tmp_st += ' | \x033B\x03:{} \x037S\x03:{} \x034O\x03:{}{}{}| {}' - tmp_st = tmp_st.format(game['balls'], game['strikes'], game['outs'], ro, pb, game['last']) - elif team and ('M' in status or 'E' in status) and not tv: - tmp_st += ' | {}' - tmp_st = tmp_st.format(game['last']) - #if team: - #print(game['id']) - tmp.append(tmp_st) - elif ('F' in game['status'] or 'O' in game['status']) and not team: - status = _parseStatus(game['state'], game['inning']) - if team: - away_disp = game['awayTeam']['full'] - home_disp = game['homeTeam']['full'] - else: - away_disp = game['awayTeam']['abbr'] - home_disp = game['homeTeam']['abbr'] - if game['homeScore'] > game['awayScore']: - tmp_st = '{} {} \x02{} {}\x02 {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - elif game['awayScore'] > game['homeScore']: - tmp_st = '\x02{} {}\x02 {} {} {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - else: - tmp_st = '{} {} {} {} {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - - tmp.append(tmp_st) - elif (game['status'] == 'S' or game['status'] == 'P') and team and not tv: - if team: - away_disp = game['awayTeam']['full'] - home_disp = game['homeTeam']['full'] - else: - away_disp = game['awayTeam']['abbr'] - home_disp = game['homeTeam']['abbr'] - tmp_st = '{} {} @ {} {} {}'.format(away_disp, game['awayRecord'], - home_disp, game['homeRecord'], - game['dt'] if game['dh'] else _parseTimezone(game['dt'], tz)) - pitchers = ' | {} vs {}'.format(game['awayProb'], game['homeProb']) - tmp_st += pitchers - #print(game['broadcasts']) - if game['broadcasts']: - if game['broadcasts']['tv'] and game['broadcasts']['radio']: - watch = ' | \x02TV:\x02 {} | \x02Radio:\x02 {}'.format( - ', '.join(tv for tv in game['broadcasts']['tv']), - ', '.join(radio for radio in game['broadcasts']['radio'])) - elif game['broadcasts']['tv'] and not game['broadcasts']['radio']: - watch = ' | \x02TV:\x02 {}'.format( - ', '.join(tv for tv in game['broadcasts']['tv'])) - elif not game['broadcasts']['tv'] and game['broadcasts']['radio']: - watch = ' | \x02Radio:\x02 {}'.format( - ', '.join(radio for radio in game['broadcasts']['radio'])) - else: - watch = '' - tmp_st += watch - if game['description']: - tmp_st += ' | {}'.format(game['description']) - tmp.append(tmp_st) - elif ('F' in game['status'] or 'O' in game['status']) and team: - status = _parseStatus(game['state'], game['inning']) - if team: - away_disp = game['awayTeam']['full'] - home_disp = game['homeTeam']['full'] - else: - away_disp = game['awayTeam']['abbr'] - home_disp = game['homeTeam']['abbr'] - if game['homeScore'] > game['awayScore']: - tmp_st = '{} {} \x02{} {}\x02 {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - elif game['awayScore'] > game['homeScore']: - tmp_st = '\x02{} {}\x02 {} {} {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - else: - tmp_st = '{} {} {} {} {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - wls_line = ' | \x033W:\x03 {} \x034L:\x03 {}'.format( - game['decisions']['W'], game['decisions']['L']) - if game['decisions'].get('S'): - wls_line += ' \x037S:\x03 {}'.format(game['decisions']['S']) - tmp_st += wls_line - if game['homers']: - hr_str = ' | \x02HR: {}\x02: {} \x02{}\x02: {}'.format( - game['awayTeam']['abbr'], - ' '.join(item for item in game['homers'][game['awayTeam']['abbr']]), - game['homeTeam']['abbr'], - ' '.join(item for item in game['homers'][game['homeTeam']['abbr']])) - tmp_st += hr_str - tmp.append(tmp_st) - elif game['status'] == 'DI' or game['status'] == 'DC' or game['status'] == 'DS' or game['status'] == 'DR' \ - or game['status'] == 'DV' or game['status'] == 'DG': - if team: - away_disp = game['awayTeam']['full'] - home_disp = game['homeTeam']['full'] - else: - away_disp = game['awayTeam']['abbr'] - home_disp = game['homeTeam']['abbr'] - tmp_st = '{} @ {} \x034PPD\x03'.format(away_disp, home_disp) - if game['reason'] and team: - tmp_st += ' - {}'.format(game['reason']) - tmp.append(tmp_st) - # elif game['status'] == 'DI': - # tmp_st = '{} @ {} \x034PPD\x03'.format(game['awayTeam'], game['homeTeam']) - # if game['reason'] and team: - # tmp_st += ' - {}'.format(game['reason']) - # tmp.append(tmp_st) - elif game['status'] == 'PW': - if team: - away_disp = game['awayTeam']['full'] - home_disp = game['homeTeam']['full'] - else: - away_disp = game['awayTeam']['abbr'] - home_disp = game['homeTeam']['abbr'] - tmp_st = '{} @ {} {} - Warmup'.format(away_disp, home_disp, - _parseTimezone(game['dt'], tz)) - if team: - pitchers = ' | {} vs {}'.format(game['awayProb'], game['homeProb']) - tmp_st += pitchers - tv = True - if tv: - if game['broadcasts']: - if game['broadcasts']['tv'] and game['broadcasts']['radio']: - watch = ' [\x02TV:\x02 {} | \x02Radio:\x02 {}]'.format( - ', '.join(tv for tv in game['broadcasts']['tv']), - ', '.join(radio for radio in game['broadcasts']['radio'])) - elif game['broadcasts']['tv'] and not game['broadcasts']['radio']: - watch = ' [\x02TV:\x02 {}]'.format( - ', '.join(tv for tv in game['broadcasts']['tv'])) - elif not game['broadcasts']['tv'] and game['broadcasts']['radio']: - watch = ' [\x02Radio:\x02 {}]'.format( - ', '.join(radio for radio in game['broadcasts']['radio'])) - else: - watch = ' [No TV or Radio broadcasts found]' - else: - watch = ' [No TV or Radio broadcasts found]' - tmp_st += watch - tmp.append(tmp_st) - elif game['status'] == 'PC' or game['status'] == 'PS' or game['status'] == 'PR' or game['status'] == 'PI': - status = _parseStatus(game['state'], game['inning']) - if game['homeScore'] > game['awayScore']: - if team: - away_disp = game['awayTeam']['full'] - home_disp = game['homeTeam']['full'] - else: - away_disp = game['awayTeam']['abbr'] - home_disp = game['homeTeam']['abbr'] - tmp_st = '{} {} \x02{} {}\x02 {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - elif game['awayScore'] > game['homeScore']: - tmp_st = '\x02{} {}\x02 {} {} {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - else: - tmp_st = '{} {} {} {} {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - status) - tmp_st += ' \x037Delay\x03' - if game['reason'] and team: - tmp_st += ' - {}'.format(game['reason']) - tmp.append(tmp_st) - elif game['status'] == 'IW' or game['status'] == 'IC' or game['status'] == 'IS' or game['status'] == 'IR': - # status = _parseStatus(game['state'], game['inning']) - if team: - away_disp = game['awayTeam']['full'] - home_disp = game['homeTeam']['full'] - else: - away_disp = game['awayTeam']['abbr'] - home_disp = game['homeTeam']['abbr'] - if game['homeScore'] > game['awayScore']: - tmp_st = '{} {} \x02{} {}\x02'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - ) - elif game['awayScore'] > game['homeScore']: - tmp_st = '\x02{} {}\x02 {} {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - ) - else: - tmp_st = '{} {} {} {}'.format(away_disp, - game['awayScore'], - home_disp, - game['homeScore'], - ) - tmp_st += ' \x037Delay\x03' - if game['reason'] and team: - tmp_st += ' - {}'.format(game['reason']) - tmp.append(tmp_st) - else: - if team: - away_disp = game['awayTeam']['full'] - home_disp = game['homeTeam']['full'] - else: - away_disp = game['awayTeam']['abbr'] - home_disp = game['homeTeam']['abbr'] - tmp_st = '{} @ {} {}'.format(away_disp, home_disp, - game['dt'] if game['dh'] else _parseTimezone(game['dt'], tz)) - if game['status'] in self._STATUSES.keys() \ - and game['status'] not in ['S', 'P', 'D']: - tmp_st += ' - {}'.format(self._STATUSES[game['status']]) - if tv: - if game['broadcasts']: - if game['broadcasts']['tv'] and game['broadcasts']['radio']: - watch = ' [\x02TV:\x02 {} | \x02Radio:\x02 {}]'.format( - ', '.join(tv for tv in game['broadcasts']['tv']), - ', '.join(radio for radio in game['broadcasts']['radio'])) - elif game['broadcasts']['tv'] and not game['broadcasts']['radio']: - watch = ' [\x02TV:\x02 {}]'.format( - ', '.join(tv for tv in game['broadcasts']['tv'])) - elif not game['broadcasts']['tv'] and game['broadcasts']['radio']: - watch = ' [\x02Radio:\x02 {}]'.format( - ', '.join(radio for radio in game['broadcasts']['radio'])) - else: - watch = ' [No TV or Radio broadcasts found]' - else: - watch = ' [No TV or Radio broadcasts found]' - tmp_st += watch - tmp.append(tmp_st) - - if len(tmp) > 1 and team: - tmp_dt = [tmp_dt + tmp[0]] - for item in tmp[1:]: - tmp_dt.append(item) - return tmp_dt - - tmp_len = len(tmp) - if tmp_len > 12: - split_at_pre = ":{}".format(tmp_len // 2) - split_at_post = "{}:".format(tmp_len // 2) - split_at = tmp_len // 2 - #print(split_at) - tmp_dt = (tmp_dt + ' | '.join(item for item in tmp[:split_at]), ' | '.join(item for item in tmp[split_at:])) - else: - tmp_dt += ' | '.join(item for item in tmp) - - return tmp_dt - - def _parseInput(self, args=None): - """parse user input from mlb2""" - # return team, date, timezone - - tz = 'US/Eastern' - date = None - team = None - is_date = None - - if not args: - return team, date, tz - - arg_array = [] - for arg in args.split(' '): - arg_array.append(arg) - - for idx, arg in enumerate(arg_array): - #print(arg) - if '--tz' in arg: - #print(arg_array[idx+1]) - try: - tz = arg_array[idx+1] - except: - tz = 'US/Eastern' - if arg.lower() in self._FUZZY_DAYS or arg[:3].lower() in self._FUZZY_DAYS: - date = self._parseDate(arg) - #print(date) - #date = pendulum.parse(date).in_tz(tz) - try: - arg = arg.strip('-') - arg = arg.strip('/') - if arg[0].isdigit() and arg[1].isdigit() and arg[2].isalpha(): - if arg[-1].isdigit(): - yr = arg[-2:] - mnth = " ".join(re.findall("[a-zA-Z]+", arg)) - #print(mnth,yr) - rebuild = '{}-{}-{}'.format(mnth, arg[:2], yr) - else: - rebuild = arg[2:] + arg[:2] - #print('both', rebuild) - elif arg[0].isdigit() and arg[1].isalpha(): - rebuild = arg[1:] + arg[0] - #print('one', rebuild) - else: - rebuild = arg - - #print(rebuild) - is_date = pendulum.parse(rebuild, strict=False) - #print(is_date) - except: - is_date = None - if is_date: - date = is_date.format('YYYY-MM-DD') - if arg.upper() in self._TEAM_BY_TRI: - team = str(self._TEAM_BY_TRI[arg.upper()]) - elif arg.lower() in self._TEAM_BY_NICK: - abbr = str(self._TEAM_BY_NICK[arg.lower()]) - team = str(self._TEAM_BY_TRI[abbr]) - # else: - # return team, date, tz - - return team, date, tz - - def _parseDate(self, string): - """parse date""" - date = string[:3].lower() - if date in self._FUZZY_DAYS or string.lower() in self._FUZZY_DAYS: - if date == 'yes': - date_string = pendulum.yesterday('US/Pacific').format('YYYY-MM-DD') - #print(date_string) - return date_string - elif date == 'tod' or date == 'ton': - date_string = pendulum.now('US/Pacific').format('YYYY-MM-DD') - return date_string - elif date == 'tom': - date_string = pendulum.tomorrow('US/Pacific').format('YYYY-MM-DD') - return date_string - elif date == 'sun': - date_string = pendulum.now('US/Pacific').next(pendulum.SUNDAY).format('YYYY-MM-DD') - return date_string - elif date == 'mon': - date_string = pendulum.now('US/Pacific').next(pendulum.MONDAY).format('YYYY-MM-DD') - return date_string - elif date == 'tue': - date_string = pendulum.now('US/Pacific').next(pendulum.TUESDAY).format('YYYY-MM-DD') - return date_string - elif date == 'wed': - date_string = pendulum.now('US/Pacific').next(pendulum.WEDNESDAY).format('YYYY-MM-DD') - return date_string - elif date == 'thu': - date_string = pendulum.now('US/Pacific').next(pendulum.THURSDAY).format('YYYY-MM-DD') - return date_string - elif date == 'fri': - date_string = pendulum.now('US/Pacific').next(pendulum.FRIDAY).format('YYYY-MM-DD') - return date_string - elif date == 'sat': - date_string = pendulum.now('US/Pacific').next(pendulum.SATURDAY).format('YYYY-MM-DD') - return date_string - - def _fetchGames(self, team=None, date=None, league=None): - """fetches games for mlb2""" - - team = 'all' if not team else team - #print(team) - date = pendulum.now('US/Pacific').to_date_string() if not date else date - - if league: - url = ('https://statsapi.mlb.com/api/v1/schedule' - '?sportId={}&leagueId={}&date={}' - '&hydrate=team(leaders(showOnPreview(' - 'leaderCategories=[homeRuns,runsBattedIn,' - 'battingAverage],statGroup=[pitching,' - 'hitting]))),linescore(matchup,runners),' - 'flags,liveLookin,review,broadcasts(all),' - 'decisions,person,probablePitcher,stats,' - 'homeRuns,previousPlay,game(content(' - 'media(featured,epg),summary),tickets),' - 'seriesStatus(useOverride=true)').format(league[0], league[1], date) - else: - url = self._SCOREBOARD_ENDPOINT.format(date) - - if 'all' not in team: - url += '&teamId={}'.format(team) - - #print(url) - - try: - data = requests.get(url).json() - except: - return None - - try: - games = data['dates'][0]['games'] - except: - return None - - return games - - def _parseGames(self, games, date, team=None): - """parse games for mlb2""" - #print('http://statsapi.mlb.com/api/v1/game/{}/linescore'.format(games[0]['gamePk'])) - - #print(games) - if team: - #date = pendulum.now('US/Pacific').to_date_string() if not date else date - #games_url = self._SCOREBOARD_ENDPOINT.format(date) - #games_url += '&teamId={}'.format(team) - #games = requests.get(games_url).json() - #print(games_url) - try: - #games = games['dates'][0]['games'] - tmpg = [] - for game in games: - #print(game['teams']['away']['team']['id'], game['teams']['home']['team']['id']) - if str(team) in [str(game['teams']['away']['team']['id']), str(game['teams']['home']['team']['id'])]: - tmpg.append(game) - if tmpg: - games = tmpg - else: - return None - except: - return None - - #print(games) - - def _parseLastPlay(): - #print('len:', len(games)) - if len(games) == 1: - url = 'http://statsapi.mlb.com/api/v1/game/{}/playByPlay' - #print(url) - url = url.format(games[0]['gamePk']) - print(url, 'http://statsapi.mlb.com/api/v1/game/{}/playByPlay'.format(games[0]['gamePk'])) - data = requests.get(url) - data = data.json() - plays = reversed(data['allPlays']) - for play in plays: - if play['about']['isComplete'] == True: - last_play = play['result']['description'] - break - #print(last_play) - return last_play - - def _parseAllAtBats(): - if len(games) == 1: - url = 'https://statsapi.mlb.com/api/v1.1/game/{}/feed/live' - #print(url) - url = url.format(games[0]['gamePk']) - print(url) - data = requests.get(url) - data = data.json() - plays = data['liveData']['plays']['allPlays'] - #print(len(plays)) - desc = '' - at_bats = {} - for play in plays: - #print(play) - if 'result' in play: - if play['result'].get('type') == 'atBat': - if play['about'].get('isComplete'): - atidx = play['atBatIndex'] - #print(atidx) - res = play['result']['description'].strip() - res = ' '.join(res.split()) - desc = ' | \x02Result:\x02 {} :: {}'.format(play['result']['event'], - res) - #print(desc) - count = '\x02B:\x02{} \x02S:\x02{} \x02O:\x02{}'.format(play['count']['balls'], - play['count']['strikes'], - play['count']['outs']) - #print(count) - batter = '\x02AB:\x02 {}'.format(play['matchup']['batter']['fullName']) - #print(batter) - pitcher = '\x02P:\x02 {}'.format(play['matchup']['pitcher']['fullName']) - #print(pitcher) - pitches = [] - pit_num = 0 - if play['playEvents']: - for idx, pitch in enumerate(play['playEvents']): - if pitch['isPitch']: - pit_num += 1 - t = '({}){} - \x02{}mph {}\x02'.format(pit_num, pitch['details']['description'], - pitch['pitchData']['startSpeed'], - pitch['details']['type']['description']) - pitches.append(t) - #print(pitches) - at_bat = '{} | {} | {} | {}{}'.format(batter, pitcher, count, - ' \x034::\x03 '.join(p for p in pitches), - desc) - #print(at_bat) - at_bats[str(atidx)] = [at_bat, atidx+1, play['matchup']['batter']['fullName']] - - #print(at_bats) - return at_bats - - def _parseAtBat(): - if len(games) == 1: - url = 'https://statsapi.mlb.com/api/v1.1/game/{}/feed/live' - #print(url) - url = url.format(games[0]['gamePk']) - print(url) - data = requests.get(url) - data = data.json() - play = data['liveData']['plays']['currentPlay'] - #print(play) - desc = '' - if 'result' in play: - if play['about']['isComplete']: - res = play['result']['description'].strip() - res = ' '.join(res.split()) - desc = ' | \x02Result:\x02 {} :: {}'.format(play['result']['event'], - res) - #print('desc') - count = '\x02B:\x02{} \x02S:\x02{} \x02O:\x02{}'.format(play['count']['balls'], - play['count']['strikes'], - play['count']['outs']) - #print('count') - batter = '\x02AB:\x02 {}'.format(play['matchup']['batter']['fullName']) - #print('batter') - pitcher = '\x02P:\x02 {}'.format(play['matchup']['pitcher']['fullName']) - #print('pitcher') - pitches = [] - pit_num = 0 - if play['playEvents']: - for idx, pitch in enumerate(play['playEvents']): - if pitch['isPitch']: - pit_num += 1 - t = '({}){} - \x02{}mph {}\x02'.format(pit_num, pitch['details']['description'], - pitch['pitchData']['startSpeed'], - pitch['details']['type']['description']) - pitches.append(t) - #print('pitches') - at_bat = '{} | {} | {} | {}{}'.format(batter, pitcher, count, - ' \x034::\x03 '.join(p for p in pitches), - desc) - - #print(at_bat) - return at_bat - - - def _parsePitcher(pitcher): - name = pitcher['lastInitName'] - pitches = pitcher['stats'][1]['stats']['pitchesThrown'] - tmp = '{} ({})'.format(name, pitches) - return tmp - - def _parseBatter(batter): - name = batter['lastInitName'] - line = '{}/{}'.format(batter['stats'][0]['stats']['hits'], batter['stats'][0]['stats']['atBats']) - tmp = '{} ({})'.format(name, line) - return tmp - - def _parseRunners(runners): - first = True if runners.get('first') else False - second = True if runners.get('second') else False - third = True if runners.get('third') else False - - #print(first, second, third) - - if first and not second and not third: - resp = '1st' - shrt = '\x039⠠\x03' - risp = False - elif first and second and not third: - resp = '1st and 2nd' - shrt = '⠢' - risp = True - elif first and second and third: - resp = 'Loaded' - shrt = '∴' - risp = True - elif not first and second and not third: - resp = '2nd' - shrt = '⠁' - risp = True - elif not first and not second and third: - resp = "3rd" - shrt = '\x034⠄\x03' - risp = True - elif not first and not second and not third: - resp = '' - shrt = '' - risp = False - elif first and not second and third: - resp = 'Corners' - shrt = '⠤' - risp = True - elif not first and second and third: - resp = '2nd and 3rd' - shrt = '⠔' - risp = True - return resp, shrt, risp - - tmp = [] - for game in games: - dh = False - description = None - gamePk = game['gamePk'] - dt = game['gameDate'] - #print(dt) - timestamp = pendulum.parse(dt).in_tz('US/Eastern').int_timestamp - #print(timestamp) - date = pendulum.parse(game['gameDate']).in_tz('US/Eastern').format('MM/DD/YY') - time = pendulum.parse(game['gameDate']).in_tz('US/Eastern').format('h:mm A zz') - #print(date, time) - status = game['status']['statusCode'] - reason = game['status'].get('reason') - at_bat = '' - at_bats = {} - try: - description = game['description'] - except: - description = None - if game['doubleHeader'] == 'Y' or game['doubleHeader'] == 'S': - #print('doubleheader') - if game['gameNumber'] > 1: - #print('game 2+') - timestamp = pendulum.parse(dt).in_tz('US/Eastern') - timestamp = timestamp.add(days=1) - timestamp = timestamp.int_timestamp - dt = 'Game {}'.format(game['gameNumber']) - dh = True - #print(time) - try: - broadcasts = {} - broadcasts['tv'] = [] - broadcasts['radio'] = [] - for channel in game['broadcasts']: - if 'TV' in channel['type']: - if 'MLB.com' not in channel['name'] and 'out-of-market' not in channel['name']: - broadcasts['tv'].append(channel['name']) - elif 'M' in channel['type']: - if 'MLB.com' not in channel['name'] and 'out-of-market' not in channel['name']: - broadcasts['radio'].append(channel['name']) - broadcasts['tv'] = [*{*broadcasts['tv']}] - broadcasts['radio'] = [*{*broadcasts['radio']}] - except: - broadcasts = None - away_team = game['teams']['away']['team']['abbreviation'] - home_team = game['teams']['home']['team']['abbreviation'] - away_full = game['teams']['away']['team']['name'] - home_full = game['teams']['home']['team']['name'] - away_record = '({}-{})'.format(game['teams']['away']['leagueRecord']['wins'], - game['teams']['away']['leagueRecord']['losses']) - home_record = '({}-{})'.format(game['teams']['home']['leagueRecord']['wins'], - game['teams']['home']['leagueRecord']['losses']) - try: - try: - away_era = game['teams']['away']['probablePitcher']['stats'][1]['stats']['era'] - away_wins = game['teams']['away']['probablePitcher']['stats'][1]['stats']['wins'] - away_loss = game['teams']['away']['probablePitcher']['stats'][1]['stats']['losses'] - away_line = ' {}/{}-{}'. format(away_era, away_wins, away_loss) - except: - away_line = '' - try: - home_era = game['teams']['home']['probablePitcher']['stats'][1]['stats']['era'] - home_wins = game['teams']['home']['probablePitcher']['stats'][1]['stats']['wins'] - home_loss = game['teams']['home']['probablePitcher']['stats'][1]['stats']['losses'] - home_line = ' {}/{}-{}'. format(home_era, home_wins, home_loss) - except: - home_line = '' - - try: - away_prob = '{} ({}HP{})'.format( - game['teams']['away']['probablePitcher']['lastInitName'], - game['teams']['away']['probablePitcher']['pitchHand']['code'], - away_line) - except: - away_prob = 'TBD' - try: - home_prob = '{} ({}HP{})'.format( - game['teams']['home']['probablePitcher']['lastInitName'], - game['teams']['home']['probablePitcher']['pitchHand']['code'], - home_line) - except: - home_prob = 'TBD' - except: - away_prob = 'TBD' - home_prob = 'TBD' - away_score = game['teams']['away'].get('score') - home_score = game['teams']['home'].get('score') - #print('scores', away_score, home_score) - if not away_score: - away_score = 0 - if not home_score: - home_score = 0 - try: - inning = game['linescore'].get('currentInning') - except: - inning = 1 - try: - state = game['linescore'].get('inningState') - except: - state = None - #print(state) - balls = '0' - strikes = '0' - outs = '0' - pitcher = None - batter = None - runners = None - short_runners = None - risp = False - if not state: - if 'F' in status or 'O' in status: - state = 'F' - ended = True - last_play = '' - elif status == 'DI' or status == 'DC' or status == 'DS' or status == 'DR' \ - or status == 'DV' or status == 'DG': - state = state - ended = True - last_play = '' - else: - state = None - ended = False - last_play = '' - else: - if 'F' in status or 'O' in status: - state = 'F' - ended = True - last_play = '' - elif status == 'DI' or status == 'DC' or status == 'DS' or status == 'DR' \ - or status == 'DV' or status == 'DG': - state = state - ended = True - last_play = '' - else: - state = state[:1] - ended = False - if 'I' in status: - try: - pitcher = _parsePitcher(game['linescore']['defense']['pitcher']) - except: - pitcher = None - try: - batter = _parseBatter(game['linescore']['offense']['batter']) - except: - batter = None - try: - runners, short_runners, risp = _parseRunners(game['linescore']['offense']) - except: - runners = None - short_runners = None - risp = False - try: - try: - last_play = _parseLastPlay() - last_play = last_play.strip() - last_play = " ".join(last_play.split()) - except: - last_play = game['previousPlay']['result'].get('description').strip() - last_play = " ".join(last_play.split()) - except: - last_play = '' - - try: - at_bat = _parseAtBat() - except: - at_bat = '' - try: - at_bats = _parseAllAtBats() - except: - at_bats = {} - try: - balls = str(game['linescore']['balls']) - except: - balls = balls - try: - strikes = str(game['linescore']['strikes']) - except: - strikes = strikes - try: - outs = str(game['linescore']['outs']) - except: - outs = outs - else: - last_play = '' - at_bat = '' - at_bats = {} - if 'F' in status or 'O' in status: - decisions = {} - try: - decisions['W'] = '{} ({}/{}-{})'.format( - game['decisions']['winner']['lastInitName'], - game['decisions']['winner']['stats'][3]['stats']['era'], - game['decisions']['winner']['stats'][3]['stats']['wins'], - game['decisions']['winner']['stats'][3]['stats']['losses']) - except: - decisions['W'] = 'TBD' - try: - decisions['L'] = '{} ({}/{}-{})'.format( - game['decisions']['loser']['lastInitName'], - game['decisions']['loser']['stats'][3]['stats']['era'], - game['decisions']['loser']['stats'][3]['stats']['wins'], - game['decisions']['loser']['stats'][3]['stats']['losses']) - except: - decisions['L'] = 'TBD' - try: - save = game['decisions'].get('save') - except: - save = None - if save: - decisions['S'] = '{} ({}/{}-{}/{}-{})'.format( - save['lastInitName'], - save['stats'][3]['stats']['era'], - save['stats'][3]['stats']['wins'], - save['stats'][3]['stats']['losses'], - save['stats'][3]['stats']['saves'], - save['stats'][3]['stats']['blownSaves']) - homers = {} - homeRuns = game.get('homeRuns') - if homeRuns: - homers[away_team] = [] - homers[home_team] = [] - for item in homeRuns: - #print(item) - try: - name = item['matchup']['batter']['lastInitName'] - except: - name = item['matchup']['batter']['fullName'] - num = item['matchup']['batter']['stats'][2]['stats']['homeRuns'] - string = '{}({})'.format(name,num) - if 'top' in item['about']['halfInning']: - homers[away_team].append(string) - elif 'bot' in item['about']['halfInning']: - homers[home_team].append(string) - - if not homers[away_team]: - homers[away_team] = ['None'] - if not homers[home_team]: - homers[home_team] = ['None'] - - if homers[away_team]: - #print('hi') - homers[away_team] = [*{*homers[away_team]}] - if homers[home_team]: - #print('bye') - homers[home_team] = [*{*homers[home_team]}] - - else: - homers = None - decisions = None - #print(time) - tmp.append({'id': gamePk, 'date': date, 'time': time, 'dt': dt, 'dh': dh, 'timestamp': timestamp, - 'awayTeam': {'abbr': away_team, 'full': away_full}, 'awayScore': away_score, - 'homeTeam': {'abbr': home_team, 'full': home_full}, 'homeScore': home_score, - 'inning': inning, 'state': state, 'last': last_play, 'atBat': at_bat, 'atBats': at_bats, - 'status': status, 'reason': reason, 'broadcasts': broadcasts, 'ended': ended, - 'balls': balls, 'strikes': strikes, 'outs': outs, - 'pitcher': pitcher, 'batter': batter, 'runners': runners, 'sh_runs': short_runners, 'risp': risp, - 'awayRecord': away_record, 'homeRecord': home_record, - 'awayProb': away_prob, 'homeProb': home_prob, - 'decisions': decisions, 'homers': homers, 'description': description}) - - return(tmp) - -Class = MLBScores - - -# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/MLBScores/requirements.txt b/MLBScores/requirements.txt deleted file mode 100644 index 48d71da..0000000 --- a/MLBScores/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -requests -httplib2 -limnoria -pytz -python_dateutil -pendulum diff --git a/MLBScores/test.py b/MLBScores/test.py deleted file mode 100644 index b8c7cb0..0000000 --- a/MLBScores/test.py +++ /dev/null @@ -1,38 +0,0 @@ -### -# Copyright (c) 2018, cottongin -# 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. - -### - -from supybot.test import * - - -class MLBScoresTestCase(PluginTestCase): - plugins = ('MLBScores',) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/NBAScores/LICENSE b/NBA/LICENSE similarity index 100% rename from NBAScores/LICENSE rename to NBA/LICENSE diff --git a/NBAScores/README.md b/NBA/README.md similarity index 73% rename from NBAScores/README.md rename to NBA/README.md index 5ccbe91..574d66e 100644 --- a/NBAScores/README.md +++ b/NBA/README.md @@ -1,6 +1,6 @@ # NBAScores -A [Limnoria](https://github.com/ProgVal/Limnoria) plugin to retrieve NBA scores from NBA.com. +A [Limnoria](https://github.com/ProgVal/Limnoria) plugin to retrieve NBA basketball scores from NBA.com. ## Requirements * Python 3 diff --git a/NBAScores/__init__.py b/NBA/__init__.py similarity index 98% rename from NBAScores/__init__.py rename to NBA/__init__.py index c6e73fe..934b64f 100644 --- a/NBAScores/__init__.py +++ b/NBA/__init__.py @@ -29,7 +29,7 @@ ### """ -NBAScores: Get scores from NBA.com +NBA: Get scores from NBA.com """ import supybot diff --git a/NBAScores/config.py b/NBA/config.py similarity index 94% rename from NBAScores/config.py rename to NBA/config.py index 3c6fe8a..a203dc7 100644 --- a/NBAScores/config.py +++ b/NBA/config.py @@ -32,7 +32,7 @@ import supybot.conf as conf import supybot.registry as registry try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('NBAScores') + _ = PluginInternationalization('NBA') except: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -45,10 +45,10 @@ def configure(advanced): # user or not. You should effect your configuration by manipulating the # registry as appropriate. from supybot.questions import expect, anything, something, yn - conf.registerPlugin('NBAScores', True) + conf.registerPlugin('NBA', True) -NBA = conf.registerPlugin('NBAScores') +NBA = conf.registerPlugin('NBA') # This is where your configuration variables (if any) should go. For example: # conf.registerGlobalValue(NBA, 'someConfigVariableName', # registry.Boolean(False, _("""Help for someConfigVariableName."""))) diff --git a/NBAScores/plugin.py b/NBA/plugin.py similarity index 99% rename from NBAScores/plugin.py rename to NBA/plugin.py index be6cd83..c9bce85 100644 --- a/NBAScores/plugin.py +++ b/NBA/plugin.py @@ -1,6 +1,3 @@ -""" Limnoria plugin to retrieve results from NBA.com using their -(undocumented) JSON API. -""" ### # Copyright (c) 2018, Santiago Gil # @@ -27,7 +24,7 @@ import supybot.ircutils as ircutils import supybot.callbacks as callbacks try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('NBAScores') + _ = PluginInternationalization('NBA') except ImportError: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -40,7 +37,7 @@ import json import pytz from xml.etree import ElementTree -class NBAScores(callbacks.Plugin): +class NBA(callbacks.Plugin): """Get scores from NBA.com.""" _ENDPOINT_BASE_URL = 'https://data.nba.net' @@ -63,7 +60,7 @@ class NBAScores(callbacks.Plugin): 'BKN', 'POR', 'GSW', 'LAC', 'WAS')) def __init__(self, irc): - self.__parent = super(NBAScores, self) + self.__parent = super(NBA, self) self.__parent.__init__(irc) self._http = httplib2.Http('.cache') @@ -814,6 +811,6 @@ class NBAScores(callbacks.Plugin): return url -Class = NBAScores +Class = NBA # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/NBAScores/requirements.txt b/NBA/requirements.txt similarity index 100% rename from NBAScores/requirements.txt rename to NBA/requirements.txt diff --git a/NBAScores/test.py b/NBAScores/test.py deleted file mode 100644 index 94f2bd5..0000000 --- a/NBAScores/test.py +++ /dev/null @@ -1,38 +0,0 @@ -### -# Copyright (c) 2016, Santiago Gil -# 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. - -### - -from supybot.test import * - - -class NBATestCase(PluginTestCase): - plugins = ('NBAScores',) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/NFL/README.md b/NFL/README.md new file mode 100644 index 0000000..f9211d8 --- /dev/null +++ b/NFL/README.md @@ -0,0 +1 @@ +Fetches NFL football scores and game information from NFL.com diff --git a/NFLScores/__init__.py b/NFL/__init__.py similarity index 95% rename from NFLScores/__init__.py rename to NFL/__init__.py index 68cffcb..a90828f 100644 --- a/NFLScores/__init__.py +++ b/NFL/__init__.py @@ -6,7 +6,7 @@ ### """ -NFLScores: Fetches scores and game information from NFL.com +NFL: Fetches scores and game information from NFL.com """ import sys diff --git a/NFLScores/config.py b/NFL/config.py similarity index 80% rename from NFLScores/config.py rename to NFL/config.py index efd909e..ddbd040 100644 --- a/NFLScores/config.py +++ b/NFL/config.py @@ -8,7 +8,7 @@ from supybot import conf, registry try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('NFLScores') + _ = PluginInternationalization('NFL') except: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -21,12 +21,12 @@ def configure(advanced): # user or not. You should effect your configuration by manipulating the # registry as appropriate. from supybot.questions import expect, anything, something, yn - conf.registerPlugin('NFLScores', True) + conf.registerPlugin('NFL', True) -NFLScores = conf.registerPlugin('NFLScores') +NFL = conf.registerPlugin('NFL') # This is where your configuration variables (if any) should go. For example: -# conf.registerGlobalValue(NFLScores, 'someConfigVariableName', +# conf.registerGlobalValue(NFL, 'someConfigVariableName', # registry.Boolean(False, _("""Help for someConfigVariableName."""))) diff --git a/NFLScores/plugin.py b/NFL/plugin.py similarity index 98% rename from NFLScores/plugin.py rename to NFL/plugin.py index bb04b38..4e6a6e8 100644 --- a/NFLScores/plugin.py +++ b/NFL/plugin.py @@ -13,7 +13,7 @@ from supybot import utils, plugins, ircutils, callbacks from supybot.commands import * try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('NFLScores') + _ = PluginInternationalization('NFL') except ImportError: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -42,7 +42,7 @@ def getValidDateFmt(irc, msg, args, state): del args[0] addConverter('validDate', getValidDateFmt) -class NFLScores(callbacks.Plugin): +class NFL(callbacks.Plugin): """Fetches scores and game information from NFL.com""" threaded = True @@ -308,10 +308,10 @@ class NFLScores(callbacks.Plugin): print(player_id) except: - self.log.exception("ERROR :: NFLScores :: failed to get link for {0}".format(burl)) + self.log.exception("ERROR :: NFL :: failed to get link for {0}".format(burl)) pass except Exception as e: - self.log.info("ERROR :: NFLScores :: {0}".format(e)) + self.log.info("ERROR :: NFL :: {0}".format(e)) pass if not player_id: @@ -512,7 +512,7 @@ class NFLScores(callbacks.Plugin): return ircutils.underline(string) -Class = NFLScores +Class = NFL # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/NFLScores/requirements.txt b/NFL/requirements.txt similarity index 100% rename from NFLScores/requirements.txt rename to NFL/requirements.txt diff --git a/NFLScores/README.md b/NFLScores/README.md deleted file mode 100644 index 8f490d3..0000000 --- a/NFLScores/README.md +++ /dev/null @@ -1 +0,0 @@ -Fetches scores and game information from NFL.com diff --git a/NFLScores/test.py b/NFLScores/test.py deleted file mode 100644 index 8a42ab7..0000000 --- a/NFLScores/test.py +++ /dev/null @@ -1,15 +0,0 @@ -### -# Copyright (c) 2019, cottongin -# All rights reserved. -# -# -### - -from supybot.test import * - - -class NFLScoresTestCase(PluginTestCase): - plugins = ('NFLScores',) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/NHLScores/LICENSE b/NHL/LICENSE similarity index 100% rename from NHLScores/LICENSE rename to NHL/LICENSE diff --git a/NHLScores/README.md b/NHL/README.md similarity index 73% rename from NHLScores/README.md rename to NHL/README.md index 4175fee..3d4c327 100644 --- a/NHLScores/README.md +++ b/NHL/README.md @@ -1,6 +1,6 @@ #NHL -A [Limnoria](https://github.com/ProgVal/Limnoria) plugin to retrieve NHL scores from NHL.com. +A [Limnoria](https://github.com/ProgVal/Limnoria) plugin to retrieve NHL hockey scores from NHL.com. ## Requirements * Python 3 diff --git a/NHLScores/__init__.py b/NHL/__init__.py similarity index 99% rename from NHLScores/__init__.py rename to NHL/__init__.py index 24a6260..a06c29b 100644 --- a/NHLScores/__init__.py +++ b/NHL/__init__.py @@ -29,7 +29,7 @@ ### """ -NHLScores: Get NHL scores +NHL: Get NHL scores """ import supybot diff --git a/NHLScores/config.py b/NHL/config.py similarity index 94% rename from NHLScores/config.py rename to NHL/config.py index b7aeb9a..33cdcef 100644 --- a/NHLScores/config.py +++ b/NHL/config.py @@ -32,7 +32,7 @@ import supybot.conf as conf import supybot.registry as registry try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('NHLScores') + _ = PluginInternationalization('NHL') except: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -45,10 +45,10 @@ def configure(advanced): # user or not. You should effect your configuration by manipulating the # registry as appropriate. from supybot.questions import expect, anything, something, yn - conf.registerPlugin('NHLScores', True) + conf.registerPlugin('NHL', True) -NHLScores = conf.registerPlugin('NHLScores') +NHL = conf.registerPlugin('NHL') # This is where your configuration variables (if any) should go. For example: # conf.registerGlobalValue(NBA, 'someConfigVariableName', # registry.Boolean(False, _("""Help for someConfigVariableName."""))) diff --git a/NHLScores/plugin.py b/NHL/plugin.py similarity index 99% rename from NHLScores/plugin.py rename to NHL/plugin.py index 61b6886..9869934 100644 --- a/NHLScores/plugin.py +++ b/NHL/plugin.py @@ -1,4 +1,3 @@ -# NHLScores ### # Limnoria plugin to retrieve results from NHL.com using their (undocumented) # JSON API. @@ -26,7 +25,7 @@ import supybot.ircutils as ircutils import supybot.callbacks as callbacks try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('NHLScores') + _ = PluginInternationalization('NHL') except ImportError: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -40,10 +39,10 @@ import urllib.request import pendulum import requests -class NHLScores(callbacks.Plugin): +class NHL(callbacks.Plugin): """Get scores from NHL.com.""" def __init__(self, irc): - self.__parent = super(NHLScores, self) + self.__parent = super(NHL, self) self.__parent.__init__(irc) self._SCOREBOARD_ENDPOINT = ("https://statsapi.web.nhl.com/api/v1/schedule?startDate={}&endDate={}" + @@ -758,6 +757,6 @@ class NHLScores(callbacks.Plugin): return date -Class = NHLScores +Class = NHL # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/NHLScores/requirements.txt b/NHL/requirements.txt similarity index 100% rename from NHLScores/requirements.txt rename to NHL/requirements.txt diff --git a/NHLScores/test.py b/NHLScores/test.py deleted file mode 100644 index 30ac554..0000000 --- a/NHLScores/test.py +++ /dev/null @@ -1,38 +0,0 @@ -### -# Copyright (c) 2016, Santiago Gil -# 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. - -### - -from supybot.test import * - - -class NBATestCase(PluginTestCase): - plugins = ('NBA',) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/NewOdds/README.md b/NewOdds/README.md deleted file mode 100644 index c1d4271..0000000 --- a/NewOdds/README.md +++ /dev/null @@ -1 +0,0 @@ -Fetches odds diff --git a/NewOdds/test.py b/NewOdds/test.py deleted file mode 100644 index e2bdad1..0000000 --- a/NewOdds/test.py +++ /dev/null @@ -1,15 +0,0 @@ -### -# Copyright (c) 2018, cottongin -# All rights reserved. -# -# -### - -from supybot.test import * - - -class NewOddsTestCase(PluginTestCase): - plugins = ('NewOdds',) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/Odds/README.md b/Odds/README.md new file mode 100644 index 0000000..1698d6f --- /dev/null +++ b/Odds/README.md @@ -0,0 +1 @@ +Fetches sports odds for NFL, MLB, NHL, NBA, CFB, CBB games. diff --git a/NewOdds/__init__.py b/Odds/__init__.py similarity index 98% rename from NewOdds/__init__.py rename to Odds/__init__.py index 948a6cc..2dff427 100644 --- a/NewOdds/__init__.py +++ b/Odds/__init__.py @@ -6,7 +6,7 @@ ### """ -NewOdds: Fetches odds +Odds: Fetches odds """ import sys diff --git a/CFBScores/config.py b/Odds/config.py similarity index 80% rename from CFBScores/config.py rename to Odds/config.py index 459e030..91cf871 100644 --- a/CFBScores/config.py +++ b/Odds/config.py @@ -8,7 +8,7 @@ from supybot import conf, registry try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('CFBScores') + _ = PluginInternationalization('Odds') except: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -21,12 +21,12 @@ def configure(advanced): # user or not. You should effect your configuration by manipulating the # registry as appropriate. from supybot.questions import expect, anything, something, yn - conf.registerPlugin('CFBScores', True) + conf.registerPlugin('Odds', True) -CFBScores = conf.registerPlugin('CFBScores') +Odds = conf.registerPlugin('Odds') # This is where your configuration variables (if any) should go. For example: -# conf.registerGlobalValue(CFBScores, 'someConfigVariableName', +# conf.registerGlobalValue(Odds, 'someConfigVariableName', # registry.Boolean(False, _("""Help for someConfigVariableName."""))) diff --git a/NewOdds/plugin.py b/Odds/plugin.py similarity index 99% rename from NewOdds/plugin.py rename to Odds/plugin.py index 3fe29f6..07e1c8b 100644 --- a/NewOdds/plugin.py +++ b/Odds/plugin.py @@ -12,19 +12,19 @@ from supybot import utils, plugins, ircutils, callbacks from supybot.commands import * try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('NewOdds') + _ = PluginInternationalization('Odds') except ImportError: # Placeholder that allows to run the plugin on a bot # without the i18n module _ = lambda x: x -class NewOdds(callbacks.Plugin): +class Odds(callbacks.Plugin): """Fetches odds""" threaded = True def __init__(self, irc): - self.__parent = super(NewOdds, self) + self.__parent = super(Odds, self) self.__parent.__init__(irc) @wrap([getopts({'nfl': '', 'mlb': '', 'nhl': '', 'nba': '', @@ -341,7 +341,7 @@ class NewOdds(callbacks.Plugin): return number -Class = NewOdds +Class = Odds # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/GolfScores/requirements.txt b/Odds/requirements.txt similarity index 100% rename from GolfScores/requirements.txt rename to Odds/requirements.txt diff --git a/PGA/README.md b/PGA/README.md new file mode 100644 index 0000000..3b0fcd3 --- /dev/null +++ b/PGA/README.md @@ -0,0 +1 @@ +Fetches PGA Golf scores etc. diff --git a/GolfScores/__init__.py b/PGA/__init__.py similarity index 97% rename from GolfScores/__init__.py rename to PGA/__init__.py index 310350c..bff88ed 100644 --- a/GolfScores/__init__.py +++ b/PGA/__init__.py @@ -6,7 +6,7 @@ ### """ -GolfScores: Fetches golf scores +PGA: Fetches golf scores """ import sys diff --git a/PGA/config.py b/PGA/config.py new file mode 100644 index 0000000..c6ce510 --- /dev/null +++ b/PGA/config.py @@ -0,0 +1,33 @@ +### +# Copyright (c) 2018, cottongin +# All rights reserved. +# +# +### + +from supybot import conf, registry +try: + from supybot.i18n import PluginInternationalization + _ = PluginInternationalization('PGA') +except: + # Placeholder that allows to run the plugin on a bot + # without the i18n module + _ = lambda x: x + + +def configure(advanced): + # This will be called by supybot to configure this module. advanced is + # a bool that specifies whether the user identified themself as an advanced + # user or not. You should effect your configuration by manipulating the + # registry as appropriate. + from supybot.questions import expect, anything, something, yn + conf.registerPlugin('PGA', True) + + +PGA = conf.registerPlugin('PGA') +# This is where your configuration variables (if any) should go. For example: +# conf.registerGlobalValue(PGA, 'someConfigVariableName', +# registry.Boolean(False, _("""Help for someConfigVariableName."""))) + + +# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/GolfScores/plugin.py b/PGA/plugin.py similarity index 98% rename from GolfScores/plugin.py rename to PGA/plugin.py index 055fec5..f0bc740 100644 --- a/GolfScores/plugin.py +++ b/PGA/plugin.py @@ -12,7 +12,7 @@ from supybot import utils, plugins, ircutils, callbacks from supybot.commands import * try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('GolfScores') + _ = PluginInternationalization('PGA') except ImportError: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -21,7 +21,7 @@ except ImportError: CURRENT_URL = 'https://statdata.pgatour.com/{trn_type}/current/message.json' SCOREBOARD = 'https://statdata.pgatour.com/{trn_type}/{trn_id}/leaderboard-v2mini.json' -class GolfScores(callbacks.Plugin): +class PGA(callbacks.Plugin): """Fetches golf scores""" threaded = True @@ -162,7 +162,7 @@ class GolfScores(callbacks.Plugin): return -Class = GolfScores +Class = PGA # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/NewOdds/requirements.txt b/PGA/requirements.txt similarity index 100% rename from NewOdds/requirements.txt rename to PGA/requirements.txt diff --git a/README.md b/README.md index 6d7158c..e3e7c64 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,15 @@ Limnoria (an IRC bot) plugins I wrote or forked. All working under Python 3. -repolist oddluck / install oddluck Plugin_Name +Requires [Limnoria](https://github.com/ProgVal/Limnoria), obviously. Additional requirements in requirements.txt files -Requires Limnoria, obviously. Additional requirements in requirements.txt files +Plugins assume Python 3.6+, though many may still work with older versions. + +Easy installation: + +load PluginDownloader
+repolist oddluck
+install oddluck PluginName
+load PluginName
gitlab mirror: https://gitlab.com/oddluck/limnoria-plugins diff --git a/Soccer/README.md b/Soccer/README.md new file mode 100644 index 0000000..7d5d534 --- /dev/null +++ b/Soccer/README.md @@ -0,0 +1,6 @@ +Fetches soccer scores and other information. + +Leagues: epl, mls, ecl, uefac, uefae, efac, carabao, liga, bundesliga, +seriea, ligue, bbva, fifawc, wc, nations, concacaf, africa, cl, etc. + + diff --git a/Soccer/__init__.py b/Soccer/__init__.py new file mode 100644 index 0000000..4c0f08b --- /dev/null +++ b/Soccer/__init__.py @@ -0,0 +1,52 @@ +### +# Copyright (c) 2018, cottongin +# All rights reserved. +# +# +### + +""" +Soccer: Fetches soccer scores and other information +""" + +import sys +import supybot +from supybot import world + +# Use this for the version of this plugin. You may wish to put a CVS keyword +# in here if you're keeping the plugin in CVS or some similar system. +__version__ = "" + +# XXX Replace this with an appropriate author or supybot.Author instance. +__author__ = supybot.Author('cottongin', 'cottongin', + 'cottongin@cottongin.club') +__maintainer__ = getattr(supybot.authors, 'oddluck', + supybot.Author('oddluck', 'oddluck', 'oddluck@riseup.net')) + +# This is a dictionary mapping supybot.Author instances to lists of +# contributions. +__contributors__ = {} + +# This is a url where the most recent plugin package can be downloaded. +__url__ = 'https://github.com/oddluck/limnoria-plugins/' + +from . import config +from . import plugin +if sys.version_info >= (3, 4): + from importlib import reload +else: + from imp import reload +# In case we're being reloaded. +reload(config) +reload(plugin) +# Add more reloads here if you add third-party modules and want them to be +# reloaded when this plugin is reloaded. Don't forget to import them as well! + +if world.testing: + from . import test + +Class = plugin.Class +configure = config.configure + + +# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/SoccerScores/config.py b/Soccer/config.py similarity index 86% rename from SoccerScores/config.py rename to Soccer/config.py index c5f153d..570a399 100644 --- a/SoccerScores/config.py +++ b/Soccer/config.py @@ -8,7 +8,7 @@ from supybot import conf, registry try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('SoccerScores') + _ = PluginInternationalization('Soccer') except: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -21,10 +21,10 @@ def configure(advanced): # user or not. You should effect your configuration by manipulating the # registry as appropriate. from supybot.questions import expect, anything, something, yn - conf.registerPlugin('SoccerScores', True) + conf.registerPlugin('Soccer', True) -Soccer = conf.registerPlugin('SoccerScores') +Soccer = conf.registerPlugin('Soccer') # This is where your configuration variables (if any) should go. For example: # conf.registerGlobalValue(Soccer, 'someConfigVariableName', # registry.Boolean(False, _("""Help for someConfigVariableName."""))) diff --git a/SoccerScores/plugin.py b/Soccer/plugin.py similarity index 98% rename from SoccerScores/plugin.py rename to Soccer/plugin.py index ac7d063..5188ea3 100644 --- a/SoccerScores/plugin.py +++ b/Soccer/plugin.py @@ -1,4 +1,3 @@ -# Soccer ### # Copyright (c) 2018, cottongin # All rights reserved. @@ -11,7 +10,7 @@ from supybot import utils, plugins, ircutils, callbacks, schedule, conf from supybot.commands import * try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('SoccerScores') + _ = PluginInternationalization('Soccer') except ImportError: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -23,12 +22,12 @@ import pendulum import pickle -class SoccerScores(callbacks.Plugin): +class Soccer(callbacks.Plugin): """Fetches soccer scores and other information""" threaded = True def __init__(self, irc): - self.__parent = super(SoccerScores, self) + self.__parent = super(Soccer, self) self.__parent.__init__(irc) self.PICKLEFILE = conf.supybot.directories.data.dirize("soccer-leagues.db") @@ -144,7 +143,7 @@ class SoccerScores(callbacks.Plugin): if not league: irc.reply('ERROR: You must provide a league via --league ') - doc = irc.getCallback('SoccerScores').soccer.__doc__ + doc = irc.getCallback('Soccer').soccer.__doc__ doclines = doc.splitlines() s = '%s' % (doclines.pop(0)) if doclines: @@ -318,7 +317,7 @@ class SoccerScores(callbacks.Plugin): -Class = SoccerScores +Class = Soccer # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/SoccerScores/requirements.txt b/Soccer/requirements.txt similarity index 100% rename from SoccerScores/requirements.txt rename to Soccer/requirements.txt diff --git a/SoccerScores/README.md b/SoccerScores/README.md deleted file mode 100644 index 79401a5..0000000 --- a/SoccerScores/README.md +++ /dev/null @@ -1 +0,0 @@ -Fetches soccer scores and other information diff --git a/SoccerScores/__init__.py b/SoccerScores/__init__.py deleted file mode 100644 index 2d75e52..0000000 --- a/SoccerScores/__init__.py +++ /dev/null @@ -1,52 +0,0 @@ -### -# Copyright (c) 2018, cottongin -# All rights reserved. -# -# -### - -""" -SoccerScores: Fetches soccer scores and other information -""" - -import sys -import supybot -from supybot import world - -# Use this for the version of this plugin. You may wish to put a CVS keyword -# in here if you're keeping the plugin in CVS or some similar system. -__version__ = "" - -# XXX Replace this with an appropriate author or supybot.Author instance. -__author__ = supybot.Author('cottongin', 'cottongin', - 'cottongin@cottongin.club') -__maintainer__ = getattr(supybot.authors, 'oddluck', - supybot.Author('oddluck', 'oddluck', 'oddluck@riseup.net')) - -# This is a dictionary mapping supybot.Author instances to lists of -# contributions. -__contributors__ = {} - -# This is a url where the most recent plugin package can be downloaded. -__url__ = 'https://github.com/oddluck/limnoria-plugins/' - -from . import config -from . import plugin -if sys.version_info >= (3, 4): - from importlib import reload -else: - from imp import reload -# In case we're being reloaded. -reload(config) -reload(plugin) -# Add more reloads here if you add third-party modules and want them to be -# reloaded when this plugin is reloaded. Don't forget to import them as well! - -if world.testing: - from . import test - -Class = plugin.Class -configure = config.configure - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/SoccerScores/test.py b/SoccerScores/test.py deleted file mode 100644 index 9b6ae31..0000000 --- a/SoccerScores/test.py +++ /dev/null @@ -1,15 +0,0 @@ -### -# Copyright (c) 2018, cottongin -# All rights reserved. -# -# -### - -from supybot.test import * - - -class SoccerTestCase(PluginTestCase): - plugins = ('SoccerScores',) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: