Corona: abbreviations, api fallback, etc.

This commit is contained in:
oddluck 2020-03-10 20:44:32 +00:00
parent 71a091e0c2
commit 69659794e5
6 changed files with 414 additions and 77 deletions

View File

@ -1,14 +0,0 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
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.

View File

@ -1,2 +1,11 @@
# Corona
Limnoria coronavirus plugin
Return the latest Coronavirus (COVID-19) statistics globally or by country/state.
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=T8E56M6SP9JH2)
`config plugins.corona.template` - Configure the template for replies
Template default: `\x02$location: \x0307$confirmed\x03 infected, \x0304$dead\x03 dead ($ratio), \x0309$recovered\x03 recovered.`
`config plugins.corona.countryFirst` - Country name abbreviations take precedence over USA state name abbreviations when `True`
countryFirst default: `False`

View File

@ -1,5 +1,6 @@
###
# Copyright (c) 2020, Hoaas
# Copyright (c) 2020, oddluck <oddluck@riseup.net>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -40,7 +41,7 @@ import imp
__version__ = "2020.02.24+git"
# XXX Replace this with an appropriate author or supybot.Author instance.
__author__ = supybot.Author('Hoaas', 'Hoaas', '')
__author__ = supybot.Author('oddluck', 'oddluck', 'oddluck@riseup.net')
__maintainer__ = {}
# This is a dictionary mapping supybot.Author instances to lists of

View File

@ -1,5 +1,6 @@
###
# Copyright (c) 2020, Hoaas
# Copyright (c) 2020, oddluck <oddluck@riseup.net>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -51,3 +52,6 @@ Corona = conf.registerPlugin('Corona')
conf.registerChannelValue(Corona, 'template',
registry.String("\x02$location: \x0307$confirmed\x03 infected, \x0304$dead\x03 dead ($ratio), \x0309$recovered\x03 recovered.", _("""Template for replies""")))
conf.registerChannelValue(Corona, 'countryFirst',
registry.Boolean(False, _("Give preference to country name abbreviations over USA state name abbreviations")))

View File

