Some visual changes

This commit is contained in:
Zeva Rose 2022-10-01 22:49:27 -06:00
parent 697b163c1c
commit 13968c3c41
4 changed files with 139 additions and 43 deletions

View file

@ -1,5 +1,7 @@
"""Main JARVIS package."""
import logging
from functools import partial
from typing import Any
import aioredis
import jurigged
@ -17,11 +19,47 @@ from jarvis.utils import get_extensions
__version__ = const.__version__
def jlogger(logger: logging.Logger, event: Any) -> None:
"""
Logging for jurigged
Args:
logger: Logger to use
event: Event to parse
"""
jlog = partial(logger.log, 11)
if isinstance(event, jurigged.live.WatchOperation):
jlog(f"[bold]Watch[/] {event.filename}", extra={"markup": True})
elif isinstance(event, jurigged.codetools.AddOperation):
event_str = f"{event.defn.parent.dotpath()}:{event.defn.stashed.lineno}"
if isinstance(event.defn, jurigged.codetools.LineDefinition):
event_str += f" | {event.defn.text}"
jlog(
f"[bold green]Run[/] {event_str}",
extra={"markup": True},
)
else:
jlog(f"[bold green]Add[/] {event_str}", extra={"markup": True})
elif isinstance(event, jurigged.codetools.UpdateOperation):
if isinstance(event.defn, jurigged.codetools.FunctionDefinition):
event_str = f"{event.defn.parent.dotpath()}:{event.defn.stashed.lineno}"
jlog(f"[bold yellow]Update[/] {event_str}", extra={"markup": True})
elif isinstance(event, jurigged.codetools.DeleteOperation):
event_str = f"{event.defn.parent.dotpath()}:{event.defn.stashed.lineno}"
if isinstance(event.defn, jurigged.codetools.LineDefinition):
event_str += f" | {event.defn.text}"
jlog(f"[bold red]Delete[/] {event_str}", extra={"markup": True})
elif isinstance(event, (Exception, SyntaxError)):
logger.exception("Jurigged encountered error", exc_info=True)
else:
jlog(event)
async def run() -> None:
"""Run JARVIS"""
# Configure logger
jconfig = JarvisConfig.from_yaml()
logger = get_logger("jarvis", show_locals=jconfig.log_level == "DEBUG")
logger = get_logger("jarvis", show_locals=False) # jconfig.log_level == "DEBUG")
logger.setLevel(jconfig.log_level)
file_handler = logging.FileHandler(filename="jarvis.log", encoding="UTF-8", mode="w")
file_handler.setFormatter(
@ -49,7 +87,8 @@ async def run() -> None:
# External modules
if jconfig.log_level == "DEBUG":
jurigged.watch(pattern="jarvis/*.py")
logging.addLevelName(11, "\033[35mJURIG\033[0m ")
jurigged.watch(pattern="jarvis/*.py", logger=partial(jlogger, logger))
if jconfig.rook_token:
rook.start(token=jconfig.rook_token, labels={"env": "dev"})

View file

@ -11,8 +11,13 @@ COMMAND_TYPES = {
"SOFT": ["warning"],
"GOOD": ["unban", "unmute"],
}
CUSTOM_COMMANDS = {}
CUSTOM_EMOJIS = {
"ico_clock_green": "<:ico_clock_green:1019710693206933605>",
"ico_clock_yellow": "<:ico_clock_yellow:1019710734340472834>",
"ico_clock_red": "<:ico_clock_red:1019710735896551534>",
"ico_check_green": "<:ico_check_green:1019725504120639549>",
}
def get_command_color(command: str) -> str:

View file

@ -1,11 +1,12 @@
"""JARVIS dbrand cog."""
import logging
import re
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
import aiohttp
from bs4 import BeautifulSoup
from naff import Client, Extension, InteractionContext
from naff.client.utils import find
from naff.models.discord.embed import EmbedField
from naff.models.naff.application_commands import (
OptionTypes,
@ -16,6 +17,7 @@ from naff.models.naff.command import cooldown
from naff.models.naff.cooldowns import Buckets
from thefuzz import process
from jarvis.branding import CUSTOM_EMOJIS
from jarvis.config import JarvisConfig
from jarvis.data.dbrand import shipping_lookup
from jarvis.utils import build_embed
@ -51,11 +53,11 @@ async def parse_db_status() -> dict:
elif "column--status" in cell["class"]:
info = cell.find("span")["class"]
if any("green" in x for x in info):
cell = "🟢"
cell = CUSTOM_EMOJIS.get("ico_clock_green", "🟢")
elif any("yellow" in x for x in info):
cell = "🟡"
cell = CUSTOM_EMOJIS.get("ico_clock_yellow", "🟡")
elif any("red" in x for x in info):
cell = "🔴"
cell = CUSTOM_EMOJIS.get("ico_clock_red", "🔴")
elif any("black" in x for x in info):
cell = ""
else:
@ -91,20 +93,26 @@ class DbrandCog(Extension):
@db.subcommand(sub_cmd_name="status", sub_cmd_description="Get dbrand operational status")
async def _status(self, ctx: InteractionContext) -> None:
status = self.cache.get("status")
if not status or status["cache_expiry"] <= datetime.utcnow():
if not status or status["cache_expiry"] <= datetime.now(tz=timezone.utc):
status = await parse_db_status()
status["cache_expiry"] = datetime.utcnow() + timedelta(hours=2)
status["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta(hours=2)
self.cache["status"] = status
status = status.get("operations")
emojies = [x["Status"] for x in status]
fields = [
EmbedField(name=f'{x["Status"]} {x["Service"]}', value=x["Detail"]) for x in status
EmbedField(name=f'{x["Status"]} {x["Service"]}', value=x["Detail"]) for x in status
]
color = "#FBBD1E"
if all("green" in x for x in emojies):
color = "#38F657"
elif all("red" in x for x in emojies):
color = "#F12D20"
embed = build_embed(
title="Operational Status",
description="Current dbrand operational status.\n[View online](https://dbrand.com/status)",
fields=fields,
url="https://dbrand.com/status",
color="#FFBB00",
color=color,
)
embed.set_thumbnail(url="https://dev.zevaryx.com/db_logo.png")
@ -112,6 +120,7 @@ class DbrandCog(Extension):
text="dbrand.com",
icon_url="https://dev.zevaryx.com/db_logo.png",
)
await ctx.send(embeds=embed)
@db.subcommand(sub_cmd_name="gripcheck", sub_cmd_description="Watch a dbrand grip get thrown")
@ -206,12 +215,12 @@ class DbrandCog(Extension):
await ctx.defer()
dest = search.lower()
data = self.cache.get(dest, None)
if not data or data["cache_expiry"] < datetime.utcnow():
if not data or data["cache_expiry"] < datetime.now(tz=timezone.utc):
api_link = self.api_url + dest
data = await self._session.get(api_link)
if 200 <= data.status < 400:
data = await data.json()
data["cache_expiry"] = datetime.utcnow() + timedelta(hours=24)
data["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta(hours=24)
self.cache[dest] = data
else:
data = None
@ -220,32 +229,56 @@ class DbrandCog(Extension):
fields = []
for service in data["shipping_services_available"]:
service_data = self.cache.get(f"{dest}-{service}")
if not service_data or service_data["cache_expiry"] < datetime.utcnow():
if not service_data or service_data["cache_expiry"] < datetime.now(tz=timezone.utc):
service_data = await self._session.get(
self.api_url + dest + "/" + service["url"]
)
if service_data.status > 400:
continue
service_data = await service_data.json()
service_data["cache_expiry"] = datetime.utcnow() + timedelta(hours=24)
service_data["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta(
hours=24
)
self.cache[f"{dest}-{service}"] = service_data
title = f'{service_data["carrier"]} {service_data["tier-title"]} | {service_data["costs-min"]}'
message = service_data["time-title"]
if service_data["free_threshold_available"]:
title += " | Free over " + service_data["free-threshold"]
fields.append(EmbedField(title, message))
status = self.cache.get("status")
if not status or status["cache_expiry"] <= datetime.now(tz=timezone.utc):
status = await parse_db_status()
status["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta(hours=2)
self.cache["status"] = status
status = status["countries"]
country = data["country"]
if country.startswith("the"):
country = country.replace("the", "").strip()
shipping_info = find(lambda x: x["Country"] == country, status)
country = "-".join(x for x in data["country"].split(" ") if x != "the")
country_urlsafe = country.replace("-", "%20")
description = (
f"Click the link above to see shipping time to {data['country']}."
"\n[View all shipping destinations](https://dbrand.com/shipping)"
" | [Check shipping status]"
f"(https://dbrand.com/status#main-content:~:text={country_urlsafe})"
)
description = ""
color = "#FFBB00"
if shipping_info:
description = f'{shipping_info["Status"]}\u200b \u200b {shipping_info["Est. Delivery Time"].split(":")[0]}'
created = self.cache.get("status").get("cache_expiry") - timedelta(hours=2)
ts = int(created.timestamp())
description += f" \u200b | \u200b Last updated: <t:{ts}:R>\n\u200b"
if "green" in shipping_info["Status"]:
color = "#38F657"
elif "yellow" in shipping_info["Status"]:
color = "#FBBD1E"
elif "red" in shipping_info["Status"]:
color = "#F12D20"
else:
color = "#FFFFFF"
embed = build_embed(
title="Shipping to {}".format(data["country"]),
description=description,
color="#FFBB00",
color=color,
fields=fields,
url=self.base_url + "shipping/" + country,
)

59
poetry.lock generated
View file

@ -172,10 +172,10 @@ aiohttp = "*"
yarl = "*"
[package.extras]
test = ["vcrpy (==4.0.2)", "testfixtures (>4.13.2,<7)", "pytest-vcr", "pytest", "mock (>=0.8)", "asynctest (>=0.13.0)"]
lint = ["pydocstyle", "pre-commit", "flynt", "flake8", "black"]
dev = ["vcrpy (==4.0.2)", "testfixtures (>4.13.2,<7)", "pytest-vcr", "pytest", "mock (>=0.8)", "asynctest (>=0.13.0)", "pydocstyle", "pre-commit", "flynt", "flake8", "black"]
ci = ["coveralls"]
dev = ["black", "flake8", "flynt", "pre-commit", "pydocstyle", "asynctest (>=0.13.0)", "mock (>=0.8)", "pytest", "pytest-vcr", "testfixtures (>4.13.2,<7)", "vcrpy (==4.0.2)"]
lint = ["black", "flake8", "flynt", "pre-commit", "pydocstyle"]
test = ["asynctest (>=0.13.0)", "mock (>=0.8)", "pytest", "pytest-vcr", "testfixtures (>4.13.2,<7)", "vcrpy (==4.0.2)"]
[[package]]
name = "attrs"
@ -306,7 +306,7 @@ optional = false
python-versions = "*"
[package.extras]
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
test = ["hypothesis (==3.55.3)", "flake8 (==3.7.8)"]
[[package]]
name = "dateparser"
@ -323,9 +323,9 @@ regex = "<2019.02.19 || >2019.02.19,<2021.8.27 || >2021.8.27,<2022.3.15"
tzlocal = "*"
[package.extras]
calendars = ["convertdate", "hijri-converter", "convertdate"]
fasttext = ["fasttext"]
langdetect = ["langdetect"]
fasttext = ["fasttext"]
calendars = ["convertdate", "hijri-converter", "convertdate"]
[[package]]
name = "discord-typings"
@ -454,7 +454,7 @@ ansicon = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "jurigged"
version = "0.5.2"
version = "0.5.3"
description = "Live update of Python functions"
category = "main"
optional = false
@ -467,7 +467,7 @@ ovld = ">=0.3.1,<0.4.0"
watchdog = ">=1.0.2"
[package.extras]
develoop = ["giving (>=0.3.6,<0.4.0)", "rich (>=10.13.0,<11.0.0)", "hrepr (>=0.4.0,<0.5.0)"]
develoop = ["hrepr (>=0.4.0,<0.5.0)", "rich (>=10.13.0,<11.0.0)", "giving (>=0.3.6,<0.4.0)"]
[[package]]
name = "marshmallow"
@ -529,7 +529,7 @@ python-versions = "*"
[[package]]
name = "naff"
version = "1.9.0"
version = "1.10.0"
description = "Not another freaking fork"
category = "main"
optional = false
@ -784,7 +784,7 @@ optional = false
python-versions = ">=3.6.8"
[package.extras]
diagrams = ["railroad-diagrams", "jinja2"]
diagrams = ["jinja2", "railroad-diagrams"]
[[package]]
name = "pyppeteer"
@ -1163,9 +1163,9 @@ optional = false
python-versions = ">=3.7"
[package.extras]
docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"]
optional = ["python-socks", "wsaccel"]
test = ["websockets"]
optional = ["wsaccel", "python-socks"]
docs = ["sphinx-rtd-theme (>=0.5)", "Sphinx (>=3.4)"]
[[package]]
name = "websockets"
@ -1413,7 +1413,10 @@ dateparser = [
{file = "dateparser-1.1.1-py2.py3-none-any.whl", hash = "sha256:9600874312ff28a41f96ec7ccdc73be1d1c44435719da47fea3339d55ff5a628"},
{file = "dateparser-1.1.1.tar.gz", hash = "sha256:038196b1f12c7397e38aad3d61588833257f6f552baa63a1499e6987fa8d42d9"},
]
discord-typings = []
discord-typings = [
{file = "discord-typings-0.5.1.tar.gz", hash = "sha256:1a4fb1e00201416ae94ca64ca5935d447c005e0475b1ec274c1a6e09072db70e"},
{file = "discord_typings-0.5.1-py3-none-any.whl", hash = "sha256:55ebdb6d6f0f47df774a0c31193ba6a45de14625fab9c6fbd43bfe87bb8c0128"},
]
distro = [
{file = "distro-1.7.0-py3-none-any.whl", hash = "sha256:d596311d707e692c2160c37807f83e3820c5d539d5a83e87cfb6babd8ba3a06b"},
{file = "distro-1.7.0.tar.gz", hash = "sha256:151aeccf60c216402932b52e40ee477a939f8d58898927378a02abbe852c1c39"},
@ -1509,8 +1512,8 @@ jinxed = [
{file = "jinxed-1.2.0.tar.gz", hash = "sha256:032acda92d5c57cd216033cbbd53de731e6ed50deb63eb4781336ca55f72cda5"},
]
jurigged = [
{file = "jurigged-0.5.2-py3-none-any.whl", hash = "sha256:410ff6199c659108dace9179507342883fe2fffec1966fd19709f9d59fd69e24"},
{file = "jurigged-0.5.2.tar.gz", hash = "sha256:de1d4daeb99c0299eaa86f691d35cb1eab3bfa836cfe9a3551a56f3829479e3b"},
{file = "jurigged-0.5.3-py3-none-any.whl", hash = "sha256:355a9bddf42cae541e862796fb125827fc35573a982c6f35d3dc5621e59c91e3"},
{file = "jurigged-0.5.3.tar.gz", hash = "sha256:47cf4e9f10455a39602caa447888c06adda962699c65f19d8c37509817341b5e"},
]
marshmallow = [
{file = "marshmallow-3.16.0-py3-none-any.whl", hash = "sha256:53a1e0ee69f79e1f3e80d17393b25cfc917eda52f859e8183b4af72c3390c1f1"},
@ -1590,8 +1593,8 @@ mypy-extensions = [
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
]
naff = [
{file = "naff-1.9.0-py3-none-any.whl", hash = "sha256:20144495aed9452d9d2e713eb6ade9636601457ca3de255684b2186068505bcd"},
{file = "naff-1.9.0.tar.gz", hash = "sha256:f4870ea304747368d6d750f3d52fcbc96017bd7afaa7ec06a3e9a68ff301997d"},
{file = "naff-1.10.0-py3-none-any.whl", hash = "sha256:bb28ef19efb3f8e04f3569a3aac6b3e2738cf5747dea0bed483c458588933682"},
{file = "naff-1.10.0.tar.gz", hash = "sha256:d0ab71c39ea5bf352228f0bc3d3dfe3610122cb01733bca4565497078de95650"},
]
nafftrack = []
nanoid = [
@ -1850,6 +1853,7 @@ pymongo = [
{file = "pymongo-3.12.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:71c0db2c313ea8a80825fb61b7826b8015874aec29ee6364ade5cb774fe4511b"},
{file = "pymongo-3.12.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b779e87300635b8075e8d5cfd4fdf7f46078cd7610c381d956bca5556bb8f97"},
{file = "pymongo-3.12.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:351a2efe1c9566c348ad0076f4bf541f4905a0ebe2d271f112f60852575f3c16"},
{file = "pymongo-3.12.3-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:858af7c2ab98f21ed06b642578b769ecfcabe4754648b033168a91536f7beef9"},
{file = "pymongo-3.12.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0a02313e71b7c370c43056f6b16c45effbb2d29a44d24403a3d5ba6ed322fa3f"},
{file = "pymongo-3.12.3-cp310-cp310-manylinux1_i686.whl", hash = "sha256:d3082e5c4d7b388792124f5e805b469109e58f1ab1eb1fbd8b998e8ab766ffb7"},
{file = "pymongo-3.12.3-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:514e78d20d8382d5b97f32b20c83d1d0452c302c9a135f0a9022236eb9940fda"},
@ -1963,7 +1967,9 @@ python-gitlab = [
{file = "python-gitlab-3.5.0.tar.gz", hash = "sha256:29ae7fb9b8c9aeb2e6e19bd2fd04867e93ecd7af719978ce68fac0cf116ab30d"},
{file = "python_gitlab-3.5.0-py3-none-any.whl", hash = "sha256:73b5aa6502efa557ee1a51227cceb0243fac5529627da34f08c5f265bf50417c"},
]
python-levenshtein = []
python-levenshtein = [
{file = "python-Levenshtein-0.12.2.tar.gz", hash = "sha256:dc2395fbd148a1ab31090dd113c366695934b9e85fe5a4b2a032745efd0346f6"},
]
pytz = [
{file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"},
{file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"},
@ -1980,6 +1986,13 @@ pyyaml = [
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
{file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
{file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
{file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
{file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
{file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
{file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
{file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
@ -2133,7 +2146,10 @@ soupsieve = [
{file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"},
{file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"},
]
thefuzz = []
thefuzz = [
{file = "thefuzz-0.19.0-py2.py3-none-any.whl", hash = "sha256:4fcdde8e40f5ca5e8106bc7665181f9598a9c8b18b0a4d38c41a095ba6788972"},
{file = "thefuzz-0.19.0.tar.gz", hash = "sha256:6f7126db2f2c8a54212b05e3a740e45f4291c497d75d20751728f635bb74aa3d"},
]
tomli = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
@ -2146,7 +2162,10 @@ tweepy = [
{file = "tweepy-4.10.0-py3-none-any.whl", hash = "sha256:f0abbd234a588e572f880f99a094ac321217ff3eade6c0eca118ed6db8e2cf0a"},
{file = "tweepy-4.10.0.tar.gz", hash = "sha256:7f92574920c2f233663fff154745fc2bb0d10aedc23617379a912d8e4fefa399"},
]
typing-extensions = []
typing-extensions = [
{file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"},
{file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"},
]
tzdata = [
{file = "tzdata-2022.1-py2.py3-none-any.whl", hash = "sha256:238e70234214138ed7b4e8a0fab0e5e13872edab3be586ab8198c407620e2ab9"},
{file = "tzdata-2022.1.tar.gz", hash = "sha256:8b536a8ec63dc0751342b3984193a3118f8fca2afe25752bb9b7fffd398552d3"},