From d1a10a0b2e596e943aca58fdfe4b23e34b0ef3b2 Mon Sep 17 00:00:00 2001 From: oddluck <39967334+oddluck@users.noreply.github.com> Date: Tue, 3 Mar 2020 19:59:47 +0000 Subject: [PATCH] Add Corona plugin. --- Corona/LICENSE | 14 +++++++ Corona/README.md | 2 + Corona/__init__.py | 64 ++++++++++++++++++++++++++++++ Corona/config.py | 50 +++++++++++++++++++++++ Corona/plugin.py | 98 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 228 insertions(+) create mode 100644 Corona/LICENSE create mode 100644 Corona/README.md create mode 100644 Corona/__init__.py create mode 100644 Corona/config.py create mode 100644 Corona/plugin.py diff --git a/Corona/LICENSE b/Corona/LICENSE new file mode 100644 index 0000000..ee7d6a5 --- /dev/null +++ b/Corona/LICENSE @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/Corona/README.md b/Corona/README.md new file mode 100644 index 0000000..b929321 --- /dev/null +++ b/Corona/README.md @@ -0,0 +1,2 @@ +# Corona +Limnoria coronavirus plugin diff --git a/Corona/__init__.py b/Corona/__init__.py new file mode 100644 index 0000000..34a9276 --- /dev/null +++ b/Corona/__init__.py @@ -0,0 +1,64 @@ +### +# Copyright (c) 2020, Hoaas +# 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. +### + +""" +Corona: Return coronavirus information +""" + +import supybot +import supybot.world as world +import imp + +# 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__ = "2020.02.24+git" + +# XXX Replace this with an appropriate author or supybot.Author instance. +__author__ = supybot.Author('Hoaas', 'Hoaas', '') +__maintainer__ = {} + +# 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 +imp.reload(plugin) # In case we're being reloaded. +# 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 diff --git a/Corona/config.py b/Corona/config.py new file mode 100644 index 0000000..152be56 --- /dev/null +++ b/Corona/config.py @@ -0,0 +1,50 @@ +### +# Copyright (c) 2020, Hoaas +# 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('Corona') +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('Corona', True) + + +Azure = conf.registerPlugin('Corona') diff --git a/Corona/plugin.py b/Corona/plugin.py new file mode 100644 index 0000000..9378b33 --- /dev/null +++ b/Corona/plugin.py @@ -0,0 +1,98 @@ +### +# Copyright (c) 2020, Hoaas +# 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 json +import urllib + +from supybot import utils, plugins, ircutils, callbacks +from supybot.commands import * +try: + from supybot.i18n import PluginInternationalization + _ = PluginInternationalization('Corona') +except ImportError: + # Placeholder that allows to run the plugin on a bot + # without the i18n module + _ = lambda x: x + + +class Corona(callbacks.Plugin): + """Displays current stats of the Coronavirus outbreak""" + threaded = True + + url = 'https://services1.arcgis.com/0MSEUqKaxRlEPj5g/arcgis/rest/services/ncov_cases/FeatureServer/1/query?f=json&where=Confirmed>0&returnGeometry=false&spatialRel=esriSpatialRelIntersects&outFields=*&orderByFields=Confirmed%20desc%2CCountry_Region%20asc%2CProvince_State%20asc&outSR=102100&resultOffset=0&resultRecordCount=250&cacheHint=true' + + @wrap([optional('text')]) + def corona(self, irc, msg, args, search): + """ + Displays Coronavirus stats""" + + try: + data = utils.web.getUrl(self.url).decode() + data = json.loads(data) + except utils.web.Error as e: + log.debug('Corona: error retrieving data from {0}: {1}'.format(self.url, e)) + return + + features = data.get('features') + if not features: + log.debug("Corona: Error retrieving features data.") + return + + total_confirmed = total_deaths = total_recovered = 0 + + extra_output = None + for region in features: + r = region.get('attributes') + + confirmed = r.get('Confirmed') + deaths = r.get('Deaths') + recovered = r.get('Recovered') + + if search: + name = r.get('Country_Region') + if search.lower() in name.lower(): + local_ratio_dead = deaths/confirmed + extra_output = ' {0} infected, {1} dead ({4:.00%}), {2} recovered in {3}.'\ + .format(confirmed, deaths, recovered, name, local_ratio_dead) + + total_confirmed += r.get('Confirmed') + total_deaths += r.get('Deaths') + total_recovered += r.get('Recovered') + + ratio_dead = total_deaths/total_confirmed + + output = '{0} infected, {1} dead ({3:.00%}), {2} recovered globally.'\ + .format(total_confirmed, total_deaths, total_recovered, ratio_dead) + + if extra_output: + output += extra_output + + irc.reply(output) + +Class = Corona