@ -1,5 +1,6 @@
###
# Copyright (c) 2020, Hoaas
# Copyright (c) 2020, oddluck <oddluck@riseup.net>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -28,8 +29,9 @@
###
import json
import urllib
import requests
import csv
from datetime import date, timedelta
from supybot import utils, plugins, ircutils, callbacks, log
from supybot.commands import *
try:
@ -41,82 +43,416 @@ except ImportError:
_ = lambda x: x
CC = {
"AF": "AFGHANISTAN",
"AX": "ÅLAND ISLANDS",
"AL": "ALBANIA",
"DZ": "ALGERIA",
"AS": "AMERICAN SAMOA",
"AD": "ANDORRA",
"AO": "ANGOLA",
"AI": "ANGUILLA",
"AQ": "ANTARCTICA",
"AG": "ANTIGUA AND BARBUDA",
"AR": "ARGENTINA",
"AM": "ARMENIA",
"AW": "ARUBA",
"AU": "AUSTRALIA",
"AT": "AUSTRIA",
"AZ": "AZERBAIJAN",
"BS": "BAHAMAS",
"BH": "BAHRAIN",
"BD": "BANGLADESH",
"BB": "BARBADOS",
"BY": "BELARUS",
"BE": "BELGIUM",
"BZ": "BELIZE",
"BJ": "BENIN",
"BM": "BERMUDA",
"BT": "BHUTAN",
"BO": "BOLIVIA, PLURINATIONAL STATE OF",
"BQ": "BONAIRE, SINT EUSTATIUS AND SABA",
"BA": "BOSNIA AND HERZEGOVINA",
"BW": "BOTSWANA",
"BV": "BOUVET ISLAND",
"BR": "BRAZIL",
"IO": "BRITISH INDIAN OCEAN TERRITORY",
"BN": "BRUNEI DARUSSALAM",
"BG": "BULGARIA",
"BF": "BURKINA FASO",
"BI": "BURUNDI",
"KH": "CAMBODIA",
"CM": "CAMEROON",
"CA": "CANADA",
"CV": "CAPE VERDE",
"KY": "CAYMAN ISLANDS",
"CF": "CENTRAL AFRICAN REPUBLIC",
"TD": "CHAD",
"CL": "CHILE",
"CN": "CHINA",
"CX": "CHRISTMAS ISLAND",
"CC": "COCOS (KEELING) ISLANDS",
"CO": "COLOMBIA",
"KM": "COMOROS",
"CG": "CONGO",
"CD": "CONGO, THE DEMOCRATIC REPUBLIC OF THE",
"CK": "COOK ISLANDS",
"CR": "COSTA RICA",
"CI": "CÔTE D'IVOIRE",
"HR": "CROATIA",
"CU": "CUBA",
"CW": "CURAÇAO",
"CY": "CYPRUS",
"CZ": "CZECH REPUBLIC",
"DK": "DENMARK",
"DJ": "DJIBOUTI",
"DM": "DOMINICA",
"DO": "DOMINICAN REPUBLIC",
"EC": "ECUADOR",
"EG": "EGYPT",
"SV": "EL SALVADOR",
"GQ": "EQUATORIAL GUINEA",
"ER": "ERITREA",
"EE": "ESTONIA",
"ET": "ETHIOPIA",
"FK": "FALKLAND ISLANDS (MALVINAS)",
"FO": "FAROE ISLANDS",
"FJ": "FIJI",
"FI": "FINLAND",
"FR": "FRANCE",
"GF": "FRENCH GUIANA",
"PF": "FRENCH POLYNESIA",
"TF": "FRENCH SOUTHERN TERRITORIES",
"GA": "GABON",
"GM": "GAMBIA",
"GE": "GEORGIA",
"DE": "GERMANY",
"GH": "GHANA",
"GI": "GIBRALTAR",
"GR": "GREECE",
"GL": "GREENLAND",
"GD": "GRENADA",
"GP": "GUADELOUPE",
"GU": "GUAM",
"GT": "GUATEMALA",
"GG": "GUERNSEY",
"GN": "GUINEA",
"GW": "GUINEA-BISSAU",
"GY": "GUYANA",
"HT": "HAITI",
"HM": "HEARD ISLAND AND MCDONALD ISLANDS",
"VA": "HOLY SEE (VATICAN CITY STATE)",
"HN": "HONDURAS",
"HK": "HONG KONG",
"HU": "HUNGARY",
"IS": "ICELAND",
"IN": "INDIA",
"ID": "INDONESIA",
"IR": "IRAN, ISLAMIC REPUBLIC OF",
"IQ": "IRAQ",
"IE": "IRELAND",
"IM": "ISLE OF MAN",
"IL": "ISRAEL",
"IT": "ITALY",
"JM": "JAMAICA",
"JP": "JAPAN",
"JE": "JERSEY",
"JO": "JORDAN",
"KZ": "KAZAKHSTAN",
"KE": "KENYA",
"KI": "KIRIBATI",
"KP": "KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF",
"KR": "KOREA, REPUBLIC OF",
"KW": "KUWAIT",
"KG": "KYRGYZSTAN",
"LA": "LAO PEOPLE'S DEMOCRATIC REPUBLIC",
"LV": "LATVIA",
"LB": "LEBANON",
"LS": "LESOTHO",
"LR": "LIBERIA",
"LY": "LIBYA",
"LI": "LIECHTENSTEIN",
"LT": "LITHUANIA",
"LU": "LUXEMBOURG",
"MO": "MACAO",
"MK": "MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF",
"MG": "MADAGASCAR",
"MW": "MALAWI",
"MY": "MALAYSIA",
"MV": "MALDIVES",
"ML": "MALI",
"MT": "MALTA",
"MH": "MARSHALL ISLANDS",
"MQ": "MARTINIQUE",
"MR": "MAURITANIA",
"MU": "MAURITIUS",
"YT": "MAYOTTE",
"MX": "MEXICO",
"FM": "MICRONESIA, FEDERATED STATES OF",
"MD": "MOLDOVA, REPUBLIC OF",
"MC": "MONACO",
"MN": "MONGOLIA",
"ME": "MONTENEGRO",
"MS": "MONTSERRAT",
"MA": "MOROCCO",
"MZ": "MOZAMBIQUE",
"MM": "MYANMAR",
"NA": "NAMIBIA",
"NR": "NAURU",
"NP": "NEPAL",
"NL": "NETHERLANDS",
"NC": "NEW CALEDONIA",
"NZ": "NEW ZEALAND",
"NI": "NICARAGUA",
"NE": "NIGER",
"NG": "NIGERIA",
"NU": "NIUE",
"NF": "NORFOLK ISLAND",
"MP": "NORTHERN MARIANA ISLANDS",
"NO": "NORWAY",
"OM": "OMAN",
"PK": "PAKISTAN",
"PW": "PALAU",
"PS": "PALESTINE, STATE OF",
"PA": "PANAMA",
"PG": "PAPUA NEW GUINEA",
"PY": "PARAGUAY",
"PE": "PERU",
"PH": "PHILIPPINES",
"PN": "PITCAIRN",
"PL": "POLAND",
"PT": "PORTUGAL",
"PR": "PUERTO RICO",
"QA": "QATAR",
"RE": "RÉUNION",
"RO": "ROMANIA",
"RU": "RUSSIAN FEDERATION",
"RW": "RWANDA",
"BL": "SAINT BARTHÉLEMY",
"SH": "SAINT HELENA, ASCENSION AND TRISTAN DA CUNHA",
"KN": "SAINT KITTS AND NEVIS",
"LC": "SAINT LUCIA",
"MF": "SAINT MARTIN (FRENCH PART)",
"PM": "SAINT PIERRE AND MIQUELON",
"VC": "SAINT VINCENT AND THE GRENADINES",
"WS": "SAMOA",
"SM": "SAN MARINO",
"ST": "SAO TOME AND PRINCIPE",
"SA": "SAUDI ARABIA",
"SN": "SENEGAL",
"RS": "SERBIA",
"SC": "SEYCHELLES",
"SL": "SIERRA LEONE",
"SG": "SINGAPORE",
"SX": "SINT MAARTEN (DUTCH PART)",
"SK": "SLOVAKIA",
"SI": "SLOVENIA",
"SB": "SOLOMON ISLANDS",
"SO": "SOMALIA",
"ZA": "SOUTH AFRICA",
"GS": "SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS",
"SS": "SOUTH SUDAN",
"ES": "SPAIN",
"LK": "SRI LANKA",
"SD": "SUDAN",
"SR": "SURINAME",
"SJ": "SVALBARD AND JAN MAYEN",
"SZ": "SWAZILAND",
"SE": "SWEDEN",
"CH": "SWITZERLAND",
"SY": "SYRIAN ARAB REPUBLIC",
"TW": "TAIWAN, PROVINCE OF CHINA",
"TJ": "TAJIKISTAN",
"TZ": "TANZANIA, UNITED REPUBLIC OF",
"TH": "THAILAND",
"TL": "TIMOR-LESTE",
"TG": "TOGO",
"TK": "TOKELAU",
"TO": "TONGA",
"TT": "TRINIDAD AND TOBAGO",
"TN": "TUNISIA",
"TR": "TURKEY",
"TM": "TURKMENISTAN",
"TC": "TURKS AND CAICOS ISLANDS",
"TV": "TUVALU",
"UG": "UGANDA",
"UA": "UKRAINE",
"AE": "UNITED ARAB EMIRATES",
"GB": "UNITED KINGDOM",
"US": "UNITED STATES",
"UM": "UNITED STATES MINOR OUTLYING ISLANDS",
"UY": "URUGUAY",
"UZ": "UZBEKISTAN",
"VU": "VANUATU",
"VE": "VENEZUELA, BOLIVARIAN REPUBLIC OF",
"VN": "VIET NAM",
"VG": "VIRGIN ISLANDS, BRITISH",
"VI": "VIRGIN ISLANDS, U.S.",
"WF": "WALLIS AND FUTUNA",
"EH": "WESTERN SAHARA",
"YE": "YEMEN",
"ZM": "ZAMBIA",
"ZW": "ZIMBABWE",
}
states = {
'AK': 'Alaska',
'AL': 'Alabama',
'AR': 'Arkansas',
'AS': 'American Samoa',
'AZ': 'Arizona',
'CA': 'California',
'CO': 'Colorado',
'CT': 'Connecticut',
'DC': 'District of Columbia',
'DE': 'Delaware',
'FL': 'Florida',
'GA': 'Georgia',
'GU': 'Guam',
'HI': 'Hawaii',
'IA': 'Iowa',
'ID': 'Idaho',
'IL': 'Illinois',
'IN': 'Indiana',
'KS': 'Kansas',
'KY': 'Kentucky',
'LA': 'Louisiana',
'MA': 'Massachusetts',
'MD': 'Maryland',
'ME': 'Maine',
'MI': 'Michigan',
'MN': 'Minnesota',
'MO': 'Missouri',
'MP': 'Northern Mariana Islands',
'MS': 'Mississippi',
'MT': 'Montana',
'NA': 'National',
'NC': 'North Carolina',
'ND': 'North Dakota',
'NE': 'Nebraska',
'NH': 'New Hampshire',
'NJ': 'New Jersey',
'NM': 'New Mexico',
'NV': 'Nevada',
'NY': 'New York',
'OH': 'Ohio',
'OK': 'Oklahoma',
'OR': 'Oregon',
'PA': 'Pennsylvania',
'PR': 'Puerto Rico',
'RI': 'Rhode Island',
'SC': 'South Carolina',
'SD': 'South Dakota',
'TN': 'Tennessee',
'TX': 'Texas',
'UT': 'Utah',
'VA': 'Virginia',
'VI': 'Virgin Islands',
'VT': 'Vermont',
'WA': 'Washington',
'WI': 'Wisconsin',
'WV': 'West Virginia',
'WY': 'Wyoming'
}
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&outFields=*"
@wrap([optional('text')])
def corona(self, irc, msg, args, search):
"""<area>
Displays Coronavirus stats
"""
git = api = False
url = "https://services1.arcgis.com/0MSEUqKaxRlEPj5g/arcgis/rest/services/ncov_cases/FeatureServer/1/query?f=json&where=Confirmed>0&outFields=*"
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))
data = requests.get(url, timeout=10)
data.raise_for_status()
except (requests.exceptions.RequestException, requests.exceptions.HTTPError) as e:
log.debug('Corona: error retrieving data from API: {0}'.format(e))
try:
day = date.today().strftime('%m-%d-%Y')
url = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/{0}.csv".format(day)
data = requests.get(url, timeout=10)
data.raise_for_status()
except (requests.exceptions.RequestException, requests.exceptions.HTTPError) as e:
log.debug('Corona: error retrieving data for today: {0}'.format(e))
try:
day = date.today() - timedelta(days=1)
day = day.strftime('%m-%d-%Y')
url = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/{0}.csv".format(day)
data = requests.get(url, timeout=10)
except (requests.exceptions.RequestException, requests.exceptions.HTTPError) as e:
log.debug('Corona: error retrieving data for yesterday: {0}'.format(e))
return
features = data.get('features')
if not features:
log.debug("Corona: Error retrieving features data.")
else:
git = True
data = csv.DictReader(data.iter_lines(decode_unicode = True))
else:
git = True
data = csv.DictReader(data.iter_lines(decode_unicode = True))
else:
api = True
data = json.loads(data.content)
data = data.get('features')
if not data:
log.debug("Corona: Error retrieving features data from API.")
return
total_confirmed = total_deaths = total_recovered = 0
confirmed = deaths = recovered = 0
location = 'Global'
for region in features:
for region in data:
if api:
r = region.get('attributes')
else:
r = region
if search:
if api:
region = r.get('Country_Region')
state = r.get('Province_State')
else:
region = r.get('Country/Region')
state = r.get('Province/State')
if len(search) == 2 and search.lower() != 'us' and search.lower() != 'uk':
if self.registryValue("countryFirst", msg.channel):
try:
search = CC[search.upper()]
except KeyError:
try:
search = states[search.upper()]
except KeyError:
pass
else:
try:
search = states[search.upper()]
except KeyError:
try:
search = CC[search.upper()]
except KeyError:
pass
if 'china' in search.lower():
search = 'mainland china'
elif search.lower() == 'usa' or 'united states' in search.lower():
search = 'us'
elif 'united kingdom' in search.lower():
search = 'uk'
if region and search.lower() == region.lower():
location = region
confirmed += r.get('Confirmed')
deaths += r.get('Deaths')
recovered += r.get('Recovered')
confirmed += int(r.get('Confirmed'))
deaths += int(r.get('Deaths'))
recovered += int(r.get('Recovered'))
local_ratio_dead = "{0:.1%}".format(deaths/confirmed)
elif state:
if search.lower() == state.lower():
elif state and search.lower() == state.lower():
location = state
confirmed += r.get('Confirmed')
deaths += r.get('Deaths')
recovered += r.get('Recovered')
confirmed += int(r.get('Confirmed'))
deaths += int(r.get('Deaths'))
recovered += int(r.get('Recovered'))
local_ratio_dead = "{0:.1%}".format(deaths/confirmed)
else:
state = state.split(',', 1)
if search.lower() == state[0].lower().strip():
location = r.get('Province_State')
confirmed += r.get('Confirmed')
deaths += r.get('Deaths')
recovered += r.get('Recovered')
local_ratio_dead = "{0:.1%}".format(deaths/confirmed)
elif len(state) > 1 and search.lower() == state[1].lower().strip():
location = state[1].strip()
confirmed += r.get('Confirmed')
deaths += r.get('Deaths')
recovered += r.get('Recovered')
local_ratio_dead = "{0:.1%}".format(deaths/confirmed)
elif search.lower().replace('county', '').strip() == state[0].lower().replace('county', '').strip():
location = r.get('Province_State')
confirmed += r.get('Confirmed')
deaths += r.get('Deaths')
recovered += r.get('Recovered')
local_ratio_dead = "{0:.1%}".format(deaths/confirmed)
total_confirmed += r.get('Confirmed')
total_deaths += r.get('Deaths')
total_recovered += r.get('Recovered')
total_confirmed += int(r.get('Confirmed'))
total_deaths += int(r.get('Deaths'))
total_recovered += int(r.get('Recovered'))
ratio_dead = "{0:.1%}".format(total_deaths/total_confirmed)
template = self.registryValue("template", msg.channel)
if location == 'Global':
template = template.replace("$location", location)
@ -130,7 +466,7 @@ class Corona(callbacks.Plugin):
template = template.replace("$dead", str(deaths))
template = template.replace("$recovered", str(recovered))
template = template.replace("$ratio", local_ratio_dead)
irc.reply(template)
Class = Corona

1
Corona/requirements.txt Normal file
View File

@ -0,0 +1 @@
requests