From c0969ea947d110d24ab0b95ef94ea76e1c9615ba Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 13:41:11 -0400 Subject: [PATCH 001/376] feat(aurora): added a Moderation model --- .gitignore | 1 + aurora/info.json | 1 + aurora/models.py | 62 +++++ poetry.lock | 693 +++++++++++++++++++++++++++-------------------- pyproject.toml | 3 +- 5 files changed, 467 insertions(+), 293 deletions(-) create mode 100644 aurora/models.py diff --git a/.gitignore b/.gitignore index 429d31f..3f0e8b8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .vscode site .venv +__pycache__ diff --git a/aurora/info.json b/aurora/info.json index 52a577e..d232f7e 100644 --- a/aurora/info.json +++ b/aurora/info.json @@ -9,6 +9,7 @@ "disabled": false, "min_bot_version": "3.5.0", "min_python_version": [3, 10, 0], + "requirements": ["pydantic"], "tags": [ "mod", "moderate", diff --git a/aurora/models.py b/aurora/models.py new file mode 100644 index 0000000..ba69b60 --- /dev/null +++ b/aurora/models.py @@ -0,0 +1,62 @@ +from typing import Dict, List, Optional + + +from discord import Guild +from pydantic import BaseModel +from utilities.database import connect + + +class Moderation(BaseModel): + moderation_id: int + timestamp: int + moderation_type: str + target_type: str + target_id: int + moderator_id: int + resolved: bool + expired: bool + duration: str + end_timestamp: int + reason: str + changes: List[Dict] + metadata: Dict + resolved_by: Optional[int] = None + resolve_reason: Optional[str] = None + role_id: Optional[int] = None + + def __str__(self): + return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}" + + async def from_sql(self, moderation_id: int, guild: Guild): + """""" + database = connect() + cursor = database.cursor() + + query = f"SELECT * FROM moderation_{guild.id} WHERE moderation_id = ?;" + cursor.execute(query, (moderation_id,)) + result = cursor.fetchone() + + cursor.close() + database.close() + + if result: + ( + self.moderation_id, + self.timestamp, + self.moderation_type, + self.target_type, + self.target_id, + self.moderator_id, + self.role_id, + self.duration, + self.end_timestamp, + self.reason, + self.resolved, + self.resolved_by, + self.resolve_reason, + self.expired, + self.changes, + self.metadata, + ) = result[0:16] + + return self diff --git a/poetry.lock b/poetry.lock index 2767d72..0a5918b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiohttp" @@ -123,6 +123,17 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "annotated-types" +version = "0.6.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, + {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, +] + [[package]] name = "apsw" version = "3.45.2.0" @@ -322,13 +333,13 @@ files = [ [[package]] name = "cairocffi" -version = "1.6.1" +version = "1.7.0" description = "cffi-based cairo bindings for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "cairocffi-1.6.1-py3-none-any.whl", hash = "sha256:aa78ee52b9069d7475eeac457389b6275aa92111895d78fbaa2202a52dac112e"}, - {file = "cairocffi-1.6.1.tar.gz", hash = "sha256:78e6bbe47357640c453d0be929fa49cd05cce2e1286f3d2a1ca9cbda7efdb8b7"}, + {file = "cairocffi-1.7.0-py3-none-any.whl", hash = "sha256:1f29a8d41dbda4090c0aa33bcdea64f3b493e95f74a43ea107c4a8a7b7f632ef"}, + {file = "cairocffi-1.7.0.tar.gz", hash = "sha256:7761863603894305f3160eca68452f373433ca8745ab7dd445bd2c6ce50dcab7"}, ] [package.dependencies] @@ -336,7 +347,7 @@ cffi = ">=1.1.0" [package.extras] doc = ["sphinx", "sphinx_rtd_theme"] -test = ["flake8", "isort", "numpy", "pikepdf", "pytest"] +test = ["numpy", "pikepdf", "pytest", "ruff"] xcb = ["xcffib (>=1.4.0)"] [[package]] @@ -766,30 +777,31 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.42" +version = "3.1.43" description = "GitPython is a Python library used to interact with Git repositories" optional = false python-versions = ">=3.7" files = [ - {file = "GitPython-3.1.42-py3-none-any.whl", hash = "sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd"}, - {file = "GitPython-3.1.42.tar.gz", hash = "sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb"}, + {file = "GitPython-3.1.43-py3-none-any.whl", hash = "sha256:eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff"}, + {file = "GitPython-3.1.43.tar.gz", hash = "sha256:35f314a9f878467f5453cc1fee295c3e18e52f1b99f10f6cf5b1682e968a9e7c"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" [package.extras] -test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar"] +doc = ["sphinx (==4.3.2)", "sphinx-autodoc-typehints", "sphinx-rtd-theme", "sphinxcontrib-applehelp (>=1.0.2,<=1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (>=2.0.0,<=2.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)"] +test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions"] [[package]] name = "griffe" -version = "0.42.1" +version = "0.44.0" description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." optional = false python-versions = ">=3.8" files = [ - {file = "griffe-0.42.1-py3-none-any.whl", hash = "sha256:7e805e35617601355edcac0d3511cedc1ed0cb1f7645e2d336ae4b05bbae7b3b"}, - {file = "griffe-0.42.1.tar.gz", hash = "sha256:57046131384043ed078692b85d86b76568a686266cc036b9b56b704466f803ce"}, + {file = "griffe-0.44.0-py3-none-any.whl", hash = "sha256:8a4471c469ba980b87c843f1168850ce39d0c1d0c7be140dca2480f76c8e5446"}, + {file = "griffe-0.44.0.tar.gz", hash = "sha256:34aee1571042f9bf00529bc715de4516fb6f482b164e90d030300601009e0223"}, ] [package.dependencies] @@ -1057,13 +1069,13 @@ pytz = "*" [[package]] name = "mkdocs-material" -version = "9.5.15" +version = "9.5.18" description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_material-9.5.15-py3-none-any.whl", hash = "sha256:e5c96dec3d19491de49ca643fc1dbb92b278e43cdb816c775bc47db77d9b62fb"}, - {file = "mkdocs_material-9.5.15.tar.gz", hash = "sha256:39f03cca45e82bf54eb7456b5a18bd252eabfdd67f237a229471484a0a4d4635"}, + {file = "mkdocs_material-9.5.18-py3-none-any.whl", hash = "sha256:1e0e27fc9fe239f9064318acf548771a4629d5fd5dfd45444fd80a953fe21eb4"}, + {file = "mkdocs_material-9.5.18.tar.gz", hash = "sha256:a43f470947053fa2405c33995f282d24992c752a50114f23f30da9d8d0c57e62"}, ] [package.dependencies] @@ -1303,61 +1315,62 @@ files = [ [[package]] name = "orjson" -version = "3.9.15" +version = "3.10.0" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" files = [ - {file = "orjson-3.9.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:d61f7ce4727a9fa7680cd6f3986b0e2c732639f46a5e0156e550e35258aa313a"}, - {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4feeb41882e8aa17634b589533baafdceb387e01e117b1ec65534ec724023d04"}, - {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fbbeb3c9b2edb5fd044b2a070f127a0ac456ffd079cb82746fc84af01ef021a4"}, - {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b66bcc5670e8a6b78f0313bcb74774c8291f6f8aeef10fe70e910b8040f3ab75"}, - {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2973474811db7b35c30248d1129c64fd2bdf40d57d84beed2a9a379a6f57d0ab"}, - {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fe41b6f72f52d3da4db524c8653e46243c8c92df826ab5ffaece2dba9cccd58"}, - {file = "orjson-3.9.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4228aace81781cc9d05a3ec3a6d2673a1ad0d8725b4e915f1089803e9efd2b99"}, - {file = "orjson-3.9.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f7b65bfaf69493c73423ce9db66cfe9138b2f9ef62897486417a8fcb0a92bfe"}, - {file = "orjson-3.9.15-cp310-none-win32.whl", hash = "sha256:2d99e3c4c13a7b0fb3792cc04c2829c9db07838fb6973e578b85c1745e7d0ce7"}, - {file = "orjson-3.9.15-cp310-none-win_amd64.whl", hash = "sha256:b725da33e6e58e4a5d27958568484aa766e825e93aa20c26c91168be58e08cbb"}, - {file = "orjson-3.9.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c8e8fe01e435005d4421f183038fc70ca85d2c1e490f51fb972db92af6e047c2"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87f1097acb569dde17f246faa268759a71a2cb8c96dd392cd25c668b104cad2f"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff0f9913d82e1d1fadbd976424c316fbc4d9c525c81d047bbdd16bd27dd98cfc"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8055ec598605b0077e29652ccfe9372247474375e0e3f5775c91d9434e12d6b1"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6768a327ea1ba44c9114dba5fdda4a214bdb70129065cd0807eb5f010bfcbb5"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12365576039b1a5a47df01aadb353b68223da413e2e7f98c02403061aad34bde"}, - {file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:71c6b009d431b3839d7c14c3af86788b3cfac41e969e3e1c22f8a6ea13139404"}, - {file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e18668f1bd39e69b7fed19fa7cd1cd110a121ec25439328b5c89934e6d30d357"}, - {file = "orjson-3.9.15-cp311-none-win32.whl", hash = "sha256:62482873e0289cf7313461009bf62ac8b2e54bc6f00c6fabcde785709231a5d7"}, - {file = "orjson-3.9.15-cp311-none-win_amd64.whl", hash = "sha256:b3d336ed75d17c7b1af233a6561cf421dee41d9204aa3cfcc6c9c65cd5bb69a8"}, - {file = "orjson-3.9.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:82425dd5c7bd3adfe4e94c78e27e2fa02971750c2b7ffba648b0f5d5cc016a73"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c51378d4a8255b2e7c1e5cc430644f0939539deddfa77f6fac7b56a9784160a"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6ae4e06be04dc00618247c4ae3f7c3e561d5bc19ab6941427f6d3722a0875ef7"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcef128f970bb63ecf9a65f7beafd9b55e3aaf0efc271a4154050fc15cdb386e"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b72758f3ffc36ca566ba98a8e7f4f373b6c17c646ff8ad9b21ad10c29186f00d"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c57bc7b946cf2efa67ac55766e41764b66d40cbd9489041e637c1304400494"}, - {file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:946c3a1ef25338e78107fba746f299f926db408d34553b4754e90a7de1d44068"}, - {file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2f256d03957075fcb5923410058982aea85455d035607486ccb847f095442bda"}, - {file = "orjson-3.9.15-cp312-none-win_amd64.whl", hash = "sha256:5bb399e1b49db120653a31463b4a7b27cf2fbfe60469546baf681d1b39f4edf2"}, - {file = "orjson-3.9.15-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b17f0f14a9c0ba55ff6279a922d1932e24b13fc218a3e968ecdbf791b3682b25"}, - {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f6cbd8e6e446fb7e4ed5bac4661a29e43f38aeecbf60c4b900b825a353276a1"}, - {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76bc6356d07c1d9f4b782813094d0caf1703b729d876ab6a676f3aaa9a47e37c"}, - {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fdfa97090e2d6f73dced247a2f2d8004ac6449df6568f30e7fa1a045767c69a6"}, - {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7413070a3e927e4207d00bd65f42d1b780fb0d32d7b1d951f6dc6ade318e1b5a"}, - {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cf1596680ac1f01839dba32d496136bdd5d8ffb858c280fa82bbfeb173bdd40"}, - {file = "orjson-3.9.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:809d653c155e2cc4fd39ad69c08fdff7f4016c355ae4b88905219d3579e31eb7"}, - {file = "orjson-3.9.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:920fa5a0c5175ab14b9c78f6f820b75804fb4984423ee4c4f1e6d748f8b22bc1"}, - {file = "orjson-3.9.15-cp38-none-win32.whl", hash = "sha256:2b5c0f532905e60cf22a511120e3719b85d9c25d0e1c2a8abb20c4dede3b05a5"}, - {file = "orjson-3.9.15-cp38-none-win_amd64.whl", hash = "sha256:67384f588f7f8daf040114337d34a5188346e3fae6c38b6a19a2fe8c663a2f9b"}, - {file = "orjson-3.9.15-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6fc2fe4647927070df3d93f561d7e588a38865ea0040027662e3e541d592811e"}, - {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34cbcd216e7af5270f2ffa63a963346845eb71e174ea530867b7443892d77180"}, - {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f541587f5c558abd93cb0de491ce99a9ef8d1ae29dd6ab4dbb5a13281ae04cbd"}, - {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92255879280ef9c3c0bcb327c5a1b8ed694c290d61a6a532458264f887f052cb"}, - {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:05a1f57fb601c426635fcae9ddbe90dfc1ed42245eb4c75e4960440cac667262"}, - {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ede0bde16cc6e9b96633df1631fbcd66491d1063667f260a4f2386a098393790"}, - {file = "orjson-3.9.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e88b97ef13910e5f87bcbc4dd7979a7de9ba8702b54d3204ac587e83639c0c2b"}, - {file = "orjson-3.9.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57d5d8cf9c27f7ef6bc56a5925c7fbc76b61288ab674eb352c26ac780caa5b10"}, - {file = "orjson-3.9.15-cp39-none-win32.whl", hash = "sha256:001f4eb0ecd8e9ebd295722d0cbedf0748680fb9998d3993abaed2f40587257a"}, - {file = "orjson-3.9.15-cp39-none-win_amd64.whl", hash = "sha256:ea0b183a5fe6b2b45f3b854b0d19c4e932d6f5934ae1f723b07cf9560edd4ec7"}, - {file = "orjson-3.9.15.tar.gz", hash = "sha256:95cae920959d772f30ab36d3b25f83bb0f3be671e986c72ce22f8fa700dae061"}, + {file = "orjson-3.10.0-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:47af5d4b850a2d1328660661f0881b67fdbe712aea905dadd413bdea6f792c33"}, + {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c90681333619d78360d13840c7235fdaf01b2b129cb3a4f1647783b1971542b6"}, + {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:400c5b7c4222cb27b5059adf1fb12302eebcabf1978f33d0824aa5277ca899bd"}, + {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5dcb32e949eae80fb335e63b90e5808b4b0f64e31476b3777707416b41682db5"}, + {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7d507c7493252c0a0264b5cc7e20fa2f8622b8a83b04d819b5ce32c97cf57b"}, + {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e286a51def6626f1e0cc134ba2067dcf14f7f4b9550f6dd4535fd9d79000040b"}, + {file = "orjson-3.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8acd4b82a5f3a3ec8b1dc83452941d22b4711964c34727eb1e65449eead353ca"}, + {file = "orjson-3.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:30707e646080dd3c791f22ce7e4a2fc2438765408547c10510f1f690bd336217"}, + {file = "orjson-3.10.0-cp310-none-win32.whl", hash = "sha256:115498c4ad34188dcb73464e8dc80e490a3e5e88a925907b6fedcf20e545001a"}, + {file = "orjson-3.10.0-cp310-none-win_amd64.whl", hash = "sha256:6735dd4a5a7b6df00a87d1d7a02b84b54d215fb7adac50dd24da5997ffb4798d"}, + {file = "orjson-3.10.0-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9587053e0cefc284e4d1cd113c34468b7d3f17666d22b185ea654f0775316a26"}, + {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bef1050b1bdc9ea6c0d08468e3e61c9386723633b397e50b82fda37b3563d72"}, + {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d16c6963ddf3b28c0d461641517cd312ad6b3cf303d8b87d5ef3fa59d6844337"}, + {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4251964db47ef090c462a2d909f16c7c7d5fe68e341dabce6702879ec26d1134"}, + {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73bbbdc43d520204d9ef0817ac03fa49c103c7f9ea94f410d2950755be2c349c"}, + {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:414e5293b82373606acf0d66313aecb52d9c8c2404b1900683eb32c3d042dbd7"}, + {file = "orjson-3.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:feaed5bb09877dc27ed0d37f037ddef6cb76d19aa34b108db270d27d3d2ef747"}, + {file = "orjson-3.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5127478260db640323cea131ee88541cb1a9fbce051f0b22fa2f0892f44da302"}, + {file = "orjson-3.10.0-cp311-none-win32.whl", hash = "sha256:b98345529bafe3c06c09996b303fc0a21961820d634409b8639bc16bd4f21b63"}, + {file = "orjson-3.10.0-cp311-none-win_amd64.whl", hash = "sha256:658ca5cee3379dd3d37dbacd43d42c1b4feee99a29d847ef27a1cb18abdfb23f"}, + {file = "orjson-3.10.0-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4329c1d24fd130ee377e32a72dc54a3c251e6706fccd9a2ecb91b3606fddd998"}, + {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef0f19fdfb6553342b1882f438afd53c7cb7aea57894c4490c43e4431739c700"}, + {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c4f60db24161534764277f798ef53b9d3063092f6d23f8f962b4a97edfa997a0"}, + {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1de3fd5c7b208d836f8ecb4526995f0d5877153a4f6f12f3e9bf11e49357de98"}, + {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f93e33f67729d460a177ba285002035d3f11425ed3cebac5f6ded4ef36b28344"}, + {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:237ba922aef472761acd697eef77fef4831ab769a42e83c04ac91e9f9e08fa0e"}, + {file = "orjson-3.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98c1bfc6a9bec52bc8f0ab9b86cc0874b0299fccef3562b793c1576cf3abb570"}, + {file = "orjson-3.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:30d795a24be16c03dca0c35ca8f9c8eaaa51e3342f2c162d327bd0225118794a"}, + {file = "orjson-3.10.0-cp312-none-win32.whl", hash = "sha256:6a3f53dc650bc860eb26ec293dfb489b2f6ae1cbfc409a127b01229980e372f7"}, + {file = "orjson-3.10.0-cp312-none-win_amd64.whl", hash = "sha256:983db1f87c371dc6ffc52931eb75f9fe17dc621273e43ce67bee407d3e5476e9"}, + {file = "orjson-3.10.0-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a667769a96a72ca67237224a36faf57db0c82ab07d09c3aafc6f956196cfa1b"}, + {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade1e21dfde1d37feee8cf6464c20a2f41fa46c8bcd5251e761903e46102dc6b"}, + {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:23c12bb4ced1c3308eff7ba5c63ef8f0edb3e4c43c026440247dd6c1c61cea4b"}, + {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2d014cf8d4dc9f03fc9f870de191a49a03b1bcda51f2a957943fb9fafe55aac"}, + {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eadecaa16d9783affca33597781328e4981b048615c2ddc31c47a51b833d6319"}, + {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd583341218826f48bd7c6ebf3310b4126216920853cbc471e8dbeaf07b0b80e"}, + {file = "orjson-3.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:90bfc137c75c31d32308fd61951d424424426ddc39a40e367704661a9ee97095"}, + {file = "orjson-3.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:13b5d3c795b09a466ec9fcf0bd3ad7b85467d91a60113885df7b8d639a9d374b"}, + {file = "orjson-3.10.0-cp38-none-win32.whl", hash = "sha256:5d42768db6f2ce0162544845facb7c081e9364a5eb6d2ef06cd17f6050b048d8"}, + {file = "orjson-3.10.0-cp38-none-win_amd64.whl", hash = "sha256:33e6655a2542195d6fd9f850b428926559dee382f7a862dae92ca97fea03a5ad"}, + {file = "orjson-3.10.0-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4050920e831a49d8782a1720d3ca2f1c49b150953667eed6e5d63a62e80f46a2"}, + {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1897aa25a944cec774ce4a0e1c8e98fb50523e97366c637b7d0cddabc42e6643"}, + {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9bf565a69e0082ea348c5657401acec3cbbb31564d89afebaee884614fba36b4"}, + {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6ebc17cfbbf741f5c1a888d1854354536f63d84bee537c9a7c0335791bb9009"}, + {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2817877d0b69f78f146ab305c5975d0618df41acf8811249ee64231f5953fee"}, + {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57d017863ec8aa4589be30a328dacd13c2dc49de1c170bc8d8c8a98ece0f2925"}, + {file = "orjson-3.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:22c2f7e377ac757bd3476ecb7480c8ed79d98ef89648f0176deb1da5cd014eb7"}, + {file = "orjson-3.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e62ba42bfe64c60c1bc84799944f80704e996592c6b9e14789c8e2a303279912"}, + {file = "orjson-3.10.0-cp39-none-win32.whl", hash = "sha256:60c0b1bdbccd959ebd1575bd0147bd5e10fc76f26216188be4a36b691c937077"}, + {file = "orjson-3.10.0-cp39-none-win_amd64.whl", hash = "sha256:175a41500ebb2fdf320bf78e8b9a75a1279525b62ba400b2b2444e274c2c8bee"}, + {file = "orjson-3.10.0.tar.gz", hash = "sha256:ba4d8cac5f2e2cff36bea6b6481cdb92b38c202bcec603d6f5ff91960595a1ed"}, ] [[package]] @@ -1537,15 +1550,125 @@ requests = ">=2.21.0" [[package]] name = "pycparser" -version = "2.21" +version = "2.22" description = "C parser in Python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.8" files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] +[[package]] +name = "pydantic" +version = "2.7.1" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic-2.7.1-py3-none-any.whl", hash = "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5"}, + {file = "pydantic-2.7.1.tar.gz", hash = "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.18.2" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.18.2" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.18.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9e08e867b306f525802df7cd16c44ff5ebbe747ff0ca6cf3fde7f36c05a59a81"}, + {file = "pydantic_core-2.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f0a21cbaa69900cbe1a2e7cad2aa74ac3cf21b10c3efb0fa0b80305274c0e8a2"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0680b1f1f11fda801397de52c36ce38ef1c1dc841a0927a94f226dea29c3ae3d"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95b9d5e72481d3780ba3442eac863eae92ae43a5f3adb5b4d0a1de89d42bb250"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fcf5cd9c4b655ad666ca332b9a081112cd7a58a8b5a6ca7a3104bc950f2038"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b5155ff768083cb1d62f3e143b49a8a3432e6789a3abee8acd005c3c7af1c74"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553ef617b6836fc7e4df130bb851e32fe357ce36336d897fd6646d6058d980af"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89ed9eb7d616ef5714e5590e6cf7f23b02d0d539767d33561e3675d6f9e3857"}, + {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:75f7e9488238e920ab6204399ded280dc4c307d034f3924cd7f90a38b1829563"}, + {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ef26c9e94a8c04a1b2924149a9cb081836913818e55681722d7f29af88fe7b38"}, + {file = "pydantic_core-2.18.2-cp310-none-win32.whl", hash = "sha256:182245ff6b0039e82b6bb585ed55a64d7c81c560715d1bad0cbad6dfa07b4027"}, + {file = "pydantic_core-2.18.2-cp310-none-win_amd64.whl", hash = "sha256:e23ec367a948b6d812301afc1b13f8094ab7b2c280af66ef450efc357d2ae543"}, + {file = "pydantic_core-2.18.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:219da3f096d50a157f33645a1cf31c0ad1fe829a92181dd1311022f986e5fbe3"}, + {file = "pydantic_core-2.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cc1cfd88a64e012b74e94cd00bbe0f9c6df57049c97f02bb07d39e9c852e19a4"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b7133a6e6aeb8df37d6f413f7705a37ab4031597f64ab56384c94d98fa0e90"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:224c421235f6102e8737032483f43c1a8cfb1d2f45740c44166219599358c2cd"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b14d82cdb934e99dda6d9d60dc84a24379820176cc4a0d123f88df319ae9c150"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2728b01246a3bba6de144f9e3115b532ee44bd6cf39795194fb75491824a1413"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:470b94480bb5ee929f5acba6995251ada5e059a5ef3e0dfc63cca287283ebfa6"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:997abc4df705d1295a42f95b4eec4950a37ad8ae46d913caeee117b6b198811c"}, + {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75250dbc5290e3f1a0f4618db35e51a165186f9034eff158f3d490b3fed9f8a0"}, + {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4456f2dca97c425231d7315737d45239b2b51a50dc2b6f0c2bb181fce6207664"}, + {file = "pydantic_core-2.18.2-cp311-none-win32.whl", hash = "sha256:269322dcc3d8bdb69f054681edff86276b2ff972447863cf34c8b860f5188e2e"}, + {file = "pydantic_core-2.18.2-cp311-none-win_amd64.whl", hash = "sha256:800d60565aec896f25bc3cfa56d2277d52d5182af08162f7954f938c06dc4ee3"}, + {file = "pydantic_core-2.18.2-cp311-none-win_arm64.whl", hash = "sha256:1404c69d6a676245199767ba4f633cce5f4ad4181f9d0ccb0577e1f66cf4c46d"}, + {file = "pydantic_core-2.18.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242"}, + {file = "pydantic_core-2.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c"}, + {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241"}, + {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3"}, + {file = "pydantic_core-2.18.2-cp312-none-win32.whl", hash = "sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038"}, + {file = "pydantic_core-2.18.2-cp312-none-win_amd64.whl", hash = "sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438"}, + {file = "pydantic_core-2.18.2-cp312-none-win_arm64.whl", hash = "sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec"}, + {file = "pydantic_core-2.18.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9fdad8e35f278b2c3eb77cbdc5c0a49dada440657bf738d6905ce106dc1de439"}, + {file = "pydantic_core-2.18.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1d90c3265ae107f91a4f279f4d6f6f1d4907ac76c6868b27dc7fb33688cfb347"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390193c770399861d8df9670fb0d1874f330c79caaca4642332df7c682bf6b91"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82d5d4d78e4448683cb467897fe24e2b74bb7b973a541ea1dcfec1d3cbce39fb"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4774f3184d2ef3e14e8693194f661dea5a4d6ca4e3dc8e39786d33a94865cefd"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4d938ec0adf5167cb335acb25a4ee69a8107e4984f8fbd2e897021d9e4ca21b"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0e8b1be28239fc64a88a8189d1df7fad8be8c1ae47fcc33e43d4be15f99cc70"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868649da93e5a3d5eacc2b5b3b9235c98ccdbfd443832f31e075f54419e1b96b"}, + {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:78363590ef93d5d226ba21a90a03ea89a20738ee5b7da83d771d283fd8a56761"}, + {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:852e966fbd035a6468fc0a3496589b45e2208ec7ca95c26470a54daed82a0788"}, + {file = "pydantic_core-2.18.2-cp38-none-win32.whl", hash = "sha256:6a46e22a707e7ad4484ac9ee9f290f9d501df45954184e23fc29408dfad61350"}, + {file = "pydantic_core-2.18.2-cp38-none-win_amd64.whl", hash = "sha256:d91cb5ea8b11607cc757675051f61b3d93f15eca3cefb3e6c704a5d6e8440f4e"}, + {file = "pydantic_core-2.18.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ae0a8a797a5e56c053610fa7be147993fe50960fa43609ff2a9552b0e07013e8"}, + {file = "pydantic_core-2.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:042473b6280246b1dbf530559246f6842b56119c2926d1e52b631bdc46075f2a"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a388a77e629b9ec814c1b1e6b3b595fe521d2cdc625fcca26fbc2d44c816804"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25add29b8f3b233ae90ccef2d902d0ae0432eb0d45370fe315d1a5cf231004b"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f459a5ce8434614dfd39bbebf1041952ae01da6bed9855008cb33b875cb024c0"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eff2de745698eb46eeb51193a9f41d67d834d50e424aef27df2fcdee1b153845"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8309f67285bdfe65c372ea3722b7a5642680f3dba538566340a9d36e920b5f0"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f93a8a2e3938ff656a7c1bc57193b1319960ac015b6e87d76c76bf14fe0244b4"}, + {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:22057013c8c1e272eb8d0eebc796701167d8377441ec894a8fed1af64a0bf399"}, + {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfeecd1ac6cc1fb2692c3d5110781c965aabd4ec5d32799773ca7b1456ac636b"}, + {file = "pydantic_core-2.18.2-cp39-none-win32.whl", hash = "sha256:0d69b4c2f6bb3e130dba60d34c0845ba31b69babdd3f78f7c0c8fae5021a253e"}, + {file = "pydantic_core-2.18.2-cp39-none-win_amd64.whl", hash = "sha256:d9319e499827271b09b4e411905b24a426b8fb69464dfa1696258f53a3334641"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374"}, + {file = "pydantic_core-2.18.2.tar.gz", hash = "sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + [[package]] name = "pygments" version = "2.17.2" @@ -1587,17 +1710,17 @@ testutils = ["gitpython (>3)"] [[package]] name = "pymdown-extensions" -version = "10.7.1" +version = "10.8.1" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.8" files = [ - {file = "pymdown_extensions-10.7.1-py3-none-any.whl", hash = "sha256:f5cc7000d7ff0d1ce9395d216017fa4df3dde800afb1fb72d1c7d3fd35e710f4"}, - {file = "pymdown_extensions-10.7.1.tar.gz", hash = "sha256:c70e146bdd83c744ffc766b4671999796aba18842b268510a329f7f64700d584"}, + {file = "pymdown_extensions-10.8.1-py3-none-any.whl", hash = "sha256:f938326115884f48c6059c67377c46cf631c733ef3629b6eed1349989d1b30cb"}, + {file = "pymdown_extensions-10.8.1.tar.gz", hash = "sha256:3ab1db5c9e21728dabf75192d71471f8e50f216627e9a1fa9535ecb0231b9940"}, ] [package.dependencies] -markdown = ">=3.5" +markdown = ">=3.6" pyyaml = "*" [package.extras] @@ -1704,101 +1827,101 @@ pyyaml = "*" [[package]] name = "rapidfuzz" -version = "3.6.2" +version = "3.7.0" description = "rapid fuzzy string matching" optional = false python-versions = ">=3.8" files = [ - {file = "rapidfuzz-3.6.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a5637e6bf11b15b5aff6ee818c76bdec99ad208511b78985e6209ba648a6e3ee"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:380586664f2f63807050ddb95e7702888b4f0b425abf17655940c411f39287ad"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3168ff565d4b8c239cf11fb604dd2507d30e9bcaac76a4077c0ac23cf2c866ed"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be69f7fd46b5c6467fe5e2fd4cff3816b0c03048eed8a4becb9a73e6000960e7"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cbd5894f23fdf5697499cf759523639838ac822bd1600e343fdce7313baa02ae"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85a5b6e026393fe39fb61146b9c17c5af66fffbe1410e992c4bb06d9ec327bd3"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab269adfc64480f209e99f253391a10735edd5c09046e04899adab5fb132f20e"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35aeac852bca06023d6bbd50c1fc504ca5a9a3613d5e75a140f0be7601fa34ef"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e706f302c6a3ae0d74edd0d6ace46aee1ae07c563b436ccf5ff04db2b3571e60"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bec353f022011e6e5cd28ccb8700fbd2a33918197af0d4e0abb3c3f4845cc864"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ef3925daaa93eed20401012e219f569ff0c039ed5bf4ce2d3737b4f75d441622"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6ee98d88ae9ccc77ff61992ed33b2496478def5dc0da55c9a9aa06fcb725a352"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:423c7c588b09d618601097b7a0017dfcb91132a2076bef29023c5f3cd2dc3de1"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-win32.whl", hash = "sha256:c17c5efee347a40a6f4c1eec59e3d7d1e22f7613a97f8b8a07733ef723483a04"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-win_amd64.whl", hash = "sha256:4209816626d8d6ff8ae7dc248061c6059e618b70c6e6f6e4d7444ae3740b2b85"}, - {file = "rapidfuzz-3.6.2-cp310-cp310-win_arm64.whl", hash = "sha256:1c54d3c85e522d3ac9ee39415f183c8fa184c4f87e7e5a37938f15a6d50e853a"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e06f6d270112f5db001f1cba5a97e1a48aee3d3dbdcbea3ec027c230462dbf9b"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:080cb71b50cb6aff11d1c6aeb157f273e2da0b2bdb3f9d7b01257e49e69a8576"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7895e04a22d6515bc91a850e0831f2405547605aa311d1ffec51e4818abc3c1"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd82f9838519136b7083dd1e3149ee80344521f3dc37f744f227505ff0883efb"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a945567c2b0b6e069454c9782d5234b0b6795718adf7a9f868bd3144afa6a023"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:673ba2c343644805acdae1cb949c6a4de71aa2f62a998978551ebea59603af3f"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d457c89bac1471442002e70551e8268e639b3870b4a4521eae363c07253be87"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:495c0d8e14e6f12520eb7fc71b9ba9fcaafb47fc23a654e6e89b6c7985ec0020"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6d67b649bf3e1b1722d04eca44d37919aef88305ce7ad05564502d013cf550fd"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e48dde8ca83d11daa00900cf6a5d281a1297aef9b7bfa73801af6e8822be5019"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:824cc381cf81cbf8d158f6935664ec2a69e6ac3b1d39fa201988bf81a257f775"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:1dfe4c24957474ce0ac75d886387e30e292b4be39228a6d71f76de414dc187db"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d57b98013b802621bbc8b12a46bfc9d36ac552ab51ca207f7ce167ad46adabeb"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-win32.whl", hash = "sha256:9a07dffac439223b4f1025dbfc68f4445a3460a859309c9858c2a3fa29617cdc"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-win_amd64.whl", hash = "sha256:95a49c6b8bf1229743ae585dd5b7d57f0d15a7eb6e826866d5c9965ba958503c"}, - {file = "rapidfuzz-3.6.2-cp311-cp311-win_arm64.whl", hash = "sha256:af7c19ec86e11488539380d3db1755be5d561a3c0e7b04ff9d07abd7f9a8e9d8"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:de8adc12161bf282c60f12dc9233bb31632f71d446a010fe7469a69b8153427f"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:337e357f693130c4c6be740652542b260e36f622c59e01fa33d58f1d2750c930"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6468f8bc8c3c50604f43631550ef9cfec873515dba5023ca34d461be94669fc8"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74c6773b11445b5e5cf93ca383171cd0ac0cdeafea11a7b2a5688f8bf8d813e6"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1507fc5769aa109dda4de3a15f822a0f6a03e18d627bd0ba3ddbb253cf70e07"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:617949a70150e6fffdaed19253dd49f7a53528411dc8bf7663d499ba21e0f61e"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8b77779174b1b40aa70827692571ab457061897846255ad7d5d559e2edb1932"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80e51b22a7da83f9c87a97e92df07ed0612c74c35496590255f4b5d5b4212dfe"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3ae7c86914cb6673e97e187ba431b9c4cf4177d9ae77f8a1e5b2ba9a5628839e"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ddc380ffaa90f204cc9ddcb779114b9ab6f015246d549de9d47871a97ef9f18a"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:3c1dc078ef371fce09f9f3eec2ca4eaa2a8cd412ec53941015b4f39f14d34407"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:9a74102fc5a2534fe91f7507838623e1f3a149d8e05648389c42bb42e14b1c3f"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:48e1eaea8fcd522fca7f04f0480663f0f0cfb77957092cce60a93f4462864996"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-win32.whl", hash = "sha256:66b008bf2972740cd2dda5d382eb8bdb87265cd88198e71c7797bdc0d1f79d20"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-win_amd64.whl", hash = "sha256:87ac3a87f2251ae2e95fc9478ca5c759de6d141d04c84d3fec9f9cdcfc167b33"}, - {file = "rapidfuzz-3.6.2-cp312-cp312-win_arm64.whl", hash = "sha256:b593cc51aed887e93b78c2f94dfae9008be2b23d17afd3b1f1d3eb3913b58f26"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7d830bc7a9b586a374147ec60b08b1f9ae5996b43f75cc514f37faef3866b519"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:dbee7f5ff11872b76505cbd87c814abc823e8757f11c69062eb3b25130a283da"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28c011fb31f2c3f82f503aedd6097d3d3854e574e327a119a3b7eb2cf90b79ca"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cda81d0e0ce0c13abfa46b24e10c1e85f9c6acb628f0a9a948f5779f9c2076a2"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c279928651ce0e9e5220dcb25a00cc53b65e592a0861336a38299bcdca3a596"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:35bd4bc9c40e6994c5d6edea4b9319388b4d9711c13c66d543bb4c37624b4184"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d07899506a5a8760448d9df036d528b55a554bf571714173635c79eef4a86e58"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb2e51d01b9c6d6954a3e055c57a80d4685b4fc82719db5519fc153566bcd6bb"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:153d065e353371cc0aeff32b99999a5758266a64e958d1364189367c1c9f6814"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4edcceebb85ebfa49a3ddcde20ad891d36c08dc0fd592efdab0e7d313a4e36af"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3549123fca5bb817341025f98e8e49ca99f84596c7c4f92b658f8e5836040d4a"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:84c1032ae42628465b7a5cc35249906061e18a8193c9c27cbd2db54e9823a9a6"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9bcc91ebd8fc69a6bd3b5711c8250f5f4e70606b4da75ef415f57ad209978205"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-win32.whl", hash = "sha256:f3a70f341c4c111bad910d2df69c78577a98af140319a996af24c9385939335d"}, - {file = "rapidfuzz-3.6.2-cp38-cp38-win_amd64.whl", hash = "sha256:354ad5fe655beb7b279390cb58334903931c5452ecbad1b1666ffb06786498e2"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1b86b93d93020c2b3edc1665d75c8855784845fc0a739b312c26c3a4bf0c80d5"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:28243086ed0e50808bb56632e5442c457241646aeafafd501ac87901f40a3237"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ed52461ae5a9ea4c400d38e2649c74a413f1a6d8fb8308b66f1fbd122514732f"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a46220f86a5f9cb016af31525e0d0865cad437d02239aa0d8aed2ab8bff1f1c"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81a630ed2fc3ec5fc7400eb66bab1f87e282b4d47f0abe3e48c6634dfa13b5e4"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8e5a437b9089df6242a718d9c31ab1742989e9400a0977af012ef483b63b4c2"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16270b5529de83b7bae7457e952e4d9cf3fbf029a837dd32d415bb9e0eb8e599"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5378c04102c7f084cde30a100154fa6d7e2baf0d51a6bdd2f912545559c1fb35"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7f18397c8d6a65fc0b288d2fc29bc7baeea6ba91eeb95163a3cd98f23cd3bc85"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2acd2514defce81e6ff4bbff50252d5e7df8e85a731442c4b83e44c86cf1c916"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:1df2faf80201952e252413b6fac6f3e146080dcebb87bb1bb722508e67558ed8"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6440ed0b3007c1c9286b0b88fe2ab2d9e83edd60cd62293b3dfabb732b4e8a30"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4fcfa23b5553b27f4016df77c53172ea743454cf12c28cfa7c35a309a2be93b3"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-win32.whl", hash = "sha256:2d580d937146e803c8e5e1b87916cab8d6f84013b6392713e201efcda335c7d8"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:fe2a68be734e8e88af23385c68d6467e15818b6b1df1cbfebf7bff577226c957"}, - {file = "rapidfuzz-3.6.2-cp39-cp39-win_arm64.whl", hash = "sha256:6478f7803efebf5f644d0b758439c5b25728550fdfbb19783d150004c46a75a9"}, - {file = "rapidfuzz-3.6.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:36ce7b68a7b90b787cdd73480a68d2f1ca63c31a3a9d5a79a8736f978e1e9344"}, - {file = "rapidfuzz-3.6.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53597fd72a9340bcdd80d3620f4957c2b92f9b569313b969a3abdaffd193aae6"}, - {file = "rapidfuzz-3.6.2-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4f6de745fe6ce46a422d353ee10599013631d7d714a36d025f164b2d4e8c000"}, - {file = "rapidfuzz-3.6.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62df2136068e2515ed8beb01756381ff62c29384d785e3bf46e3111d4ea3ba1e"}, - {file = "rapidfuzz-3.6.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7382c90170f60c846c81a07ddd80bb2e8c43c8383754486fa37f67391a571897"}, - {file = "rapidfuzz-3.6.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f31314fd2e2f3dc3e519e6f93669462ce7953df2def1c344aa8f5345976d0eb2"}, - {file = "rapidfuzz-3.6.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:012221629d54d3bee954148247f711eb86d4d390b589ebfe03172ea0b37a7531"}, - {file = "rapidfuzz-3.6.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d41dd59a70decfce6595315367a2fea2af660d92a9d144acc6479030501014d7"}, - {file = "rapidfuzz-3.6.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f9fa14136a5b0cba1ec42531f7c3e0b0d3edb7fd6bc5e5ae7b498541f3855ab"}, - {file = "rapidfuzz-3.6.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:259364199cbfeca33b1af369fc7951f71717aa285184a3fa5a7b1772da1b89db"}, - {file = "rapidfuzz-3.6.2.tar.gz", hash = "sha256:cf911e792ab0c431694c9bf2648afabfd92099103f2e31492893e078ddca5e1a"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:860f438238f1807532aa5c5c25e74c284232ccc115fe84697b78e25d48f364f7"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bb9285abeb0477cdb2f8ea0cf7fd4b5f72ed5a9a7d3f0c0bb4a5239db2fc1ed"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:08671280e0c04d2bb3f39511f13cae5914e6690036fd1eefc3d47a47f9fae634"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04bae4d9c16ce1bab6447d196fb8258d98139ed8f9b288a38b84887985e4227b"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1efa2268b51b68156fb84d18ca1720311698a58051c4a19c40d670057ce60519"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:600b4d4315f33ec0356c0dab3991a5d5761102420bcff29e0773706aa48936e8"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18bc2f13c73d5d34499ff6ada55b052c445d3aa64d22c2639e5ab45472568046"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e11c5e6593be41a555475c9c20320342c1f5585d635a064924956944c465ad4"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d7878025248b99ccca3285891899373f98548f2ca13835d83619ffc42241c626"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b4a7e37fe136022d944374fcd8a2f72b8a19f7b648d2cdfb946667e9ede97f9f"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b5881856f830351aaabd869151124f64a80bf61560546d9588a630a4e933a5de"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:c788b11565cc176fab8fab6dfcd469031e906927db94bf7e422afd8ef8f88a5a"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9e17a3092e74025d896ef1d67ac236c83494da37a78ef84c712e4e2273c115f1"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-win32.whl", hash = "sha256:e499c823206c9ffd9d89aa11f813a4babdb9219417d4efe4c8a6f8272da00e98"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:91f798cc00cd94a0def43e9befc6e867c9bd8fa8f882d1eaa40042f528b7e2c7"}, + {file = "rapidfuzz-3.7.0-cp310-cp310-win_arm64.whl", hash = "sha256:d5a3872f35bec89f07b993fa1c5401d11b9e68bcdc1b9737494e279308a38a5f"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ef6b6ab64c4c91c57a6b58e1d690b59453bfa1f1e9757a7e52e59b4079e36631"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f9070b42c0ba030b045bba16a35bdb498a0d6acb0bdb3ff4e325960e685e290"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:63044c63565f50818d885bfcd40ac369947da4197de56b4d6c26408989d48edf"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49b0c47860c733a3d73a4b70b97b35c8cbf24ef24f8743732f0d1c412a8c85de"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1b14489b038f007f425a06fcf28ac6313c02cb603b54e3a28d9cfae82198cc0"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be08f39e397a618aab907887465d7fabc2d1a4d15d1a67cb8b526a7fb5202a3e"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16895dc62a7b92028f9c8b6d22830f1cbc77306ee794f461afc6028e1a8d7539"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:579cce49dfa57ffd8c8227b3fb53cced54b4df70cec502e63e9799b4d1f44004"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:40998c8dc35fdd221790b8b5134a8d7499adbfab9a5dd9ec626c7e92e17a43ed"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:dc3fdb4738a6b83ae27f1d8923b00d3a9c2b5c50da75b9f8b81841839c6e3e1f"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:92b8146fbfb37ac358ef7e0f6b79619e4f793fbbe894b99ea87920f9c0a9d77d"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:1dfceaa7c2914585bb8a043265c39ec09078f13fbf53b5525722fc074306b6fa"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f332d61f51b0b9c8b55a0fb052b4764b6ad599ea8ce948ac47a4388e9083c35e"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-win32.whl", hash = "sha256:dfd1e4819f1f3c47141f86159b44b7360ecb19bf675080b3b40437bf97273ab9"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:594b9c33fc1a86784962043ee3fbaaed875fbaadff72e467c2f7a83cd6c5d69d"}, + {file = "rapidfuzz-3.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:0b13a6823a1b83ae43f8bf35955df35032bee7bec0daf9b5ab836e0286067434"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:075a419a0ec29be44b3d7f4bcfa5cb7e91e419379a85fc05eb33de68315bd96f"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:51a5b96d2081c3afbef1842a61d63e55d0a5a201473e6975a80190ff2d6f22ca"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9460d8fddac7ea46dff9298eee9aa950dbfe79f2eb509a9f18fbaefcd10894c"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f39eb1513ee139ba6b5c01fe47ddf2d87e9560dd7fdee1068f7f6efbae70de34"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eace9fdde58a425d4c9a93021b24a0cac830df167a5b2fc73299e2acf9f41493"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cc77237242303733de47829028a0a8b6ab9188b23ec9d9ff0a674fdcd3c8e7f"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:74e692357dd324dff691d379ef2c094c9ec526c0ce83ed43a066e4e68fe70bf6"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f2075ac9ee5c15d33d24a1efc8368d095602b5fd9634c5b5f24d83e41903528"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5a8ba64d72329a940ff6c74b721268c2004eecc48558f648a38e96915b5d1c1b"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a1f268a2a37cd22573b4a06eccd481c04504b246d3cadc2d8e8dfa64b575636d"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:42c2e8a2341363c7caf276efdbe1a673fc5267a02568c47c8e980f12e9bc8727"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:a9acca34b34fb895ee6a84c436bb919f3b9cd8f43e7003d43e9573a1d990ff74"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9bad6a0fe3bc1753dacaa6229a8ba7d9844eb7ae24d44d17c5f4c51c91a8a95e"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-win32.whl", hash = "sha256:c86bc4b1d2380739e6485396195e30021df509b4923f3f757914e171587bce7c"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:d7361608c8e73a1dc0203a87d151cddebdade0098a047c46da43c469c07df964"}, + {file = "rapidfuzz-3.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:8fdc26e7863e0f63c2185d53bb61f5173ad4451c1c8287b535b30ea25a419a5a"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9b6167468f76779a14b9af66210f68741af94d32d086f19118de4e919f00585c"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5bd394e28ff221557ea4d8152fcec3e66d9f620557feca5f2bedc4c21f8cf2f9"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8e70f876ca89a6df344f8157ac60384e8c05a0dfb442da2490c3f1c45238ccf5"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c837f89d86a5affe9ee6574dad6b195475676a6ab171a67920fc99966f2ab2c"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cda4550a98658f9a8bcdc03d0498ed1565c1563880e3564603a9eaae28d51b2a"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecd70212fd9f1f8b1d3bdd8bcb05acc143defebd41148bdab43e573b043bb241"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:187db4cc8fb54f8c49c67b7f38ef3a122ce23be273032fa2ff34112a2694c3d8"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4604dfc1098920c4eb6d0c6b5cc7bdd4bf95b48633e790c1d3f100a25870691d"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01581b688c5f4f6665b779135e32db0edab1d78028abf914bb91469928efa383"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0828b55ec8ad084febdf4ab0c942eb1f81c97c0935f1cb0be0b4ea84ce755988"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:150c98b65faff17b917b9d36bff8a4d37b6173579c6bc2e38ff2044e209d37a4"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7e4eea225d2bff1aff4c85fcc44716596d3699374d99eb5906b7a7560297460e"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7bc944d7e830cfce0f8b4813875f05904207017b66e25ab7ee757507001310a9"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-win32.whl", hash = "sha256:3e55f02105c451ab6ff0edaaba57cab1b6c0a0241cfb2b306d4e8e1503adba50"}, + {file = "rapidfuzz-3.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:41851620d2900791d66d9b6092fc163441d7dd91a460c73b07957ff1c517bc30"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e8041c6b2d339766efe6298fa272f79d6dd799965df364ef4e50f488c101c899"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4e09d81008e212fc824ea23603ff5270d75886e72372fa6c7c41c1880bcb57ed"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:419c8961e861fb5fc5590056c66a279623d1ea27809baea17e00cdc313f1217a"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1522eaab91b9400b3ef16eebe445940a19e70035b5bc5d98aef23d66e9ac1df0"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:611278ce3136f4544d596af18ab8849827d64372e1d8888d9a8d071bf4a3f44d"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4efa9bfc5b955b6474ee077eee154e240441842fa304f280b06e6b6aa58a1d1e"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0cc9d3c8261457af3f8756b1f71a9fdc4892978a9e8b967976d2803e08bf972"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce728e2b582fd396bc2559160ee2e391e6a4b5d2e455624044699d96abe8a396"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a6a36c9299e059e0bee3409218bc5235a46570c20fc980cdee5ed21ea6110ad"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9ea720db8def684c1eb71dadad1f61c9b52f4d979263eb5d443f2b22b0d5430a"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:358692f1df3f8aebcd48e69c77c948c9283b44c0efbaf1eeea01739efe3cd9a6"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:faded69ffe79adcefa8da08f414a0fd52375e2b47f57be79471691dad9656b5a"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7f9f3dc14fadbd553975f824ac48c381f42192cec9d7e5711b528357662a8d8e"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-win32.whl", hash = "sha256:7be5f460ff42d7d27729115bfe8a02e83fa0284536d8630ee900d17b75c29e65"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:dd5ad2c12dab2b98340c4b7b9592c8f349730bda9a2e49675ea592bbcbc1360b"}, + {file = "rapidfuzz-3.7.0-cp39-cp39-win_arm64.whl", hash = "sha256:aa163257a0ac4e70f9009d25e5030bdd83a8541dfa3ba78dc86b35c9e16a80b4"}, + {file = "rapidfuzz-3.7.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4e50840a8a8e0229563eeaf22e21a203359859557db8829f4d0285c17126c5fb"}, + {file = "rapidfuzz-3.7.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:632f09e19365ace5ff2670008adc8bf23d03d668b03a30230e5b60ff9317ee93"}, + {file = "rapidfuzz-3.7.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:209dda6ae66b702f74a78cef555397cdc2a83d7f48771774a20d2fc30808b28c"}, + {file = "rapidfuzz-3.7.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bc0b78572626af6ab134895e4dbfe4f4d615d18dcc43b8d902d8e45471aabba"}, + {file = "rapidfuzz-3.7.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7ba14850cc8258b3764ea16b8a4409ac2ba16d229bde7a5f495dd479cd9ccd56"}, + {file = "rapidfuzz-3.7.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b917764fd2b267addc9d03a96d26f751f6117a95f617428c44a069057653b528"}, + {file = "rapidfuzz-3.7.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1252ca156e1b053e84e5ae1c8e9e062ee80468faf23aa5c543708212a42795fd"}, + {file = "rapidfuzz-3.7.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86c7676a32d7524e40bc73546e511a408bc831ae5b163029d325ea3a2027d089"}, + {file = "rapidfuzz-3.7.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20e7d729af2e5abb29caa070ec048aba042f134091923d9ca2ac662b5604577e"}, + {file = "rapidfuzz-3.7.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86eea3e6c314a9238de568254a9c591ec73c2985f125675ed5f171d869c47773"}, + {file = "rapidfuzz-3.7.0.tar.gz", hash = "sha256:620df112c39c6d27316dc1e22046dc0382d6d91fd60d7c51bd41ca0333d867e9"}, ] [package.extras] @@ -1820,13 +1943,13 @@ dev = ["black (==22.1.0)", "flake8 (==4.0.1)", "isort (==5.10.1)"] [[package]] name = "red-discordbot" -version = "3.5.7" +version = "3.5.9" description = "A highly customisable Discord bot" optional = false python-versions = "<3.12,>=3.8.1" files = [ - {file = "Red-DiscordBot-3.5.7.tar.gz", hash = "sha256:7673ea794016b6d3d7b96eb07a46cd92c52974e15b3a6ad95608df69dc320838"}, - {file = "Red_DiscordBot-3.5.7-py3-none-any.whl", hash = "sha256:3b9df02cd8efd35170c9505e3f0a8c9b1bd415bcc2ca451a19733d28b1b3a5b4"}, + {file = "Red_DiscordBot-3.5.9-py3-none-any.whl", hash = "sha256:d392c4947f95151435792e99cc74afb7c440b11fb516fa59927f5e462c61385f"}, + {file = "red_discordbot-3.5.9.tar.gz", hash = "sha256:1f50e508b6923868ea4d7bb0eb80a2b1dbdeae248cf0a57717539ca6f5c5874f"}, ] [package.dependencies] @@ -1848,14 +1971,14 @@ markdown = "3.6" markdown-it-py = "3.0.0" mdurl = "0.1.2" multidict = "6.0.5" -orjson = "3.9.15" +orjson = "3.10.0" packaging = "24.0" platformdirs = "4.2.0" psutil = "5.9.8" pygments = "2.17.2" python-dateutil = "2.9.0.post0" pyyaml = "6.0.1" -rapidfuzz = "3.6.2" +rapidfuzz = "3.7.0" red-commons = "1.0.0" red-lavalink = "0.11.0" rich = "13.7.1" @@ -1867,11 +1990,11 @@ yarl = "1.9.4" [package.extras] all = ["async-timeout (==4.0.3)", "asyncpg (==0.29.0)"] -dev = ["alabaster (==0.7.13)", "astroid (==3.1.0)", "async-timeout (==4.0.3)", "asyncpg (==0.29.0)", "black (==23.12.1)", "certifi (==2024.2.2)", "charset-normalizer (==3.3.2)", "dill (==0.3.8)", "docutils (==0.20.1)", "exceptiongroup (==1.2.0)", "imagesize (==1.4.1)", "importlib-metadata (==7.1.0)", "iniconfig (==2.0.0)", "isort (==5.13.2)", "jinja2 (==3.1.3)", "markupsafe (==2.1.5)", "mccabe (==0.7.0)", "mypy-extensions (==1.0.0)", "pathspec (==0.12.1)", "pluggy (==1.4.0)", "pylint (==3.1.0)", "pytest (==7.4.4)", "pytest-asyncio (==0.21.1)", "pytest-mock (==3.12.0)", "pytz (==2024.1)", "requests (==2.31.0)", "snowballstemmer (==2.2.0)", "sphinx (==7.1.2)", "sphinx-prompt (==1.7.0)", "sphinx-rtd-theme (==2.0.0)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jquery (==4.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "tomli (==2.0.1)", "tomli (==2.0.1)", "tomlkit (==0.12.4)", "urllib3 (==2.2.1)", "zipp (==3.18.1)"] +dev = ["alabaster (==0.7.13)", "astroid (==3.1.0)", "async-timeout (==4.0.3)", "asyncpg (==0.29.0)", "black (==23.12.1)", "certifi (==2024.2.2)", "charset-normalizer (==3.3.2)", "dill (==0.3.8)", "docutils (==0.20.1)", "exceptiongroup (==1.2.0)", "imagesize (==1.4.1)", "importlib-metadata (==7.1.0)", "iniconfig (==2.0.0)", "isort (==5.13.2)", "jinja2 (==3.1.3)", "markupsafe (==2.1.5)", "mccabe (==0.7.0)", "mypy-extensions (==1.0.0)", "pathspec (==0.12.1)", "pluggy (==1.4.0)", "pylint (==3.1.0)", "pytest (==7.4.4)", "pytest-asyncio (==0.21.1)", "pytest-mock (==3.14.0)", "pytz (==2024.1)", "requests (==2.31.0)", "snowballstemmer (==2.2.0)", "sphinx (==7.1.2)", "sphinx-prompt (==1.7.0)", "sphinx-rtd-theme (==2.0.0)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jquery (==4.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "tomli (==2.0.1)", "tomli (==2.0.1)", "tomlkit (==0.12.4)", "urllib3 (==2.2.1)", "zipp (==3.18.1)"] doc = ["alabaster (==0.7.13)", "certifi (==2024.2.2)", "charset-normalizer (==3.3.2)", "docutils (==0.20.1)", "imagesize (==1.4.1)", "importlib-metadata (==7.1.0)", "jinja2 (==3.1.3)", "markupsafe (==2.1.5)", "pytz (==2024.1)", "requests (==2.31.0)", "snowballstemmer (==2.2.0)", "sphinx (==7.1.2)", "sphinx-prompt (==1.7.0)", "sphinx-rtd-theme (==2.0.0)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jquery (==4.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "urllib3 (==2.2.1)", "zipp (==3.18.1)"] postgres = ["async-timeout (==4.0.3)", "asyncpg (==0.29.0)"] style = ["black (==23.12.1)", "mypy-extensions (==1.0.0)", "pathspec (==0.12.1)", "tomli (==2.0.1)"] -test = ["astroid (==3.1.0)", "dill (==0.3.8)", "exceptiongroup (==1.2.0)", "iniconfig (==2.0.0)", "isort (==5.13.2)", "mccabe (==0.7.0)", "pluggy (==1.4.0)", "pylint (==3.1.0)", "pytest (==7.4.4)", "pytest-asyncio (==0.21.1)", "pytest-mock (==3.12.0)", "tomli (==2.0.1)", "tomlkit (==0.12.4)"] +test = ["astroid (==3.1.0)", "dill (==0.3.8)", "exceptiongroup (==1.2.0)", "iniconfig (==2.0.0)", "isort (==5.13.2)", "mccabe (==0.7.0)", "pluggy (==1.4.0)", "pylint (==3.1.0)", "pytest (==7.4.4)", "pytest-asyncio (==0.21.1)", "pytest-mock (==3.14.0)", "tomli (==2.0.1)", "tomlkit (==0.12.4)"] [[package]] name = "red-lavalink" @@ -1895,104 +2018,90 @@ test = ["pytest (>=7)", "pytest-asyncio (>=0.19)"] [[package]] name = "regex" -version = "2023.12.25" +version = "2024.4.28" description = "Alternative regular expression module, to replace re." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, - {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, - {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, - {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, - {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, - {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, - {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, - {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, - {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, - {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, - {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, - {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, - {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, - {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, - {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, + {file = "regex-2024.4.28-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd196d056b40af073d95a2879678585f0b74ad35190fac04ca67954c582c6b61"}, + {file = "regex-2024.4.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8bb381f777351bd534462f63e1c6afb10a7caa9fa2a421ae22c26e796fe31b1f"}, + {file = "regex-2024.4.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:47af45b6153522733aa6e92543938e97a70ce0900649ba626cf5aad290b737b6"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99d6a550425cc51c656331af0e2b1651e90eaaa23fb4acde577cf15068e2e20f"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bf29304a8011feb58913c382902fde3395957a47645bf848eea695839aa101b7"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:92da587eee39a52c91aebea8b850e4e4f095fe5928d415cb7ed656b3460ae79a"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6277d426e2f31bdbacb377d17a7475e32b2d7d1f02faaecc48d8e370c6a3ff31"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28e1f28d07220c0f3da0e8fcd5a115bbb53f8b55cecf9bec0c946eb9a059a94c"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aaa179975a64790c1f2701ac562b5eeb733946eeb036b5bcca05c8d928a62f10"}, + {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6f435946b7bf7a1b438b4e6b149b947c837cb23c704e780c19ba3e6855dbbdd3"}, + {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:19d6c11bf35a6ad077eb23852827f91c804eeb71ecb85db4ee1386825b9dc4db"}, + {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:fdae0120cddc839eb8e3c15faa8ad541cc6d906d3eb24d82fb041cfe2807bc1e"}, + {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e672cf9caaf669053121f1766d659a8813bd547edef6e009205378faf45c67b8"}, + {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f57515750d07e14743db55d59759893fdb21d2668f39e549a7d6cad5d70f9fea"}, + {file = "regex-2024.4.28-cp310-cp310-win32.whl", hash = "sha256:a1409c4eccb6981c7baabc8888d3550df518add6e06fe74fa1d9312c1838652d"}, + {file = "regex-2024.4.28-cp310-cp310-win_amd64.whl", hash = "sha256:1f687a28640f763f23f8a9801fe9e1b37338bb1ca5d564ddd41619458f1f22d1"}, + {file = "regex-2024.4.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:84077821c85f222362b72fdc44f7a3a13587a013a45cf14534df1cbbdc9a6796"}, + {file = "regex-2024.4.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b45d4503de8f4f3dc02f1d28a9b039e5504a02cc18906cfe744c11def942e9eb"}, + {file = "regex-2024.4.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:457c2cd5a646dd4ed536c92b535d73548fb8e216ebee602aa9f48e068fc393f3"}, + {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b51739ddfd013c6f657b55a508de8b9ea78b56d22b236052c3a85a675102dc6"}, + {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:459226445c7d7454981c4c0ce0ad1a72e1e751c3e417f305722bbcee6697e06a"}, + {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:670fa596984b08a4a769491cbdf22350431970d0112e03d7e4eeaecaafcd0fec"}, + {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe00f4fe11c8a521b173e6324d862ee7ee3412bf7107570c9b564fe1119b56fb"}, + {file = "regex-2024.4.28-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36f392dc7763fe7924575475736bddf9ab9f7a66b920932d0ea50c2ded2f5636"}, + {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:23a412b7b1a7063f81a742463f38821097b6a37ce1e5b89dd8e871d14dbfd86b"}, + {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f1d6e4b7b2ae3a6a9df53efbf199e4bfcff0959dbdb5fd9ced34d4407348e39a"}, + {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:499334ad139557de97cbc4347ee921c0e2b5e9c0f009859e74f3f77918339257"}, + {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:0940038bec2fe9e26b203d636c44d31dd8766abc1fe66262da6484bd82461ccf"}, + {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:66372c2a01782c5fe8e04bff4a2a0121a9897e19223d9eab30c54c50b2ebeb7f"}, + {file = "regex-2024.4.28-cp311-cp311-win32.whl", hash = "sha256:c77d10ec3c1cf328b2f501ca32583625987ea0f23a0c2a49b37a39ee5c4c4630"}, + {file = "regex-2024.4.28-cp311-cp311-win_amd64.whl", hash = "sha256:fc0916c4295c64d6890a46e02d4482bb5ccf33bf1a824c0eaa9e83b148291f90"}, + {file = "regex-2024.4.28-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:08a1749f04fee2811c7617fdd46d2e46d09106fa8f475c884b65c01326eb15c5"}, + {file = "regex-2024.4.28-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b8eb28995771c087a73338f695a08c9abfdf723d185e57b97f6175c5051ff1ae"}, + {file = "regex-2024.4.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dd7ef715ccb8040954d44cfeff17e6b8e9f79c8019daae2fd30a8806ef5435c0"}, + {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb0315a2b26fde4005a7c401707c5352df274460f2f85b209cf6024271373013"}, + {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f2fc053228a6bd3a17a9b0a3f15c3ab3cf95727b00557e92e1cfe094b88cc662"}, + {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fe9739a686dc44733d52d6e4f7b9c77b285e49edf8570754b322bca6b85b4cc"}, + {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74fcf77d979364f9b69fcf8200849ca29a374973dc193a7317698aa37d8b01c"}, + {file = "regex-2024.4.28-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:965fd0cf4694d76f6564896b422724ec7b959ef927a7cb187fc6b3f4e4f59833"}, + {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2fef0b38c34ae675fcbb1b5db760d40c3fc3612cfa186e9e50df5782cac02bcd"}, + {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bc365ce25f6c7c5ed70e4bc674f9137f52b7dd6a125037f9132a7be52b8a252f"}, + {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:ac69b394764bb857429b031d29d9604842bc4cbfd964d764b1af1868eeebc4f0"}, + {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:144a1fc54765f5c5c36d6d4b073299832aa1ec6a746a6452c3ee7b46b3d3b11d"}, + {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2630ca4e152c221072fd4a56d4622b5ada876f668ecd24d5ab62544ae6793ed6"}, + {file = "regex-2024.4.28-cp312-cp312-win32.whl", hash = "sha256:7f3502f03b4da52bbe8ba962621daa846f38489cae5c4a7b5d738f15f6443d17"}, + {file = "regex-2024.4.28-cp312-cp312-win_amd64.whl", hash = "sha256:0dd3f69098511e71880fb00f5815db9ed0ef62c05775395968299cb400aeab82"}, + {file = "regex-2024.4.28-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:374f690e1dd0dbdcddea4a5c9bdd97632cf656c69113f7cd6a361f2a67221cb6"}, + {file = "regex-2024.4.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f87ae6b96374db20f180eab083aafe419b194e96e4f282c40191e71980c666"}, + {file = "regex-2024.4.28-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5dbc1bcc7413eebe5f18196e22804a3be1bfdfc7e2afd415e12c068624d48247"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f85151ec5a232335f1be022b09fbbe459042ea1951d8a48fef251223fc67eee1"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57ba112e5530530fd175ed550373eb263db4ca98b5f00694d73b18b9a02e7185"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:224803b74aab56aa7be313f92a8d9911dcade37e5f167db62a738d0c85fdac4b"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a54a047b607fd2d2d52a05e6ad294602f1e0dec2291152b745870afc47c1397"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a2a512d623f1f2d01d881513af9fc6a7c46e5cfffb7dc50c38ce959f9246c94"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c06bf3f38f0707592898428636cbb75d0a846651b053a1cf748763e3063a6925"}, + {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1031a5e7b048ee371ab3653aad3030ecfad6ee9ecdc85f0242c57751a05b0ac4"}, + {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d7a353ebfa7154c871a35caca7bfd8f9e18666829a1dc187115b80e35a29393e"}, + {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:7e76b9cfbf5ced1aca15a0e5b6f229344d9b3123439ffce552b11faab0114a02"}, + {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5ce479ecc068bc2a74cb98dd8dba99e070d1b2f4a8371a7dfe631f85db70fe6e"}, + {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d77b6f63f806578c604dca209280e4c54f0fa9a8128bb8d2cc5fb6f99da4150"}, + {file = "regex-2024.4.28-cp38-cp38-win32.whl", hash = "sha256:d84308f097d7a513359757c69707ad339da799e53b7393819ec2ea36bc4beb58"}, + {file = "regex-2024.4.28-cp38-cp38-win_amd64.whl", hash = "sha256:2cc1b87bba1dd1a898e664a31012725e48af826bf3971e786c53e32e02adae6c"}, + {file = "regex-2024.4.28-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7413167c507a768eafb5424413c5b2f515c606be5bb4ef8c5dee43925aa5718b"}, + {file = "regex-2024.4.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:108e2dcf0b53a7c4ab8986842a8edcb8ab2e59919a74ff51c296772e8e74d0ae"}, + {file = "regex-2024.4.28-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f1c5742c31ba7d72f2dedf7968998730664b45e38827637e0f04a2ac7de2f5f1"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecc6148228c9ae25ce403eade13a0961de1cb016bdb35c6eafd8e7b87ad028b1"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7d893c8cf0e2429b823ef1a1d360a25950ed11f0e2a9df2b5198821832e1947"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4290035b169578ffbbfa50d904d26bec16a94526071ebec3dadbebf67a26b25e"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44a22ae1cfd82e4ffa2066eb3390777dc79468f866f0625261a93e44cdf6482b"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd24fd140b69f0b0bcc9165c397e9b2e89ecbeda83303abf2a072609f60239e2"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:39fb166d2196413bead229cd64a2ffd6ec78ebab83fff7d2701103cf9f4dfd26"}, + {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9301cc6db4d83d2c0719f7fcda37229691745168bf6ae849bea2e85fc769175d"}, + {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7c3d389e8d76a49923683123730c33e9553063d9041658f23897f0b396b2386f"}, + {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:99ef6289b62042500d581170d06e17f5353b111a15aa6b25b05b91c6886df8fc"}, + {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:b91d529b47798c016d4b4c1d06cc826ac40d196da54f0de3c519f5a297c5076a"}, + {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:43548ad74ea50456e1c68d3c67fff3de64c6edb85bcd511d1136f9b5376fc9d1"}, + {file = "regex-2024.4.28-cp39-cp39-win32.whl", hash = "sha256:05d9b6578a22db7dedb4df81451f360395828b04f4513980b6bd7a1412c679cc"}, + {file = "regex-2024.4.28-cp39-cp39-win_amd64.whl", hash = "sha256:3986217ec830c2109875be740531feb8ddafe0dfa49767cdcd072ed7e8927962"}, + {file = "regex-2024.4.28.tar.gz", hash = "sha256:83ab366777ea45d58f72593adf35d36ca911ea8bd838483c1823b883a121b0e4"}, ] [[package]] @@ -2036,28 +2145,28 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.3.4" +version = "0.3.7" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.3.4-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:60c870a7d46efcbc8385d27ec07fe534ac32f3b251e4fc44b3cbfd9e09609ef4"}, - {file = "ruff-0.3.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6fc14fa742e1d8f24910e1fff0bd5e26d395b0e0e04cc1b15c7c5e5fe5b4af91"}, - {file = "ruff-0.3.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3ee7880f653cc03749a3bfea720cf2a192e4f884925b0cf7eecce82f0ce5854"}, - {file = "ruff-0.3.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf133dd744f2470b347f602452a88e70dadfbe0fcfb5fd46e093d55da65f82f7"}, - {file = "ruff-0.3.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f3860057590e810c7ffea75669bdc6927bfd91e29b4baa9258fd48b540a4365"}, - {file = "ruff-0.3.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:986f2377f7cf12efac1f515fc1a5b753c000ed1e0a6de96747cdf2da20a1b369"}, - {file = "ruff-0.3.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fd98e85869603e65f554fdc5cddf0712e352fe6e61d29d5a6fe087ec82b76c"}, - {file = "ruff-0.3.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64abeed785dad51801b423fa51840b1764b35d6c461ea8caef9cf9e5e5ab34d9"}, - {file = "ruff-0.3.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df52972138318bc7546d92348a1ee58449bc3f9eaf0db278906eb511889c4b50"}, - {file = "ruff-0.3.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:98e98300056445ba2cc27d0b325fd044dc17fcc38e4e4d2c7711585bd0a958ed"}, - {file = "ruff-0.3.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:519cf6a0ebed244dce1dc8aecd3dc99add7a2ee15bb68cf19588bb5bf58e0488"}, - {file = "ruff-0.3.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bb0acfb921030d00070539c038cd24bb1df73a2981e9f55942514af8b17be94e"}, - {file = "ruff-0.3.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cf187a7e7098233d0d0c71175375c5162f880126c4c716fa28a8ac418dcf3378"}, - {file = "ruff-0.3.4-py3-none-win32.whl", hash = "sha256:af27ac187c0a331e8ef91d84bf1c3c6a5dea97e912a7560ac0cef25c526a4102"}, - {file = "ruff-0.3.4-py3-none-win_amd64.whl", hash = "sha256:de0d5069b165e5a32b3c6ffbb81c350b1e3d3483347196ffdf86dc0ef9e37dd6"}, - {file = "ruff-0.3.4-py3-none-win_arm64.whl", hash = "sha256:6810563cc08ad0096b57c717bd78aeac888a1bfd38654d9113cb3dc4d3f74232"}, - {file = "ruff-0.3.4.tar.gz", hash = "sha256:f0f4484c6541a99862b693e13a151435a279b271cff20e37101116a21e2a1ad1"}, + {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0e8377cccb2f07abd25e84fc5b2cbe48eeb0fea9f1719cad7caedb061d70e5ce"}, + {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:15a4d1cc1e64e556fa0d67bfd388fed416b7f3b26d5d1c3e7d192c897e39ba4b"}, + {file = "ruff-0.3.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d28bdf3d7dc71dd46929fafeec98ba89b7c3550c3f0978e36389b5631b793663"}, + {file = "ruff-0.3.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:379b67d4f49774ba679593b232dcd90d9e10f04d96e3c8ce4a28037ae473f7bb"}, + {file = "ruff-0.3.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c060aea8ad5ef21cdfbbe05475ab5104ce7827b639a78dd55383a6e9895b7c51"}, + {file = "ruff-0.3.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ebf8f615dde968272d70502c083ebf963b6781aacd3079081e03b32adfe4d58a"}, + {file = "ruff-0.3.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d48098bd8f5c38897b03604f5428901b65e3c97d40b3952e38637b5404b739a2"}, + {file = "ruff-0.3.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da8a4fda219bf9024692b1bc68c9cff4b80507879ada8769dc7e985755d662ea"}, + {file = "ruff-0.3.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c44e0149f1d8b48c4d5c33d88c677a4aa22fd09b1683d6a7ff55b816b5d074f"}, + {file = "ruff-0.3.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3050ec0af72b709a62ecc2aca941b9cd479a7bf2b36cc4562f0033d688e44fa1"}, + {file = "ruff-0.3.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a29cc38e4c1ab00da18a3f6777f8b50099d73326981bb7d182e54a9a21bb4ff7"}, + {file = "ruff-0.3.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b15cc59c19edca917f51b1956637db47e200b0fc5e6e1878233d3a938384b0b"}, + {file = "ruff-0.3.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e491045781b1e38b72c91247cf4634f040f8d0cb3e6d3d64d38dcf43616650b4"}, + {file = "ruff-0.3.7-py3-none-win32.whl", hash = "sha256:bc931de87593d64fad3a22e201e55ad76271f1d5bfc44e1a1887edd0903c7d9f"}, + {file = "ruff-0.3.7-py3-none-win_amd64.whl", hash = "sha256:5ef0e501e1e39f35e03c2acb1d1238c595b8bb36cf7a170e7c1df1b73da00e74"}, + {file = "ruff-0.3.7-py3-none-win_arm64.whl", hash = "sha256:789e144f6dc7019d1f92a812891c645274ed08af6037d11fc65fcbc183b7d59f"}, + {file = "ruff-0.3.7.tar.gz", hash = "sha256:d5c1aebee5162c2226784800ae031f660c350e7a3402c4d1f8ea4e97e232e3ba"}, ] [[package]] @@ -2098,13 +2207,13 @@ files = [ [[package]] name = "tinycss2" -version = "1.2.1" +version = "1.3.0" description = "A tiny CSS parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tinycss2-1.2.1-py3-none-any.whl", hash = "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847"}, - {file = "tinycss2-1.2.1.tar.gz", hash = "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"}, + {file = "tinycss2-1.3.0-py3-none-any.whl", hash = "sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7"}, + {file = "tinycss2-1.3.0.tar.gz", hash = "sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d"}, ] [package.dependencies] @@ -2112,7 +2221,7 @@ webencodings = ">=0.4" [package.extras] doc = ["sphinx", "sphinx_rtd_theme"] -test = ["flake8", "isort", "pytest"] +test = ["pytest", "ruff"] [[package]] name = "tomlkit" @@ -2436,4 +2545,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "42f6d2a053929b5a71b673e30f222c3e5914c723d074b453afd349e11118590f" +content-hash = "67eb5e616951979332b6f32bcb39d85171cbf8377f566ea1862c51b5068b52f3" diff --git a/pyproject.toml b/pyproject.toml index 93bdd53..91c350e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,11 +9,12 @@ package-mode = false [tool.poetry.dependencies] python = ">=3.11,<3.12" -Red-DiscordBot = "^3.5.5" +Red-DiscordBot = "^3.5.9" py-dactyl = "^2.0.4" websockets = "^12.0" pillow = "^10.3.0" numpy = "^1.26.4" +pydantic = "^2.7.1" [tool.poetry.group.dev] optional = true -- 2.45.3 From b6d1510698a7ad3913c8f4c54f74219d5417ae1e Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 13:42:58 -0400 Subject: [PATCH 002/376] fix(aurora): fixed a broken import --- aurora/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index ba69b60..694c9fd 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,9 +1,9 @@ from typing import Dict, List, Optional - from discord import Guild from pydantic import BaseModel -from utilities.database import connect + +from aurora.utilities.database import connect class Moderation(BaseModel): -- 2.45.3 From f3d6244a175ab5b22992b5100b3cc4416118f435 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 13:47:07 -0400 Subject: [PATCH 003/376] fix(aurora): optimizing the from_sql method --- aurora/models.py | 39 ++++++++++----------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 694c9fd..dca0422 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -27,36 +27,17 @@ class Moderation(BaseModel): def __str__(self): return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}" - async def from_sql(self, moderation_id: int, guild: Guild): - """""" - database = connect() - cursor = database.cursor() - + @classmethod + def from_sql(cls, moderation_id: int, guild: Guild): query = f"SELECT * FROM moderation_{guild.id} WHERE moderation_id = ?;" - cursor.execute(query, (moderation_id,)) - result = cursor.fetchone() - cursor.close() - database.close() + with connect() as database, database.cursor() as cursor: + cursor.execute(query, (moderation_id,)) + result = cursor.fetchone() - if result: - ( - self.moderation_id, - self.timestamp, - self.moderation_type, - self.target_type, - self.target_id, - self.moderator_id, - self.role_id, - self.duration, - self.end_timestamp, - self.reason, - self.resolved, - self.resolved_by, - self.resolve_reason, - self.expired, - self.changes, - self.metadata, - ) = result[0:16] + if result: + moderation_data = dict(zip(cls.model_fields, result)) + moderation = cls(**moderation_data) + return moderation - return self + return None -- 2.45.3 From 14a04cff59a8117e84920b07cdeaae888777e9ae Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 13:48:57 -0400 Subject: [PATCH 004/376] fix(aurora): fixed an error --- aurora/models.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index dca0422..90463d4 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -31,13 +31,15 @@ class Moderation(BaseModel): def from_sql(cls, moderation_id: int, guild: Guild): query = f"SELECT * FROM moderation_{guild.id} WHERE moderation_id = ?;" - with connect() as database, database.cursor() as cursor: + with connect() as database: + cursor = database.cursor() cursor.execute(query, (moderation_id,)) result = cursor.fetchone() if result: moderation_data = dict(zip(cls.model_fields, result)) moderation = cls(**moderation_data) + cursor.close() return moderation return None -- 2.45.3 From e5cdd3893fc15ce177ae56b267a8d16c2e21444f Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 14:08:53 -0400 Subject: [PATCH 005/376] fix(aurora): cleaned up the Moderation model --- aurora/models.py | 55 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 90463d4..2b8fcb8 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,35 +1,36 @@ +import json +from datetime import datetime, timedelta from typing import Dict, List, Optional -from discord import Guild from pydantic import BaseModel -from aurora.utilities.database import connect - class Moderation(BaseModel): moderation_id: int - timestamp: int + guild_id: int + timestamp: datetime moderation_type: str target_type: str target_id: int moderator_id: int + role_id: Optional[int] + duration: Optional[timedelta] + end_timestamp: Optional[datetime] + reason: Optional[str] resolved: bool + resolved_by: Optional[int] + resolve_reason: Optional[str] expired: bool - duration: str - end_timestamp: int - reason: str changes: List[Dict] metadata: Dict - resolved_by: Optional[int] = None - resolve_reason: Optional[str] = None - role_id: Optional[int] = None def __str__(self): return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}" @classmethod - def from_sql(cls, moderation_id: int, guild: Guild): - query = f"SELECT * FROM moderation_{guild.id} WHERE moderation_id = ?;" + def from_sql(cls, moderation_id: int, guild_id: int): + from aurora.utilities.database import connect + query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;" with connect() as database: cursor = database.cursor() @@ -37,9 +38,33 @@ class Moderation(BaseModel): result = cursor.fetchone() if result: - moderation_data = dict(zip(cls.model_fields, result)) - moderation = cls(**moderation_data) + if result[7] != "NULL": + hours, minutes, seconds = map(int, result[7].split(':')) + duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) + else: + duration = None + case = { + "moderation_id": int(result[0]), + "guild_id": int(guild_id), + "timestamp": datetime.fromtimestamp(result[1]), + "moderation_type": str(result[2]), + "target_type": str(result[3]), + "target_id": int(result[4]), + "moderator_id": int(result[5]), + "role_id": int(result[6]) if result[6] != "0" else None, + "duration": duration, + "end_timestamp": datetime.fromtimestamp(result[8]) if result[8] != 0 else None, + "reason": result[9] if result[9] != "NULL" else None, + "resolved": bool(result[10]), + "resolved_by": result[11] if result[11] != "NULL" else None, + "resolve_reason": result[12] if result[12] != "NULL" else None, + "expired": bool(result[13]), + "changes": json.loads(result[14]), + "metadata": json.loads(result[15]), + } + cursor.close() - return moderation + + return cls(**case) return None -- 2.45.3 From 2da76eb51a459de9eba6d5095a94b58aee07a80c Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 14:18:19 -0400 Subject: [PATCH 006/376] feat(aurora): subclassed jsonencoder to allow for custom behavior --- aurora/models.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/aurora/models.py b/aurora/models.py index 2b8fcb8..f875ce7 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -68,3 +68,11 @@ class Moderation(BaseModel): return cls(**case) return None + +class JSONEncoder(json.JSONEncoder): + def default(self, o): + if isinstance(o, datetime): + return o.timestamp() + if isinstance(o, timedelta): + return str(o) + return super().default(o) -- 2.45.3 From e8ca0aeb1c54c26f12f3a97e2ae3de38403afd7b Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 14:19:48 -0400 Subject: [PATCH 007/376] fix(aurora): convert float timestamps to integers --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index f875ce7..d93c025 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -72,7 +72,7 @@ class Moderation(BaseModel): class JSONEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, datetime): - return o.timestamp() + return int(o.timestamp()) if isinstance(o, timedelta): return str(o) return super().default(o) -- 2.45.3 From afed1d6a37e5a5dc2ae28e4c8db1937bcace4134 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 14:49:07 -0400 Subject: [PATCH 008/376] feat(aurora): changed a lot of stuff. THIS IS A BREAKING CHANGE! VERY BREAKING! TAKE DATABASE BACKUPS BEFORE UPDATING TO THIS --- aurora/importers/aurora.py | 11 ++++++++--- aurora/models.py | 4 ++++ aurora/utilities/database.py | 36 +++++++++++++++++++++--------------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 44cab98..29d153e 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -62,7 +62,12 @@ class ImportAuroraView(ui.View): case["target_type"] = "USER" if "role_id" not in case or not case["role_id"]: - case["role_id"] = 0 + case["role_id"] = None + else: + case["role_id"] = int(case["role_id"]) + + case["target_id"] = int(case["target_id"]) + case["moderator_id"] = int(case["moderator_id"]) if "changes" not in case or not case["changes"]: case["changes"] = [] @@ -74,11 +79,11 @@ class ImportAuroraView(ui.View): if not metadata.get("imported_from"): metadata.update({"imported_from": "Aurora"}) - if case["duration"] != "NULL": + if case["duration"] != "NULL" and case["duration"] is not None: hours, minutes, seconds = map(int, case["duration"].split(":")) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) else: - duration = "NULL" + duration = None await mysql_log( self.ctx.guild.id, diff --git a/aurora/models.py b/aurora/models.py index d93c025..c4013cb 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -75,4 +75,8 @@ class JSONEncoder(json.JSONEncoder): return int(o.timestamp()) if isinstance(o, timedelta): return str(o) + if isinstance(o, Moderation): + return o.model_dump() + if isinstance(o, None): + return "NULL" return super().default(o) diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index a2bcb92..95ad7c8 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -8,8 +8,7 @@ from discord import Guild from redbot.core import data_manager from .logger import logger -from .utils import (convert_timedelta_to_str, generate_dict, - get_next_case_number) +from .utils import convert_timedelta_to_str, generate_dict, get_next_case_number def connect() -> sqlite3.Connection: @@ -42,9 +41,9 @@ async def create_guild_table(guild: Guild): timestamp INTEGER NOT NULL, moderation_type TEXT NOT NULL, target_type TEXT NOT NULL, - target_id TEXT NOT NULL, - moderator_id TEXT NOT NULL, - role_id TEXT, + target_id INTEGER NOT NULL, + moderator_id INTEGER NOT NULL, + role_id INTEGER, duration TEXT, end_timestamp INTEGER, reason TEXT, @@ -52,8 +51,8 @@ async def create_guild_table(guild: Guild): resolved_by TEXT, resolve_reason TEXT, expired INTEGER NOT NULL, - changes TEXT NOT NULL, - metadata TEXT NOT NULL + changes JSON NOT NULL, + metadata JSON NOT NULL ) """ cursor.execute(query) @@ -111,8 +110,8 @@ async def mysql_log( target_type: str, target_id: int, role_id: int, - duration: timedelta, - reason: str, + duration: timedelta = None, + reason: str = None, database: sqlite3.Connection = None, timestamp: int = None, resolved: bool = False, @@ -125,13 +124,14 @@ async def mysql_log( if not timestamp: timestamp = int(time.time()) - if duration != "NULL": + if duration != "NULL" and duration is not None: end_timedelta = datetime.fromtimestamp(timestamp) + duration end_timestamp = int(end_timedelta.timestamp()) duration = convert_timedelta_to_str(duration) else: - end_timestamp = 0 + duration = None + end_timestamp = None if not expired: if int(time.time()) > end_timestamp: @@ -139,11 +139,17 @@ async def mysql_log( else: expired = 0 - if resolved_by is None: - resolved_by = "NULL" + if reason == "NULL": + reason = None - if resolved_reason is None: - resolved_reason = "NULL" + if resolved_by == "NULL": + resolved_by = None + + if resolved_reason == "NULL": + resolved_reason = None + + if role_id == 0: + role_id = None if not database: database = connect() -- 2.45.3 From ea65816c3270ea782afc72c9c4a11b9da978c024 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 14:51:22 -0400 Subject: [PATCH 009/376] fix(aurora): fixed an incorrect if statement --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index c4013cb..9ac8b90 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -38,7 +38,7 @@ class Moderation(BaseModel): result = cursor.fetchone() if result: - if result[7] != "NULL": + if result[7] is not None: hours, minutes, seconds = map(int, result[7].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) else: -- 2.45.3 From 1d825625f3a27d985b5887e9dd7bdd0db1d1ddee Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 14:53:04 -0400 Subject: [PATCH 010/376] fix(aurora): fixed some broken conditional statements --- aurora/models.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 9ac8b90..77ce650 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -51,13 +51,13 @@ class Moderation(BaseModel): "target_type": str(result[3]), "target_id": int(result[4]), "moderator_id": int(result[5]), - "role_id": int(result[6]) if result[6] != "0" else None, + "role_id": int(result[6]) if result[6] is not None else None, "duration": duration, - "end_timestamp": datetime.fromtimestamp(result[8]) if result[8] != 0 else None, - "reason": result[9] if result[9] != "NULL" else None, + "end_timestamp": datetime.fromtimestamp(result[8]) if result[8] is not None else None, + "reason": result[9], "resolved": bool(result[10]), - "resolved_by": result[11] if result[11] != "NULL" else None, - "resolve_reason": result[12] if result[12] != "NULL" else None, + "resolved_by": result[11], + "resolve_reason": result[12], "expired": bool(result[13]), "changes": json.loads(result[14]), "metadata": json.loads(result[15]), -- 2.45.3 From 92f9619cead2dfd009cc92d336863e5475220080 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 14:54:14 -0400 Subject: [PATCH 011/376] fix(aurora): added two conditional statements to fix an error --- aurora/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 77ce650..31037ec 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -59,8 +59,8 @@ class Moderation(BaseModel): "resolved_by": result[11], "resolve_reason": result[12], "expired": bool(result[13]), - "changes": json.loads(result[14]), - "metadata": json.loads(result[15]), + "changes": json.loads(result[14]) if result[14] else [], + "metadata": json.loads(result[15]) if result[15] else {}, } cursor.close() -- 2.45.3 From 25d7101cb5d148c518fc714edaac6859a59a6b32 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 14:55:17 -0400 Subject: [PATCH 012/376] fix(aurora): testing a potential bugfix --- aurora/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 31037ec..d876cf0 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -59,8 +59,8 @@ class Moderation(BaseModel): "resolved_by": result[11], "resolve_reason": result[12], "expired": bool(result[13]), - "changes": json.loads(result[14]) if result[14] else [], - "metadata": json.loads(result[15]) if result[15] else {}, + "changes": result[14] if result[14] else [], + "metadata": result[15] if result[15] else {}, } cursor.close() -- 2.45.3 From 69805b276f20a17347a58396427f03c5bf4b2fec Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 14:58:24 -0400 Subject: [PATCH 013/376] fix(aurora): fixed an issue with json decoding --- aurora/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index d876cf0..391312d 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -59,8 +59,8 @@ class Moderation(BaseModel): "resolved_by": result[11], "resolve_reason": result[12], "expired": bool(result[13]), - "changes": result[14] if result[14] else [], - "metadata": result[15] if result[15] else {}, + "changes": json.loads(result[14].strip('"').replace('\\"', '"')) if result[14] else [], + "metadata": json.loads(result[15].strip('"').replace('\\"', '"')) if result[15] else {}, } cursor.close() -- 2.45.3 From ca1722fee33ebf41301c15526b85e7a7e67f86b5 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 15:05:50 -0400 Subject: [PATCH 014/376] feat(aurora): migrated to a custom json encoder --- aurora/aurora.py | 30 ++++++++++-------------------- aurora/models.py | 12 ------------ aurora/utilities/encoder.py | 15 +++++++++++++++ aurora/utilities/utils.py | 10 ++++++++++ 4 files changed, 35 insertions(+), 32 deletions(-) create mode 100644 aurora/utilities/encoder.py diff --git a/aurora/aurora.py b/aurora/aurora.py index 15a9b2f..463de76 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -19,8 +19,7 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import (box, error, humanize_list, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -29,19 +28,10 @@ from aurora.menus.guild import Guild from aurora.menus.immune import Immune from aurora.menus.overrides import Overrides from aurora.utilities.config import config, register_config -from aurora.utilities.database import (connect, create_guild_table, fetch_case, - mysql_log) -from aurora.utilities.factory import (addrole_embed, case_factory, - changes_factory, evidenceformat_factory, - guild_embed, immune_embed, - message_factory, overrides_embed) +from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log +from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from aurora.utilities.logger import logger -from aurora.utilities.utils import (check_moddable, check_permissions, - convert_timedelta_to_str, - fetch_channel_dict, fetch_user_dict, - generate_dict, get_footer_image, log, - send_evidenceformat, - timedelta_from_relativedelta) +from aurora.utilities.utils import check_moddable, check_permissions, convert_timedelta_to_str, dump, dumps, fetch_channel_dict, fetch_user_dict, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta class Aurora(commands.Cog): @@ -1078,7 +1068,7 @@ class Aurora(commands.Cog): ) with open(filename, "w", encoding="utf-8") as f: - json.dump(cases, f, indent=2) + dump(cases, f, indent=2) await interaction.followup.send( file=discord.File( @@ -1337,7 +1327,7 @@ class Aurora(commands.Cog): cursor.execute( resolve_query, ( - json.dumps(changes), + dumps(changes), interaction.user.id, reason, case_dict["moderation_id"], @@ -1416,7 +1406,7 @@ class Aurora(commands.Cog): ) with open(filename, "w", encoding="utf-8") as f: - json.dump(case_dict, f, indent=2) + dump(case_dict, f, indent=2) if export.value == "codeblock": content = f"Case #{case:,} exported.\n" + warning( @@ -1437,7 +1427,7 @@ class Aurora(commands.Cog): os.remove(filename) return await interaction.response.send_message( - content=box(json.dumps(case_dict, indent=2), 'json'), + content=box(dumps(case_dict, indent=2), 'json'), ephemeral=ephemeral, ) return @@ -1586,7 +1576,7 @@ class Aurora(commands.Cog): cursor.execute( update_query, ( - json.dumps(changes), + dumps(changes), reason, convert_timedelta_to_str(parsed_time), end_timestamp, @@ -1595,7 +1585,7 @@ class Aurora(commands.Cog): ) else: update_query = f"UPDATE `moderation_{interaction.guild.id}` SET changes = ?, reason = ? WHERE moderation_id = ?" - cursor.execute(update_query, (json.dumps(changes), reason, case)) + cursor.execute(update_query, (dumps(changes), reason, case)) database.commit() new_case = await fetch_case(case, interaction.guild.id) diff --git a/aurora/models.py b/aurora/models.py index 391312d..6244ebf 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -68,15 +68,3 @@ class Moderation(BaseModel): return cls(**case) return None - -class JSONEncoder(json.JSONEncoder): - def default(self, o): - if isinstance(o, datetime): - return int(o.timestamp()) - if isinstance(o, timedelta): - return str(o) - if isinstance(o, Moderation): - return o.model_dump() - if isinstance(o, None): - return "NULL" - return super().default(o) diff --git a/aurora/utilities/encoder.py b/aurora/utilities/encoder.py new file mode 100644 index 0000000..ba69ef2 --- /dev/null +++ b/aurora/utilities/encoder.py @@ -0,0 +1,15 @@ +import json +from datetime import datetime, timedelta + +from aurora.models import Moderation + + +class JSONEncoder(json.JSONEncoder): + def default(self, o): + if isinstance(o, datetime): + return int(o.timestamp()) + if isinstance(o, timedelta): + return str(o) + if isinstance(o, Moderation): + return o.model_dump() + return super().default(o) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 1ff21fa..8a31063 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -296,3 +296,13 @@ def get_footer_image(coginstance: commands.Cog) -> File: """Returns the footer image for the embeds.""" image_path = data_manager.bundled_data_path(coginstance) / "arrow.png" return File(image_path, filename="arrow.png", description="arrow") + +def dumps(obj: any, indent: int = None) -> str: + """Returns a JSON string from an object.""" + from aurora.utilities.encoder import JSONEncoder + return json.dumps(obj, indent=indent, cls=JSONEncoder) + +def dump(obj: any, indent: int = None) -> str: + """Returns a JSON string from an object.""" + from aurora.utilities.encoder import JSONEncoder + return json.dump(obj, indent=indent, cls=JSONEncoder) -- 2.45.3 From 58303b8e9cf73f6d691229e2df25125c89f92b15 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 15:08:08 -0400 Subject: [PATCH 015/376] feat(aurora): added a to_json method to the moderation model --- aurora/models.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aurora/models.py b/aurora/models.py index 6244ebf..4c0fff6 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -68,3 +68,7 @@ class Moderation(BaseModel): return cls(**case) return None + + def to_json(self, indent: int = None, file: bool = False): + from aurora.utilities.utils import dump, dumps + return dump(self.model_dump(), indent=indent) if file else dumps(self.model_dump(), indent=indent) -- 2.45.3 From df8761205518edc0c7abae6a60cf5559c5135b68 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 15:13:31 -0400 Subject: [PATCH 016/376] feat(aurora): added imported_timestamp to metadata on new imports --- aurora/importers/aurora.py | 2 ++ aurora/importers/galacticbot.py | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 29d153e..d1905e7 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -1,6 +1,7 @@ # pylint: disable=duplicate-code import json from datetime import timedelta +from time import time from typing import Dict from discord import ButtonStyle, Interaction, Message, ui @@ -78,6 +79,7 @@ class ImportAuroraView(ui.View): metadata: Dict[str, any] = json.loads(case["metadata"]) if not metadata.get("imported_from"): metadata.update({"imported_from": "Aurora"}) + metadata.update({"imported_timestamp": int(time())}) if case["duration"] != "NULL" and case["duration"] is not None: hours, minutes, seconds = map(int, case["duration"].split(":")) diff --git a/aurora/importers/galacticbot.py b/aurora/importers/galacticbot.py index c6e0b99..3d13b8e 100644 --- a/aurora/importers/galacticbot.py +++ b/aurora/importers/galacticbot.py @@ -1,6 +1,7 @@ # pylint: disable=duplicate-code import json from datetime import timedelta +from time import time from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands @@ -67,12 +68,12 @@ class ImportGalacticBotView(ui.View): if case["duration"] is not None and float(case["duration"]) != 0: duration = timedelta(seconds=round(float(case["duration"]) / 1000)) else: - duration = "NULL" + duration = None except OverflowError: failed_cases.append(case["case"]) continue - metadata = {"imported_from": "GalacticBot"} + metadata = {"imported_from": "GalacticBot", "imported_timestamp": int(time())} if case["type"] == "SLOWMODE": metadata["seconds"] = case["data"]["seconds"] @@ -113,14 +114,14 @@ class ImportGalacticBotView(ui.View): ] else: resolved = 0 - resolved_by = "NULL" - resolved_reason = "NULL" + resolved_by = None + resolved_reason = None changes = [] if case["reason"] and case["reason"] != "N/A": reason = case["reason"] else: - reason = "NULL" + reason = None await mysql_log( self.ctx.guild.id, -- 2.45.3 From 7dfd9c607a30324663a23be36571cb2cf62cbb96 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 15:25:05 -0400 Subject: [PATCH 017/376] misc(aurora): moved some stuff around --- aurora/aurora.py | 21 ++++-- aurora/models.py | 2 +- aurora/utilities/encoder.py | 15 ----- aurora/utilities/json.py | 124 ++++++++++++++++++++++++++++++++++++ aurora/utilities/utils.py | 10 --- 5 files changed, 141 insertions(+), 31 deletions(-) delete mode 100644 aurora/utilities/encoder.py create mode 100644 aurora/utilities/json.py diff --git a/aurora/aurora.py b/aurora/aurora.py index 463de76..300d127 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -19,7 +19,8 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (box, error, humanize_list, + humanize_timedelta, warning) from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -28,10 +29,20 @@ from aurora.menus.guild import Guild from aurora.menus.immune import Immune from aurora.menus.overrides import Overrides from aurora.utilities.config import config, register_config -from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log -from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed +from aurora.utilities.database import (connect, create_guild_table, fetch_case, + mysql_log) +from aurora.utilities.factory import (addrole_embed, case_factory, + changes_factory, evidenceformat_factory, + guild_embed, immune_embed, + message_factory, overrides_embed) +from aurora.utilities.json import dump, dumps from aurora.utilities.logger import logger -from aurora.utilities.utils import check_moddable, check_permissions, convert_timedelta_to_str, dump, dumps, fetch_channel_dict, fetch_user_dict, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from aurora.utilities.utils import (check_moddable, check_permissions, + convert_timedelta_to_str, + fetch_channel_dict, fetch_user_dict, + generate_dict, get_footer_image, log, + send_evidenceformat, + timedelta_from_relativedelta) class Aurora(commands.Cog): @@ -40,7 +51,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["SeaswimmerTheFsh"] - __version__ = "2.1.2" + __version__ = "2.2.0" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): diff --git a/aurora/models.py b/aurora/models.py index 4c0fff6..5ee33c5 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -70,5 +70,5 @@ class Moderation(BaseModel): return None def to_json(self, indent: int = None, file: bool = False): - from aurora.utilities.utils import dump, dumps + from aurora.utilities.json import dump, dumps return dump(self.model_dump(), indent=indent) if file else dumps(self.model_dump(), indent=indent) diff --git a/aurora/utilities/encoder.py b/aurora/utilities/encoder.py deleted file mode 100644 index ba69ef2..0000000 --- a/aurora/utilities/encoder.py +++ /dev/null @@ -1,15 +0,0 @@ -import json -from datetime import datetime, timedelta - -from aurora.models import Moderation - - -class JSONEncoder(json.JSONEncoder): - def default(self, o): - if isinstance(o, datetime): - return int(o.timestamp()) - if isinstance(o, timedelta): - return str(o) - if isinstance(o, Moderation): - return o.model_dump() - return super().default(o) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py new file mode 100644 index 0000000..90b335f --- /dev/null +++ b/aurora/utilities/json.py @@ -0,0 +1,124 @@ +import json +from datetime import datetime, timedelta + +from aurora.models import Moderation + + +class JSONEncoder(json.JSONEncoder): + def default(self, o): + if isinstance(o, datetime): + return int(o.timestamp()) + if isinstance(o, timedelta): + return str(o) + if isinstance(o, Moderation): + return o.model_dump() + return super().default(o) + + +# This is a wrapper around the json module's dumps function that uses our custom JSONEncoder class +def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, + allow_nan=True, indent=None, separators=None, + default=None, sort_keys=False, **kw) -> str: + """Serialize ``obj`` to a JSON formatted ``str``. + + If ``skipkeys`` is true then ``dict`` keys that are not basic types + (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped + instead of raising a ``TypeError``. + + If ``ensure_ascii`` is false, then the return value can contain non-ASCII + characters if they appear in strings contained in ``obj``. Otherwise, all + such characters are escaped in JSON strings. + + If ``check_circular`` is false, then the circular reference check + for container types will be skipped and a circular reference will + result in an ``RecursionError`` (or worse). + + If ``allow_nan`` is false, then it will be a ``ValueError`` to + serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in + strict compliance of the JSON specification, instead of using the + JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). + + If ``indent`` is a non-negative integer, then JSON array elements and + object members will be pretty-printed with that indent level. An indent + level of 0 will only insert newlines. ``None`` is the most compact + representation. + + If specified, ``separators`` should be an ``(item_separator, key_separator)`` + tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and + ``(',', ': ')`` otherwise. To get the most compact JSON representation, + you should specify ``(',', ':')`` to eliminate whitespace. + + ``default(obj)`` is a function that should return a serializable version + of obj or raise TypeError. The default simply raises TypeError. + + If *sort_keys* is true (default: ``False``), then the output of + dictionaries will be sorted by key. + """ + return json.dumps( + obj, + cls=JSONEncoder, + shipkeys=skipkeys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + indent=indent, + separators=separators, + default=default, + sort_keys=sort_keys, + **kw + ) + +# This is a wrapper around the json module's dump function that uses our custom JSONEncoder class +def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, + allow_nan=True, indent=None, separators=None, + default=None, sort_keys=False, **kw) -> str: + """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a + ``.write()``-supporting file-like object). + + If ``skipkeys`` is true then ``dict`` keys that are not basic types + (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped + instead of raising a ``TypeError``. + + If ``ensure_ascii`` is false, then the strings written to ``fp`` can + contain non-ASCII characters if they appear in strings contained in + ``obj``. Otherwise, all such characters are escaped in JSON strings. + + If ``check_circular`` is false, then the circular reference check + for container types will be skipped and a circular reference will + result in an ``RecursionError`` (or worse). + + If ``allow_nan`` is false, then it will be a ``ValueError`` to + serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) + in strict compliance of the JSON specification, instead of using the + JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). + + If ``indent`` is a non-negative integer, then JSON array elements and + object members will be pretty-printed with that indent level. An indent + level of 0 will only insert newlines. ``None`` is the most compact + representation. + + If specified, ``separators`` should be an ``(item_separator, key_separator)`` + tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and + ``(',', ': ')`` otherwise. To get the most compact JSON representation, + you should specify ``(',', ':')`` to eliminate whitespace. + + ``default(obj)`` is a function that should return a serializable version + of obj or raise TypeError. The default simply raises TypeError. + + If *sort_keys* is true (default: ``False``), then the output of + dictionaries will be sorted by key. + """ + return json.dump( + obj, + fp, + cls=JSONEncoder, + skipkeys=skipkeys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + indent=indent, + separators=separators, + default=default, + sort_keys=sort_keys, + **kw + ) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 8a31063..1ff21fa 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -296,13 +296,3 @@ def get_footer_image(coginstance: commands.Cog) -> File: """Returns the footer image for the embeds.""" image_path = data_manager.bundled_data_path(coginstance) / "arrow.png" return File(image_path, filename="arrow.png", description="arrow") - -def dumps(obj: any, indent: int = None) -> str: - """Returns a JSON string from an object.""" - from aurora.utilities.encoder import JSONEncoder - return json.dumps(obj, indent=indent, cls=JSONEncoder) - -def dump(obj: any, indent: int = None) -> str: - """Returns a JSON string from an object.""" - from aurora.utilities.encoder import JSONEncoder - return json.dump(obj, indent=indent, cls=JSONEncoder) -- 2.45.3 From 98f3e5943bd0218122c68b40057b369f04ec52db Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 15:29:01 -0400 Subject: [PATCH 018/376] fix(aurora): fixed incorrect kwarg name --- aurora/utilities/json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index 90b335f..bac1668 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -57,7 +57,7 @@ def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, return json.dumps( obj, cls=JSONEncoder, - shipkeys=skipkeys, + skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular, allow_nan=allow_nan, -- 2.45.3 From ca7c0d8d7cc1e4b300b55fcc6a0aad76e061fd97 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 15:33:49 -0400 Subject: [PATCH 019/376] fix(aurora): use pydantic basemodels instead of the Moderation model --- aurora/utilities/json.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index bac1668..c3e79a3 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -1,7 +1,7 @@ import json from datetime import datetime, timedelta -from aurora.models import Moderation +from pydantic import BaseModel class JSONEncoder(json.JSONEncoder): @@ -10,7 +10,7 @@ class JSONEncoder(json.JSONEncoder): return int(o.timestamp()) if isinstance(o, timedelta): return str(o) - if isinstance(o, Moderation): + if isinstance(o, BaseModel): return o.model_dump() return super().default(o) -- 2.45.3 From 2dfc9d98240e45c2f6ccc9710d34f7ba69bbe661 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 15:37:07 -0400 Subject: [PATCH 020/376] fix(aurora): use AuroraBaseModels for the JSONEncoder class instead of just pydantic ones to prevent issues with other data types --- aurora/models.py | 5 ++++- aurora/utilities/json.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 5ee33c5..62b5ea7 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -5,7 +5,10 @@ from typing import Dict, List, Optional from pydantic import BaseModel -class Moderation(BaseModel): + +class AuroraBaseModel(BaseModel): + """Base class for all models in Aurora.""" +class Moderation(AuroraBaseModel): moderation_id: int guild_id: int timestamp: datetime diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index c3e79a3..e8678af 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -1,7 +1,7 @@ import json from datetime import datetime, timedelta -from pydantic import BaseModel +from aurora.models import AuroraBaseModel class JSONEncoder(json.JSONEncoder): @@ -10,7 +10,7 @@ class JSONEncoder(json.JSONEncoder): return int(o.timestamp()) if isinstance(o, timedelta): return str(o) - if isinstance(o, BaseModel): + if isinstance(o, AuroraBaseModel): return o.model_dump() return super().default(o) -- 2.45.3 From 6147c8c6d5c7ca16d7e84301ce4c798321ef27ef Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 16:54:12 -0400 Subject: [PATCH 021/376] feat(aurora): whole bunch of changes to the models and various other things --- aurora/aurora.py | 36 ++++------- aurora/models.py | 120 ++++++++++++++++++++++++++---------- aurora/utilities/factory.py | 114 +++++++++------------------------- aurora/utilities/utils.py | 45 ++++++++------ poetry.lock | 13 +++- pyproject.toml | 1 + 6 files changed, 167 insertions(+), 162 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 300d127..0996fd8 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -19,8 +19,7 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import (box, error, humanize_list, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -28,21 +27,13 @@ from aurora.menus.addrole import Addrole from aurora.menus.guild import Guild from aurora.menus.immune import Immune from aurora.menus.overrides import Overrides +from aurora.models import Moderation from aurora.utilities.config import config, register_config -from aurora.utilities.database import (connect, create_guild_table, fetch_case, - mysql_log) -from aurora.utilities.factory import (addrole_embed, case_factory, - changes_factory, evidenceformat_factory, - guild_embed, immune_embed, - message_factory, overrides_embed) +from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log +from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from aurora.utilities.json import dump, dumps from aurora.utilities.logger import logger -from aurora.utilities.utils import (check_moddable, check_permissions, - convert_timedelta_to_str, - fetch_channel_dict, fetch_user_dict, - generate_dict, get_footer_image, log, - send_evidenceformat, - timedelta_from_relativedelta) +from aurora.utilities.utils import check_moddable, check_permissions, convert_timedelta_to_str, fetch_channel_dict, fetch_user_dict, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta class Aurora(commands.Cog): @@ -1406,10 +1397,10 @@ class Aurora(commands.Cog): ) if case != 0: - case_dict = await fetch_case(case, interaction.guild.id) - if case_dict: + mod = Moderation.from_sql(interaction.client, case, interaction.guild.id) + if mod: if export: - if export.value == "file" or len(str(case_dict)) > 1800: + if export.value == "file" or len(mod.to_json(2)) > 1800: filename = ( str(data_manager.cog_data_path(cog_instance=self)) + str(os.sep) @@ -1417,8 +1408,7 @@ class Aurora(commands.Cog): ) with open(filename, "w", encoding="utf-8") as f: - dump(case_dict, f, indent=2) - + mod.to_json(2, f) if export.value == "codeblock": content = f"Case #{case:,} exported.\n" + warning( "Case was too large to export as codeblock, so it has been uploaded as a `.json` file." @@ -1438,27 +1428,27 @@ class Aurora(commands.Cog): os.remove(filename) return await interaction.response.send_message( - content=box(dumps(case_dict, indent=2), 'json'), + content=box(mod.to_json(2), 'json'), ephemeral=ephemeral, ) return if changes: embed = await changes_factory( - interaction=interaction, case_dict=case_dict + interaction=interaction, moderation=mod ) await interaction.response.send_message( embed=embed, ephemeral=ephemeral ) elif evidenceformat: content = await evidenceformat_factory( - interaction=interaction, case_dict=case_dict + interaction=interaction, moderation=mod ) await interaction.response.send_message( content=content, ephemeral=ephemeral ) else: embed = await case_factory( - interaction=interaction, case_dict=case_dict + interaction=interaction, moderation=mod ) await interaction.response.send_message( embed=embed, ephemeral=ephemeral diff --git a/aurora/models.py b/aurora/models.py index 62b5ea7..9fbb0ba 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,14 +1,18 @@ -import json from datetime import datetime, timedelta -from typing import Dict, List, Optional +from typing import Any, Dict, List, Optional, Union +from async_property import async_cached_property +from discord import Forbidden, HTTPException, InvalidData, NotFound from pydantic import BaseModel +from redbot.core.bot import Red +from aurora.utilities.utils import generate_dict class AuroraBaseModel(BaseModel): """Base class for all models in Aurora.""" class Moderation(AuroraBaseModel): + bot: Red moderation_id: int guild_id: int timestamp: datetime @@ -27,11 +31,36 @@ class Moderation(AuroraBaseModel): changes: List[Dict] metadata: Dict + @property + def id(self) -> int: + return self.moderation_id + + @property + def type(self) -> str: + return self.moderation_type + + @async_cached_property + async def moderator(self) -> "PartialUser": + return await PartialUser.from_id(self.bot, self.moderator_id) + + @async_cached_property + async def target(self) -> Union["PartialUser", "PartialChannel"]: + if self.target_type == "user": + return await PartialUser.from_id(self.bot, self.target_id) + else: + return await PartialChannel.from_id(self.bot, self.target_id) + + @async_cached_property + async def resolved_by_user(self) -> Optional["PartialUser"]: + if self.resolved_by: + return await PartialUser.from_id(self.bot, self.resolved_by) + return None + def __str__(self): return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}" @classmethod - def from_sql(cls, moderation_id: int, guild_id: int): + def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> Optional["Moderation"]: from aurora.utilities.database import connect query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;" @@ -41,37 +70,64 @@ class Moderation(AuroraBaseModel): result = cursor.fetchone() if result: - if result[7] is not None: - hours, minutes, seconds = map(int, result[7].split(':')) - duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) - else: - duration = None - case = { - "moderation_id": int(result[0]), - "guild_id": int(guild_id), - "timestamp": datetime.fromtimestamp(result[1]), - "moderation_type": str(result[2]), - "target_type": str(result[3]), - "target_id": int(result[4]), - "moderator_id": int(result[5]), - "role_id": int(result[6]) if result[6] is not None else None, - "duration": duration, - "end_timestamp": datetime.fromtimestamp(result[8]) if result[8] is not None else None, - "reason": result[9], - "resolved": bool(result[10]), - "resolved_by": result[11], - "resolve_reason": result[12], - "expired": bool(result[13]), - "changes": json.loads(result[14].strip('"').replace('\\"', '"')) if result[14] else [], - "metadata": json.loads(result[15].strip('"').replace('\\"', '"')) if result[15] else {}, - } - + case = generate_dict(result) cursor.close() - - return cls(**case) + return cls.from_dict(bot, case) return None - def to_json(self, indent: int = None, file: bool = False): + @classmethod + def from_dict(cls, bot: Red, data: dict) -> "Moderation": + return cls(bot=bot, **data) + + def to_json(self, indent: int = None, file: Any = None): from aurora.utilities.json import dump, dumps - return dump(self.model_dump(), indent=indent) if file else dumps(self.model_dump(), indent=indent) + return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent) + + +class PartialUser(AuroraBaseModel): + id: int + username: str + discriminator: int + + @property + def name(self): + return f"{self.username}#{self.discriminator}" if self.discriminator == 0 else self.username + + def __str__(self): + return self.name + + @classmethod + async def from_id(cls, bot: Red, user_id: int) -> "PartialUser": + user = bot.get_user(user_id) + if not user: + try: + user = await bot.fetch_user(user_id) + return cls(id=user.id, username=user.name, discriminator=user.discriminator) + except NotFound: + return cls(id=user_id, username="Deleted User", discriminator=0) + +class PartialChannel(AuroraBaseModel): + id: int + name: str + + @property + def mention(self): + if self.name == "Deleted Channel" or self.name == "Forbidden Channel": + return self.name + return f"<#{self.id}>" + + def __str__(self): + return self.mention + + @classmethod + async def from_id(cls, bot: Red, channel_id: int) -> "PartialChannel": + user = bot.get_channel(channel_id) + if not user: + try: + user = await bot.fetch_channel(channel_id) + return cls(id=user.id, username=user.name, discriminator=user.discriminator) + except (NotFound, InvalidData, HTTPException, Forbidden) as e: + if e == Forbidden: + return cls(id=channel_id, name="Forbidden Channel") + return cls(id=channel_id, name="Deleted Channel") diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index d7f4eb7..4f9d8c6 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -1,13 +1,18 @@ # pylint: disable=cyclic-import from datetime import datetime, timedelta -from typing import Union +from typing import Optional, Union -from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User +from discord import (Color, Embed, Guild, Interaction, InteractionMessage, + Member, Role, User) from redbot.core import commands -from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (bold, box, error, + humanize_timedelta, warning) +from aurora.models import Moderation, PartialChannel, PartialUser from aurora.utilities.config import config -from aurora.utilities.utils import fetch_channel_dict, fetch_user_dict, get_bool_emoji, get_next_case_number, get_pagesize_str +from aurora.utilities.utils import (fetch_channel_dict, fetch_user_dict, + get_bool_emoji, get_next_case_number, + get_pagesize_str) async def message_factory( @@ -94,7 +99,7 @@ async def message_factory( async def log_factory( - interaction: Interaction, case_dict: dict, resolved: bool = False + interaction: Interaction, moderation: Moderation, resolved: bool = False ) -> Embed: """This function creates a log embed from set parameters, meant for moderation logging. @@ -103,113 +108,50 @@ async def log_factory( case_dict (dict): The case dictionary. resolved (bool, optional): Whether the case is resolved or not. Defaults to False. """ + target: Union[PartialUser, PartialChannel] = await moderation.target + moderator: PartialUser = await moderation.moderator if resolved: - if case_dict["target_type"] == "USER": - target_user = await fetch_user_dict(interaction.client, case_dict["target_id"]) - target_name = ( - f"`{target_user['name']}`" - if target_user["discriminator"] == "0" - else f"`{target_user['name']}#{target_user['discriminator']}`" - ) - elif case_dict["target_type"] == "CHANNEL": - target_user = await fetch_channel_dict(interaction.guild, case_dict["target_id"]) - if target_user["mention"]: - target_name = f"{target_user['mention']}" - else: - target_name = f"`{target_user['name']}`" - - moderator_user = await fetch_user_dict(interaction.client, case_dict["moderator_id"]) - moderator_name = ( - f"`{moderator_user['name']}`" - if moderator_user["discriminator"] == "0" - else f"`{moderator_user['name']}#{moderator_user['discriminator']}`" - ) - embed = Embed( - title=f"📕 Case #{case_dict['moderation_id']:,} Resolved", + title=f"📕 Case #{moderation.id:,} Resolved", color=await interaction.client.get_embed_color(interaction.channel), ) - embed.description = f"**Type:** {str.title(case_dict['moderation_type'])}\n**Target:** {target_name} ({target_user['id']})\n**Moderator:** {moderator_name} ({moderator_user['id']})\n**Timestamp:** | " + resolved_by: Optional[PartialUser] = await moderation.resolved_by_user + embed.description = f"**Type:** {str.title(moderation.moderation_type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " - if case_dict["duration"] != "NULL": - td = timedelta( - **{ - unit: int(val) - for unit, val in zip( - ["hours", "minutes", "seconds"], - case_dict["duration"].split(":"), - ) - } - ) + if moderation.duration is not None: duration_embed = ( - f"{humanize_timedelta(timedelta=td)} | " - if case_dict["expired"] == "0" - else str(humanize_timedelta(timedelta=td)) + f"{humanize_timedelta(timedelta=moderation.duration)} | " + if not moderation.expired + else str(humanize_timedelta(timedelta=moderation.duration)) ) embed.description = ( embed.description - + f"\n**Duration:** {duration_embed}\n**Expired:** {bool(case_dict['expired'])}" + + f"\n**Duration:** {duration_embed}\n**Expired:** {moderation.expired}" ) - embed.add_field(name="Reason", value=box(case_dict["reason"]), inline=False) + embed.add_field(name="Reason", value=box(moderation.reason), inline=False) - resolved_user = await fetch_user_dict(interaction.client, case_dict["resolved_by"]) - resolved_name = ( - resolved_user["name"] - if resolved_user["discriminator"] == "0" - else f"{resolved_user['name']}#{resolved_user['discriminator']}" - ) embed.add_field( name="Resolve Reason", - value=f"Resolved by `{resolved_name}` ({resolved_user['id']}) for:\n" - + box(case_dict["resolve_reason"]), + value=f"Resolved by `{resolved_by.name}` ({resolved_by.id}) for:\n" + + box(moderation.resolve_reason), inline=False, ) else: - if case_dict["target_type"] == "USER": - target_user = await fetch_user_dict(interaction.client, case_dict["target_id"]) - target_name = ( - f"`{target_user['name']}`" - if target_user["discriminator"] == "0" - else f"`{target_user['name']}#{target_user['discriminator']}`" - ) - elif case_dict["target_type"] == "CHANNEL": - target_user = await fetch_channel_dict(interaction.guild, case_dict["target_id"]) - if target_user["mention"]: - target_name = target_user["mention"] - else: - target_name = f"`{target_user['name']}`" - - moderator_user = await fetch_user_dict(interaction.client, case_dict["moderator_id"]) - moderator_name = ( - f"`{moderator_user['name']}`" - if moderator_user["discriminator"] == "0" - else f"`{moderator_user['name']}#{moderator_user['discriminator']}`" - ) - embed = Embed( - title=f"📕 Case #{case_dict['moderation_id']:,}", + title=f"📕 Case #{moderation.id:,}", color=await interaction.client.get_embed_color(interaction.channel), ) - embed.description = f"**Type:** {str.title(case_dict['moderation_type'])}\n**Target:** {target_name} ({target_user['id']})\n**Moderator:** {moderator_name} ({moderator_user['id']})\n**Timestamp:** | " + embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " - if case_dict["duration"] != "NULL": - td = timedelta( - **{ - unit: int(val) - for unit, val in zip( - ["hours", "minutes", "seconds"], - case_dict["duration"].split(":"), - ) - } - ) + if moderation.duration: embed.description = ( embed.description - + f"\n**Duration:** {humanize_timedelta(timedelta=td)} | " + + f"\n**Duration:** {humanize_timedelta(timedelta=moderation.duration)} | " ) - embed.add_field(name="Reason", value=box(case_dict["reason"]), inline=False) + embed.add_field(name="Reason", value=box(moderation.reason), inline=False) return embed diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 1ff21fa..3761543 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -1,7 +1,6 @@ # pylint: disable=cyclic-import import json -from datetime import datetime -from datetime import timedelta as td +from datetime import datetime, timedelta from typing import Optional, Union from dateutil.relativedelta import relativedelta as rd @@ -10,7 +9,7 @@ from discord.errors import Forbidden, NotFound from redbot.core import commands, data_manager from redbot.core.utils.chat_formatting import error -from .config import config +from aurora.utilities.config import config def check_permissions( @@ -125,24 +124,30 @@ async def get_next_case_number(guild_id: str, cursor=None) -> int: return (result[0] + 1) if result else 1 -def generate_dict(result) -> dict: +def generate_dict(result: dict, guild_id: int) -> dict: + if result[7] is not None: + hours, minutes, seconds = map(int, result[7].split(':')) + duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) + else: + duration = None case = { - "moderation_id": result[0], - "timestamp": result[1], - "moderation_type": result[2], - "target_type": result[3], - "target_id": result[4], - "moderator_id": result[5], - "role_id": result[6], - "duration": result[7], - "end_timestamp": result[8], + "moderation_id": int(result[0]), + "guild_id": int(guild_id), + "timestamp": datetime.fromtimestamp(result[1]), + "moderation_type": str(result[2]), + "target_type": str(result[3]), + "target_id": int(result[4]), + "moderator_id": int(result[5]), + "role_id": int(result[6]) if result[6] is not None else None, + "duration": duration, + "end_timestamp": datetime.fromtimestamp(result[8]) if result[8] is not None else None, "reason": result[9], - "resolved": result[10], + "resolved": bool(result[10]), "resolved_by": result[11], "resolve_reason": result[12], - "expired": result[13], - "changes": json.loads(result[14]), - "metadata": json.loads(result[15]), + "expired": bool(result[13]), + "changes": json.loads(result[14].strip('"').replace('\\"', '"')) if result[14] else [], + "metadata": json.loads(result[15].strip('"').replace('\\"', '"')) if result[15] else {}, } return case @@ -241,9 +246,9 @@ async def send_evidenceformat(interaction: Interaction, case_dict: dict) -> None await interaction.followup.send(content=content, ephemeral=True) -def convert_timedelta_to_str(timedelta: td) -> str: +def convert_timedelta_to_str(td: timedelta) -> str: """This function converts a timedelta object to a string.""" - total_seconds = int(timedelta.total_seconds()) + total_seconds = int(td.total_seconds()) hours = total_seconds // 3600 minutes = (total_seconds % 3600) // 60 seconds = total_seconds % 60 @@ -286,7 +291,7 @@ def create_pagesize_options() -> list[SelectOption]: ) return options -def timedelta_from_relativedelta(relativedelta: rd) -> td: +def timedelta_from_relativedelta(relativedelta: rd) -> timedelta: """Converts a relativedelta object to a timedelta object.""" now = datetime.now() then = now - relativedelta diff --git a/poetry.lock b/poetry.lock index 0a5918b..9089f57 100644 --- a/poetry.lock +++ b/poetry.lock @@ -206,6 +206,17 @@ files = [ {file = "astroid-3.1.0.tar.gz", hash = "sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4"}, ] +[[package]] +name = "async-property" +version = "0.2.2" +description = "Python decorator for async properties." +optional = false +python-versions = "*" +files = [ + {file = "async_property-0.2.2-py2.py3-none-any.whl", hash = "sha256:8924d792b5843994537f8ed411165700b27b2bd966cefc4daeefc1253442a9d7"}, + {file = "async_property-0.2.2.tar.gz", hash = "sha256:17d9bd6ca67e27915a75d92549df64b5c7174e9dc806b30a3934dc4ff0506380"}, +] + [[package]] name = "attrs" version = "23.2.0" @@ -2545,4 +2556,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "67eb5e616951979332b6f32bcb39d85171cbf8377f566ea1862c51b5068b52f3" +content-hash = "05c89da1577b4a3507856338502218e0da92dd9785a5fc4a78d6cb59058d887f" diff --git a/pyproject.toml b/pyproject.toml index 91c350e..7e50d58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ websockets = "^12.0" pillow = "^10.3.0" numpy = "^1.26.4" pydantic = "^2.7.1" +async-property = "^0.2.2" [tool.poetry.group.dev] optional = true -- 2.45.3 From d13ad88f1699b0439cf3e6798da8b0cc82eb6ddb Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 17:09:22 -0400 Subject: [PATCH 022/376] fix(aurora): fixed a whole bunch of pydantic errors --- aurora/models.py | 10 +++------- aurora/utilities/factory.py | 14 +++++++------- poetry.lock | 13 +------------ pyproject.toml | 1 - 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 9fbb0ba..6de0340 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,7 +1,6 @@ from datetime import datetime, timedelta from typing import Any, Dict, List, Optional, Union -from async_property import async_cached_property from discord import Forbidden, HTTPException, InvalidData, NotFound from pydantic import BaseModel from redbot.core.bot import Red @@ -39,19 +38,16 @@ class Moderation(AuroraBaseModel): def type(self) -> str: return self.moderation_type - @async_cached_property - async def moderator(self) -> "PartialUser": + async def get_moderator(self) -> "PartialUser": return await PartialUser.from_id(self.bot, self.moderator_id) - @async_cached_property - async def target(self) -> Union["PartialUser", "PartialChannel"]: + async def get_target(self) -> Union["PartialUser", "PartialChannel"]: if self.target_type == "user": return await PartialUser.from_id(self.bot, self.target_id) else: return await PartialChannel.from_id(self.bot, self.target_id) - @async_cached_property - async def resolved_by_user(self) -> Optional["PartialUser"]: + async def get_resolved_by(self) -> Optional["PartialUser"]: if self.resolved_by: return await PartialUser.from_id(self.bot, self.resolved_by) return None diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 4f9d8c6..c6506ec 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -1,6 +1,6 @@ # pylint: disable=cyclic-import from datetime import datetime, timedelta -from typing import Optional, Union +from typing import Union from discord import (Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User) @@ -8,7 +8,7 @@ from redbot.core import commands from redbot.core.utils.chat_formatting import (bold, box, error, humanize_timedelta, warning) -from aurora.models import Moderation, PartialChannel, PartialUser +from aurora.models import Moderation from aurora.utilities.config import config from aurora.utilities.utils import (fetch_channel_dict, fetch_user_dict, get_bool_emoji, get_next_case_number, @@ -104,19 +104,19 @@ async def log_factory( """This function creates a log embed from set parameters, meant for moderation logging. Args: - interaction (Interaction): The interaction object. - case_dict (dict): The case dictionary. + interaction (discord.Interaction): The interaction object. + moderation (aurora.models.Moderation): The moderation object. resolved (bool, optional): Whether the case is resolved or not. Defaults to False. """ - target: Union[PartialUser, PartialChannel] = await moderation.target - moderator: PartialUser = await moderation.moderator + target = await moderation.get_target() + moderator = await moderation.get_moderator() if resolved: embed = Embed( title=f"📕 Case #{moderation.id:,} Resolved", color=await interaction.client.get_embed_color(interaction.channel), ) - resolved_by: Optional[PartialUser] = await moderation.resolved_by_user + resolved_by = await moderation.get_resolved_by() embed.description = f"**Type:** {str.title(moderation.moderation_type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " if moderation.duration is not None: diff --git a/poetry.lock b/poetry.lock index 9089f57..0a5918b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -206,17 +206,6 @@ files = [ {file = "astroid-3.1.0.tar.gz", hash = "sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4"}, ] -[[package]] -name = "async-property" -version = "0.2.2" -description = "Python decorator for async properties." -optional = false -python-versions = "*" -files = [ - {file = "async_property-0.2.2-py2.py3-none-any.whl", hash = "sha256:8924d792b5843994537f8ed411165700b27b2bd966cefc4daeefc1253442a9d7"}, - {file = "async_property-0.2.2.tar.gz", hash = "sha256:17d9bd6ca67e27915a75d92549df64b5c7174e9dc806b30a3934dc4ff0506380"}, -] - [[package]] name = "attrs" version = "23.2.0" @@ -2556,4 +2545,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "05c89da1577b4a3507856338502218e0da92dd9785a5fc4a78d6cb59058d887f" +content-hash = "67eb5e616951979332b6f32bcb39d85171cbf8377f566ea1862c51b5068b52f3" diff --git a/pyproject.toml b/pyproject.toml index 7e50d58..91c350e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,6 @@ websockets = "^12.0" pillow = "^10.3.0" numpy = "^1.26.4" pydantic = "^2.7.1" -async-property = "^0.2.2" [tool.poetry.group.dev] optional = true -- 2.45.3 From 26bf5920c6f1d1f8a7b2bc6b4d03c1de5344835d Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 17:10:26 -0400 Subject: [PATCH 023/376] fix(aurora): mark the bot as a classvar in the moderation model --- aurora/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 6de0340..8409ee2 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,5 +1,5 @@ from datetime import datetime, timedelta -from typing import Any, Dict, List, Optional, Union +from typing import Any, ClassVar, Dict, List, Optional, Union from discord import Forbidden, HTTPException, InvalidData, NotFound from pydantic import BaseModel @@ -11,7 +11,7 @@ from aurora.utilities.utils import generate_dict class AuroraBaseModel(BaseModel): """Base class for all models in Aurora.""" class Moderation(AuroraBaseModel): - bot: Red + bot: ClassVar[Red] moderation_id: int guild_id: int timestamp: datetime -- 2.45.3 From a3a208b38e10ae8f9153e91b1017829f757f82be Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 17:12:35 -0400 Subject: [PATCH 024/376] fix(aurora): fixed an incorrect function call in Moderation.from_sql() --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 8409ee2..e9f0ca0 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -66,7 +66,7 @@ class Moderation(AuroraBaseModel): result = cursor.fetchone() if result: - case = generate_dict(result) + case = generate_dict(result, guild_id) cursor.close() return cls.from_dict(bot, case) -- 2.45.3 From 2c336ff70c143abea2a605ded05b934ad185e9cb Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 17:15:21 -0400 Subject: [PATCH 025/376] fix(aurora): fixed a faulty expiration check --- aurora/aurora.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 0996fd8..0cc9546 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1621,7 +1621,7 @@ class Aurora(commands.Cog): if not await self.bot.cog_disabled_in_guild(self, guild): time_per_guild = time.time() - tempban_query = f"SELECT target_id, moderation_id FROM moderation_{guild.id} WHERE end_timestamp != 0 AND end_timestamp <= ? AND moderation_type = 'TEMPBAN' AND expired = 0" + tempban_query = f"SELECT target_id, moderation_id FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'TEMPBAN' AND expired = 0" try: cursor.execute(tempban_query, (time.time(),)) @@ -1680,7 +1680,7 @@ class Aurora(commands.Cog): ) removerole_num = 0 - addrole_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp != 0 AND end_timestamp <= ? AND moderation_type = 'ADDROLE' AND expired = 0" + addrole_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL AND end_timestamp <= ? AND moderation_type = 'ADDROLE' AND expired = 0" try: cursor.execute(addrole_query, (time.time(),)) result = cursor.fetchall() @@ -1715,7 +1715,7 @@ class Aurora(commands.Cog): continue addrole_num = 0 - removerole_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp != 0 AND end_timestamp <= ? AND moderation_type = 'REMOVEROLE' AND expired = 0" + removerole_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'REMOVEROLE' AND expired = 0" try: cursor.execute(removerole_query, (time.time(),)) result = cursor.fetchall() @@ -1744,7 +1744,7 @@ class Aurora(commands.Cog): logger.error("Adding the role %s to user %s failed due to: \n%s", role_id, target_id, e) continue - expiry_query = f"UPDATE `moderation_{guild.id}` SET expired = 1 WHERE (end_timestamp != 0 AND end_timestamp <= ? AND expired = 0) OR (expired = 0 AND resolved = 1);" + expiry_query = f"UPDATE `moderation_{guild.id}` SET expired = 1 WHERE (end_timestamp IS NOT NULL AND end_timestamp <= ? AND expired = 0) OR (expired = 0 AND resolved = 1);" cursor.execute(expiry_query, (time.time(),)) per_guild_completion_time = (time.time() - time_per_guild) * 1000 -- 2.45.3 From eea66607d9479315a742f7111fc825b7015f4836 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 17:31:16 -0400 Subject: [PATCH 026/376] feat(aurora): finished migrating case_factory to the new model --- aurora/models.py | 32 ++++++++++++++- aurora/utilities/factory.py | 82 +++++++++++++------------------------ 2 files changed, 58 insertions(+), 56 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index e9f0ca0..2561267 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -52,6 +52,11 @@ class Moderation(AuroraBaseModel): return await PartialUser.from_id(self.bot, self.resolved_by) return None + async def get_role(self) -> Optional["PartialRole"]: + if self.role_id: + return await PartialRole.from_id(self.bot, self.guild_id, self.role_id) + return None + def __str__(self): return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}" @@ -76,9 +81,9 @@ class Moderation(AuroraBaseModel): def from_dict(cls, bot: Red, data: dict) -> "Moderation": return cls(bot=bot, **data) - def to_json(self, indent: int = None, file: Any = None): + def to_json(self, indent: int = None, file: Any = None, **kwargs): from aurora.utilities.json import dump, dumps - return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent) + return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) class PartialUser(AuroraBaseModel): @@ -127,3 +132,26 @@ class PartialChannel(AuroraBaseModel): if e == Forbidden: return cls(id=channel_id, name="Forbidden Channel") return cls(id=channel_id, name="Deleted Channel") + +class PartialRole(AuroraBaseModel): + id: int + guild_id: int + name: str + + @property + def mention(self): + return f"<@&{self.id}>" + + def __str__(self): + return self.mention + + @classmethod + async def from_id(cls, bot: Red, guild_id: int, role_id: int) -> "PartialRole": + try: + guild = await bot.fetch_guild(guild_id, with_counts=False) + except (Forbidden, HTTPException): + return cls(id=role_id, guild_id=guild_id, name="Forbidden Role") + role = guild.get_role(role_id) + if not role: + return cls(id=role_id, guild_id=guild_id, name="Deleted Role") + return cls(id=role.id, guild_id=guild_id, name=role.name) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index c6506ec..09d9dd3 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -155,83 +155,57 @@ async def log_factory( return embed -async def case_factory(interaction: Interaction, case_dict: dict) -> Embed: +async def case_factory(interaction: Interaction, moderation: Moderation) -> Embed: """This function creates a case embed from set parameters. Args: - interaction (Interaction): The interaction object. - case_dict (dict): The case dictionary. + interaction (discord.Interaction): The interaction object. + moderation (aurora.models.Moderation): The moderation object. """ - if case_dict["target_type"] == "USER": - target_user = await fetch_user_dict(interaction.client, case_dict["target_id"]) - target_name = ( - f"`{target_user['name']}`" - if target_user["discriminator"] == "0" - else f"`{target_user['name']}#{target_user['discriminator']}`" - ) - elif case_dict["target_type"] == "CHANNEL": - target_user = await fetch_channel_dict(interaction.guild, case_dict["target_id"]) - if target_user["mention"]: - target_name = f"{target_user['mention']}" - else: - target_name = f"`{target_user['name']}`" - - moderator_user = await fetch_user_dict(interaction.client, case_dict["moderator_id"]) - moderator_name = ( - f"`{moderator_user['name']}`" - if moderator_user["discriminator"] == "0" - else f"`{moderator_user['name']}#{moderator_user['discriminator']}`" - ) + target = await moderation.get_target() + moderator = await moderation.get_moderator() embed = Embed( - title=f"📕 Case #{case_dict['moderation_id']:,}", + title=f"📕 Case #{moderation.id:,}", color=await interaction.client.get_embed_color(interaction.channel), ) - embed.description = f"**Type:** {str.title(case_dict['moderation_type'])}\n**Target:** {target_name} ({target_user['id']})\n**Moderator:** {moderator_name} ({moderator_user['id']})\n**Resolved:** {bool(case_dict['resolved'])}\n**Timestamp:** | " + embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Resolved:** {moderation.resolved}\n**Timestamp:** | " - if case_dict["duration"] != "NULL": - td = timedelta( - **{ - unit: int(val) - for unit, val in zip( - ["hours", "minutes", "seconds"], case_dict["duration"].split(":") - ) - } - ) + if moderation.duration: duration_embed = ( - f"{humanize_timedelta(timedelta=td)} | " - if bool(case_dict["expired"]) is False - else str(humanize_timedelta(timedelta=td)) + f"{humanize_timedelta(timedelta=moderation.duration)} | " + if moderation.expired is False + else str(humanize_timedelta(timedelta=moderation.duration)) ) - embed.description += f"\n**Duration:** {duration_embed}\n**Expired:** {bool(case_dict['expired'])}" + embed.description += f"\n**Duration:** {duration_embed}\n**Expired:** {moderation.expired}" embed.description += ( - f"\n**Changes:** {len(case_dict['changes']) - 1}" - if case_dict["changes"] + f"\n**Changes:** {len(moderation.changes) - 1}" + if moderation.changes else "\n**Changes:** 0" ) - if case_dict["role_id"]: - embed.description += f"\n**Role:** <@&{case_dict['role_id']}>" + if moderation.role_id: + role = await moderation.get_role() + embed.description += f"\n**Role:** {role.name}" - if case_dict["metadata"]: - if case_dict["metadata"]["imported_from"]: + if moderation.metadata: + if moderation.metadata["imported_from"]: embed.description += ( - f"\n**Imported From:** {case_dict['metadata']['imported_from']}" + f"\n**Imported From:** {moderation.metadata['imported_from']}" + ) + if moderation.metadata["imported_timestamp"]: + embed.description += ( + f"\n**Imported Timestamp:** | " ) - embed.add_field(name="Reason", value=box(case_dict["reason"]), inline=False) + embed.add_field(name="Reason", value=box(moderation.reason), inline=False) - if case_dict["resolved"] == 1: - resolved_user = await fetch_user_dict(interaction.client, case_dict["resolved_by"]) - resolved_name = ( - f"`{resolved_user['name']}`" - if resolved_user["discriminator"] == "0" - else f"`{resolved_user['name']}#{resolved_user['discriminator']}`" - ) + if moderation.resolved: + resolved_user = await moderation.get_resolved_by() embed.add_field( name="Resolve Reason", - value=f"Resolved by {resolved_name} ({resolved_user['id']}) for:\n{box(case_dict['resolve_reason'])}", + value=f"Resolved by {resolved_user.name} ({resolved_user.id}) for:\n{box(moderation.resolve_reason)}", inline=False, ) -- 2.45.3 From e7e8d60f3b56d33baead9915aa70a52b4c827453 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 17:48:08 -0400 Subject: [PATCH 027/376] feat(aurora): added a new object for Changes --- aurora/models.py | 23 ++++++++++++++++++++++- aurora/utilities/factory.py | 22 +++++++++------------- aurora/utilities/utils.py | 11 ++++++++++- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 2561267..6fd3862 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,5 +1,5 @@ from datetime import datetime, timedelta -from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Any, ClassVar, Dict, List, Literal, Optional, Union from discord import Forbidden, HTTPException, InvalidData, NotFound from pydantic import BaseModel @@ -10,6 +10,11 @@ from aurora.utilities.utils import generate_dict class AuroraBaseModel(BaseModel): """Base class for all models in Aurora.""" + + def to_json(self, indent: int = None, file: Any = None, **kwargs): + from aurora.utilities.json import dump, dumps + return dump(self.model_dump(), file, indent=indent, **kwargs) if file else dumps(self.model_dump(), indent=indent, **kwargs) + class Moderation(AuroraBaseModel): bot: ClassVar[Red] moderation_id: int @@ -86,6 +91,21 @@ class Moderation(AuroraBaseModel): return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) +class Change(AuroraBaseModel): + type: Literal["ORIGINAL", "RESOLVE", "EDIT"] + timestamp: datetime + reason: str + user_id: int + duration: Optional[timedelta] + end_timestamp: Optional[datetime] + + def __str__(self): + return f"{self.type} {self.user_id} {self.reason}" + + @classmethod + def from_dict(cls, data: dict) -> "Change": + return cls(**data) + class PartialUser(AuroraBaseModel): id: int username: str @@ -108,6 +128,7 @@ class PartialUser(AuroraBaseModel): except NotFound: return cls(id=user_id, username="Deleted User", discriminator=0) + class PartialChannel(AuroraBaseModel): id: int name: str diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 09d9dd3..823f05c 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -2,17 +2,13 @@ from datetime import datetime, timedelta from typing import Union -from discord import (Color, Embed, Guild, Interaction, InteractionMessage, - Member, Role, User) +from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User from redbot.core import commands -from redbot.core.utils.chat_formatting import (bold, box, error, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning from aurora.models import Moderation from aurora.utilities.config import config -from aurora.utilities.utils import (fetch_channel_dict, fetch_user_dict, - get_bool_emoji, get_next_case_number, - get_pagesize_str) +from aurora.utilities.utils import fetch_channel_dict, fetch_user_dict, get_bool_emoji, get_next_case_number, get_pagesize_str async def message_factory( @@ -212,22 +208,22 @@ async def case_factory(interaction: Interaction, moderation: Moderation) -> Embe return embed -async def changes_factory(interaction: Interaction, case_dict: dict) -> Embed: +async def changes_factory(interaction: Interaction, moderation: Moderation) -> Embed: """This function creates a changes embed from set parameters. Args: - interaction (Interaction): The interaction object. - case_dict (dict): The case dictionary. + interaction (discord.Interaction): The interaction object. + moderation (aurora.models.Moderation): The moderation object. """ embed = Embed( - title=f"📕 Case #{case_dict['moderation_id']:,} Changes", + title=f"📕 Case #{moderation.id:,} Changes", color=await interaction.client.get_embed_color(interaction.channel), ) memory_dict = {} - if case_dict["changes"]: - for change in case_dict["changes"]: + if moderation.changes: + for change in moderation.changes: if change["user_id"] not in memory_dict: memory_dict[str(change["user_id"])] = await fetch_user_dict( interaction.client, change["user_id"] diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 3761543..5f7de72 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -9,9 +9,11 @@ from discord.errors import Forbidden, NotFound from redbot.core import commands, data_manager from redbot.core.utils.chat_formatting import error +from aurora.models import Change from aurora.utilities.config import config + def check_permissions( user: User, permissions: list, @@ -130,6 +132,13 @@ def generate_dict(result: dict, guild_id: int) -> dict: duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) else: duration = None + + if result[14] is not None: + changes = json.loads(result[14].strip('"').replace('\\"', '"')) + change_obj_list = [] + for change in changes: + change_obj_list.append(Change(**change)) + case = { "moderation_id": int(result[0]), "guild_id": int(guild_id), @@ -146,7 +155,7 @@ def generate_dict(result: dict, guild_id: int) -> dict: "resolved_by": result[11], "resolve_reason": result[12], "expired": bool(result[13]), - "changes": json.loads(result[14].strip('"').replace('\\"', '"')) if result[14] else [], + "changes": change_obj_list if result[14] else [], "metadata": json.loads(result[15].strip('"').replace('\\"', '"')) if result[15] else {}, } return case -- 2.45.3 From e46612dc08a75db8fe789243b3c77a58793a9688 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 17:49:01 -0400 Subject: [PATCH 028/376] fix(aurora): fixed a circular import --- aurora/utilities/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 5f7de72..874ade3 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -9,11 +9,9 @@ from discord.errors import Forbidden, NotFound from redbot.core import commands, data_manager from redbot.core.utils.chat_formatting import error -from aurora.models import Change from aurora.utilities.config import config - def check_permissions( user: User, permissions: list, @@ -127,6 +125,7 @@ async def get_next_case_number(guild_id: str, cursor=None) -> int: def generate_dict(result: dict, guild_id: int) -> dict: + from aurora.models import Change if result[7] is not None: hours, minutes, seconds = map(int, result[7].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) -- 2.45.3 From 39479eb216bac3e9c0f9201ccd5ab6cffa95dbe2 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:05:20 -0400 Subject: [PATCH 029/376] fix(aurora): fixing up some model stuff --- aurora/models.py | 61 +++++++++++++++++++-------------------- aurora/utilities/utils.py | 5 ++-- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 6fd3862..c21ff4c 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -10,29 +10,29 @@ from aurora.utilities.utils import generate_dict class AuroraBaseModel(BaseModel): """Base class for all models in Aurora.""" + bot: ClassVar[Red] + guild_id: int def to_json(self, indent: int = None, file: Any = None, **kwargs): from aurora.utilities.json import dump, dumps - return dump(self.model_dump(), file, indent=indent, **kwargs) if file else dumps(self.model_dump(), indent=indent, **kwargs) + return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) class Moderation(AuroraBaseModel): - bot: ClassVar[Red] moderation_id: int - guild_id: int timestamp: datetime moderation_type: str target_type: str target_id: int moderator_id: int - role_id: Optional[int] - duration: Optional[timedelta] - end_timestamp: Optional[datetime] - reason: Optional[str] + role_id: Optional[int] = None + duration: Optional[timedelta] = None + end_timestamp: Optional[datetime] = None + reason: Optional[str] = None resolved: bool - resolved_by: Optional[int] - resolve_reason: Optional[str] + resolved_by: Optional[int] = None + resolve_reason: Optional[str] = None expired: bool - changes: List[Dict] + changes: List["Change"] metadata: Dict @property @@ -76,7 +76,7 @@ class Moderation(AuroraBaseModel): result = cursor.fetchone() if result: - case = generate_dict(result, guild_id) + case = generate_dict(bot, result, guild_id) cursor.close() return cls.from_dict(bot, case) @@ -86,25 +86,23 @@ class Moderation(AuroraBaseModel): def from_dict(cls, bot: Red, data: dict) -> "Moderation": return cls(bot=bot, **data) - def to_json(self, indent: int = None, file: Any = None, **kwargs): - from aurora.utilities.json import dump, dumps - return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) - - class Change(AuroraBaseModel): type: Literal["ORIGINAL", "RESOLVE", "EDIT"] timestamp: datetime reason: str user_id: int - duration: Optional[timedelta] - end_timestamp: Optional[datetime] + duration: Optional[timedelta] = None + end_timestamp: Optional[datetime] = None def __str__(self): return f"{self.type} {self.user_id} {self.reason}" + async def get_user(self) -> "PartialUser": + return await PartialUser.from_id(self.bot, self.user_id) + @classmethod - def from_dict(cls, data: dict) -> "Change": - return cls(**data) + def from_dict(cls, bot: Red, data: dict) -> "Change": + return cls(bot=bot, **data) class PartialUser(AuroraBaseModel): id: int @@ -124,9 +122,9 @@ class PartialUser(AuroraBaseModel): if not user: try: user = await bot.fetch_user(user_id) - return cls(id=user.id, username=user.name, discriminator=user.discriminator) + return cls(bot=bot, guild_id=0, id=user.id, username=user.name, discriminator=user.discriminator) except NotFound: - return cls(id=user_id, username="Deleted User", discriminator=0) + return cls(bot=bot, guild_id=0, id=user_id, username="Deleted User", discriminator=0) class PartialChannel(AuroraBaseModel): @@ -144,19 +142,18 @@ class PartialChannel(AuroraBaseModel): @classmethod async def from_id(cls, bot: Red, channel_id: int) -> "PartialChannel": - user = bot.get_channel(channel_id) - if not user: + channel = bot.get_channel(channel_id) + if not channel: try: - user = await bot.fetch_channel(channel_id) - return cls(id=user.id, username=user.name, discriminator=user.discriminator) + channel = await bot.fetch_channel(channel_id) + return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, username=channel.name) except (NotFound, InvalidData, HTTPException, Forbidden) as e: if e == Forbidden: - return cls(id=channel_id, name="Forbidden Channel") - return cls(id=channel_id, name="Deleted Channel") + return cls(bot=bot, guild_id=0, id=channel_id, name="Forbidden Channel") + return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel") class PartialRole(AuroraBaseModel): id: int - guild_id: int name: str @property @@ -171,8 +168,8 @@ class PartialRole(AuroraBaseModel): try: guild = await bot.fetch_guild(guild_id, with_counts=False) except (Forbidden, HTTPException): - return cls(id=role_id, guild_id=guild_id, name="Forbidden Role") + return cls(bot=bot, guild_id=guild_id, id=role_id, name="Forbidden Role") role = guild.get_role(role_id) if not role: - return cls(id=role_id, guild_id=guild_id, name="Deleted Role") - return cls(id=role.id, guild_id=guild_id, name=role.name) + return cls(bot=bot, guild_id=guild_id, id=role_id, name="Deleted Role") + return cls(bot=bot, guild_id=guild_id, id=role.id, name=role.name) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 874ade3..f6e69bf 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -7,6 +7,7 @@ from dateutil.relativedelta import relativedelta as rd from discord import File, Guild, Interaction, Member, SelectOption, User from discord.errors import Forbidden, NotFound from redbot.core import commands, data_manager +from redbot.core.bot import Red from redbot.core.utils.chat_formatting import error from aurora.utilities.config import config @@ -124,7 +125,7 @@ async def get_next_case_number(guild_id: str, cursor=None) -> int: return (result[0] + 1) if result else 1 -def generate_dict(result: dict, guild_id: int) -> dict: +def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: from aurora.models import Change if result[7] is not None: hours, minutes, seconds = map(int, result[7].split(':')) @@ -136,7 +137,7 @@ def generate_dict(result: dict, guild_id: int) -> dict: changes = json.loads(result[14].strip('"').replace('\\"', '"')) change_obj_list = [] for change in changes: - change_obj_list.append(Change(**change)) + change_obj_list.append(Change.from_dict(bot=bot, **change)) case = { "moderation_id": int(result[0]), -- 2.45.3 From b752181781aa497360e2c0887e9499a0abce1835 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:06:23 -0400 Subject: [PATCH 030/376] fix(aurora): oops lol --- aurora/utilities/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index f6e69bf..b15a865 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -137,7 +137,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: changes = json.loads(result[14].strip('"').replace('\\"', '"')) change_obj_list = [] for change in changes: - change_obj_list.append(Change.from_dict(bot=bot, **change)) + change_obj_list.append(Change.from_dict(bot=bot, data=change)) case = { "moderation_id": int(result[0]), -- 2.45.3 From 1313834ea51ff21232a3d83f387fcf4db7b68311 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:07:29 -0400 Subject: [PATCH 031/376] fix(aurora): fixed a pydantic error --- aurora/models.py | 2 +- aurora/utilities/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index c21ff4c..c3ef428 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -101,7 +101,7 @@ class Change(AuroraBaseModel): return await PartialUser.from_id(self.bot, self.user_id) @classmethod - def from_dict(cls, bot: Red, data: dict) -> "Change": + def from_dict(cls, bot: Red, guild_id: int, data: dict) -> "Change": return cls(bot=bot, **data) class PartialUser(AuroraBaseModel): diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index b15a865..71e57ff 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -137,7 +137,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: changes = json.loads(result[14].strip('"').replace('\\"', '"')) change_obj_list = [] for change in changes: - change_obj_list.append(Change.from_dict(bot=bot, data=change)) + change_obj_list.append(Change.from_dict(bot=bot, guild_id=guild_id, data=change)) case = { "moderation_id": int(result[0]), -- 2.45.3 From 74a098341932e83cca96000e2c4a07945b8f4b4a Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:08:27 -0400 Subject: [PATCH 032/376] fix(aurora): fixed a missing kwarg in a model initialization function --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index c3ef428..3fbd6dd 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -102,7 +102,7 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, guild_id: int, data: dict) -> "Change": - return cls(bot=bot, **data) + return cls(bot=bot, guild_id=guild_id, **data) class PartialUser(AuroraBaseModel): id: int -- 2.45.3 From 356d58f9d7247cd07d51d42c8eaf5a2fdc910aae Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:09:06 -0400 Subject: [PATCH 033/376] fix(aurora): changed the jsonencoder --- aurora/utilities/json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index e8678af..aad7be7 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -11,7 +11,7 @@ class JSONEncoder(json.JSONEncoder): if isinstance(o, timedelta): return str(o) if isinstance(o, AuroraBaseModel): - return o.model_dump() + return o.to_json() return super().default(o) -- 2.45.3 From d70f2bf5f1eac1300e0278f891512de9aa2209cb Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:17:21 -0400 Subject: [PATCH 034/376] fix(aurora): fixed guild ids appearing in changes --- aurora/models.py | 25 ++++++++++++++++--------- aurora/utilities/utils.py | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 3fbd6dd..012eaaf 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -11,13 +11,20 @@ from aurora.utilities.utils import generate_dict class AuroraBaseModel(BaseModel): """Base class for all models in Aurora.""" bot: ClassVar[Red] + + def to_json(self, indent: int = None, file: Any = None, **kwargs): + from aurora.utilities.json import dump, dumps + return dump(self.model_dump(exclude={"bot"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) + +class AuroraGuildModel(AuroraBaseModel): + """Subclass of AuroraBaseModel that includes a guild_id attribute, and a modified to_json() method to match.""" guild_id: int def to_json(self, indent: int = None, file: Any = None, **kwargs): from aurora.utilities.json import dump, dumps return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) -class Moderation(AuroraBaseModel): +class Moderation(AuroraGuildModel): moderation_id: int timestamp: datetime moderation_type: str @@ -101,8 +108,8 @@ class Change(AuroraBaseModel): return await PartialUser.from_id(self.bot, self.user_id) @classmethod - def from_dict(cls, bot: Red, guild_id: int, data: dict) -> "Change": - return cls(bot=bot, guild_id=guild_id, **data) + def from_dict(cls, bot: Red, data: dict) -> "Change": + return cls(bot=bot **data) class PartialUser(AuroraBaseModel): id: int @@ -122,12 +129,12 @@ class PartialUser(AuroraBaseModel): if not user: try: user = await bot.fetch_user(user_id) - return cls(bot=bot, guild_id=0, id=user.id, username=user.name, discriminator=user.discriminator) + return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator) except NotFound: - return cls(bot=bot, guild_id=0, id=user_id, username="Deleted User", discriminator=0) + return cls(bot=bot, id=user_id, username="Deleted User", discriminator=0) -class PartialChannel(AuroraBaseModel): +class PartialChannel(AuroraGuildModel): id: int name: str @@ -149,10 +156,10 @@ class PartialChannel(AuroraBaseModel): return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, username=channel.name) except (NotFound, InvalidData, HTTPException, Forbidden) as e: if e == Forbidden: - return cls(bot=bot, guild_id=0, id=channel_id, name="Forbidden Channel") - return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel") + return cls(bot=bot, guild_id=None, id=channel_id, name="Forbidden Channel") + return cls(bot=bot, guild_id=None, id=channel_id, name="Deleted Channel") -class PartialRole(AuroraBaseModel): +class PartialRole(AuroraGuildModel): id: int name: str diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 71e57ff..b15a865 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -137,7 +137,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: changes = json.loads(result[14].strip('"').replace('\\"', '"')) change_obj_list = [] for change in changes: - change_obj_list.append(Change.from_dict(bot=bot, guild_id=guild_id, data=change)) + change_obj_list.append(Change.from_dict(bot=bot, data=change)) case = { "moderation_id": int(result[0]), -- 2.45.3 From ea280c2d62b280abefb995d6a78309bd199bea94 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:18:57 -0400 Subject: [PATCH 035/376] fix(aurora): fixed a syntax error --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 012eaaf..f0b8590 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -109,7 +109,7 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Change": - return cls(bot=bot **data) + return cls(bot=bot, **data) class PartialUser(AuroraBaseModel): id: int -- 2.45.3 From 6520f4f2b91ffb12530b9cd493d7346825b42970 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:22:42 -0400 Subject: [PATCH 036/376] fix(aurora): don't inherit from AuroraBaseModel --- aurora/models.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index f0b8590..c90d674 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -16,8 +16,9 @@ class AuroraBaseModel(BaseModel): from aurora.utilities.json import dump, dumps return dump(self.model_dump(exclude={"bot"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) -class AuroraGuildModel(AuroraBaseModel): - """Subclass of AuroraBaseModel that includes a guild_id attribute, and a modified to_json() method to match.""" +class AuroraGuildModel(BaseModel): + """Base class that includes a guild_id attribute, and a modified to_json() method to match.""" + bot: ClassVar[Red] guild_id: int def to_json(self, indent: int = None, file: Any = None, **kwargs): -- 2.45.3 From a7d8f452d11ca8a4fa52021b073c98891ad2fd32 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:23:24 -0400 Subject: [PATCH 037/376] fix(aurora): updated utilities.json.JSONEncoder to match the model change I just made --- aurora/utilities/json.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index aad7be7..7052f90 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -1,7 +1,7 @@ import json from datetime import datetime, timedelta -from aurora.models import AuroraBaseModel +from aurora.models import AuroraBaseModel, AuroraGuildModel class JSONEncoder(json.JSONEncoder): @@ -12,6 +12,8 @@ class JSONEncoder(json.JSONEncoder): return str(o) if isinstance(o, AuroraBaseModel): return o.to_json() + if isinstance(o, AuroraGuildModel): + return o.to_json() return super().default(o) -- 2.45.3 From 6a7758e8f933c29b56943f2f91c994a2729e4ee4 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:27:12 -0400 Subject: [PATCH 038/376] fix(aurora): reverted previous change, instead using pydantic's ConfigDicts to resolve the error I was encountering previously --- aurora/models.py | 12 ++++++------ aurora/utilities/factory.py | 10 +++++++--- aurora/utilities/json.py | 4 +--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index c90d674..a50aba8 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,8 +1,8 @@ from datetime import datetime, timedelta -from typing import Any, ClassVar, Dict, List, Literal, Optional, Union +from typing import Any, Dict, List, Literal, Optional, Union from discord import Forbidden, HTTPException, InvalidData, NotFound -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict from redbot.core.bot import Red from aurora.utilities.utils import generate_dict @@ -10,15 +10,15 @@ from aurora.utilities.utils import generate_dict class AuroraBaseModel(BaseModel): """Base class for all models in Aurora.""" - bot: ClassVar[Red] + model_config = ConfigDict(ignored_types=(Red,)) + bot: Red def to_json(self, indent: int = None, file: Any = None, **kwargs): from aurora.utilities.json import dump, dumps return dump(self.model_dump(exclude={"bot"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) -class AuroraGuildModel(BaseModel): - """Base class that includes a guild_id attribute, and a modified to_json() method to match.""" - bot: ClassVar[Red] +class AuroraGuildModel(AuroraBaseModel): + """Subclass of AuroraBaseModel that includes a guild_id attribute, and a modified to_json() method to match.""" guild_id: int def to_json(self, indent: int = None, file: Any = None, **kwargs): diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 823f05c..fdc4126 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -2,13 +2,17 @@ from datetime import datetime, timedelta from typing import Union -from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User +from discord import (Color, Embed, Guild, Interaction, InteractionMessage, + Member, Role, User) from redbot.core import commands -from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (bold, box, error, + humanize_timedelta, warning) from aurora.models import Moderation from aurora.utilities.config import config -from aurora.utilities.utils import fetch_channel_dict, fetch_user_dict, get_bool_emoji, get_next_case_number, get_pagesize_str +from aurora.utilities.utils import (fetch_channel_dict, fetch_user_dict, + get_bool_emoji, get_next_case_number, + get_pagesize_str) async def message_factory( diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index 7052f90..aad7be7 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -1,7 +1,7 @@ import json from datetime import datetime, timedelta -from aurora.models import AuroraBaseModel, AuroraGuildModel +from aurora.models import AuroraBaseModel class JSONEncoder(json.JSONEncoder): @@ -12,8 +12,6 @@ class JSONEncoder(json.JSONEncoder): return str(o) if isinstance(o, AuroraBaseModel): return o.to_json() - if isinstance(o, AuroraGuildModel): - return o.to_json() return super().default(o) -- 2.45.3 From a22de1d2c2b344577400eb12e486b68bece42f30 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 18:28:03 -0400 Subject: [PATCH 039/376] fix(aurora): fixed another pydantic error --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index a50aba8..2c74015 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -10,7 +10,7 @@ from aurora.utilities.utils import generate_dict class AuroraBaseModel(BaseModel): """Base class for all models in Aurora.""" - model_config = ConfigDict(ignored_types=(Red,)) + model_config = ConfigDict(ignored_types=(Red,), arbitrary_types_allowed=True) bot: Red def to_json(self, indent: int = None, file: Any = None, **kwargs): -- 2.45.3 From 3f6aec0a82d05c648750c8936b0ad6af3fd0caa8 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 20:55:11 -0400 Subject: [PATCH 040/376] fix(aurora): don't JSON serialize the Red class --- aurora/utilities/json.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index aad7be7..cad264e 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -1,6 +1,9 @@ import json from datetime import datetime, timedelta +from redbot.core.bot import Red + + from aurora.models import AuroraBaseModel @@ -12,6 +15,8 @@ class JSONEncoder(json.JSONEncoder): return str(o) if isinstance(o, AuroraBaseModel): return o.to_json() + if isinstance(o, Red): + return None return super().default(o) -- 2.45.3 From 0b31e70089b7698668d355805f5e77ba5d98bc3c Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 20:59:23 -0400 Subject: [PATCH 041/376] fix(aurora): fixed a conditional statement and a pydantic issue --- aurora/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 2c74015..be0c0e2 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -55,7 +55,7 @@ class Moderation(AuroraGuildModel): return await PartialUser.from_id(self.bot, self.moderator_id) async def get_target(self) -> Union["PartialUser", "PartialChannel"]: - if self.target_type == "user": + if self.target_type == "USER": return await PartialUser.from_id(self.bot, self.target_id) else: return await PartialChannel.from_id(self.bot, self.target_id) @@ -157,8 +157,8 @@ class PartialChannel(AuroraGuildModel): return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, username=channel.name) except (NotFound, InvalidData, HTTPException, Forbidden) as e: if e == Forbidden: - return cls(bot=bot, guild_id=None, id=channel_id, name="Forbidden Channel") - return cls(bot=bot, guild_id=None, id=channel_id, name="Deleted Channel") + return cls(bot=bot, guild_id=0, id=channel_id, name="Forbidden Channel") + return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel") class PartialRole(AuroraGuildModel): id: int -- 2.45.3 From 23eba46948b1ee96f6dc0768c4af38e7991a9b84 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 21:02:18 -0400 Subject: [PATCH 042/376] fix(aurora): fix a few classmethods returning None instead of their constructed classes --- aurora/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aurora/models.py b/aurora/models.py index be0c0e2..b336d3a 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -133,6 +133,7 @@ class PartialUser(AuroraBaseModel): return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator) except NotFound: return cls(bot=bot, id=user_id, username="Deleted User", discriminator=0) + return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator) class PartialChannel(AuroraGuildModel): @@ -159,6 +160,7 @@ class PartialChannel(AuroraGuildModel): if e == Forbidden: return cls(bot=bot, guild_id=0, id=channel_id, name="Forbidden Channel") return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel") + return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, username=channel.name) class PartialRole(AuroraGuildModel): id: int -- 2.45.3 From 50c2db80d9f3df344399d9ea0477ca04fcb5d759 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 21:06:29 -0400 Subject: [PATCH 043/376] fix(aurora): convert datetimes to unix timestamps --- aurora/models.py | 4 ++++ aurora/utilities/factory.py | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index b336d3a..ab8bd3d 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -51,6 +51,10 @@ class Moderation(AuroraGuildModel): def type(self) -> str: return self.moderation_type + @property + def unix_timestamp(self) -> int: + return int(self.timestamp.timestamp()) + async def get_moderator(self) -> "PartialUser": return await PartialUser.from_id(self.bot, self.moderator_id) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index fdc4126..63e8f03 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -117,7 +117,7 @@ async def log_factory( ) resolved_by = await moderation.get_resolved_by() - embed.description = f"**Type:** {str.title(moderation.moderation_type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " + embed.description = f"**Type:** {str.title(moderation.moderation_type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " if moderation.duration is not None: duration_embed = ( @@ -143,12 +143,12 @@ async def log_factory( title=f"📕 Case #{moderation.id:,}", color=await interaction.client.get_embed_color(interaction.channel), ) - embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " + embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " if moderation.duration: embed.description = ( embed.description - + f"\n**Duration:** {humanize_timedelta(timedelta=moderation.duration)} | " + + f"\n**Duration:** {humanize_timedelta(timedelta=moderation.duration)} | " ) embed.add_field(name="Reason", value=box(moderation.reason), inline=False) @@ -169,11 +169,11 @@ async def case_factory(interaction: Interaction, moderation: Moderation) -> Embe title=f"📕 Case #{moderation.id:,}", color=await interaction.client.get_embed_color(interaction.channel), ) - embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Resolved:** {moderation.resolved}\n**Timestamp:** | " + embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Resolved:** {moderation.resolved}\n**Timestamp:** | " if moderation.duration: duration_embed = ( - f"{humanize_timedelta(timedelta=moderation.duration)} | " + f"{humanize_timedelta(timedelta=moderation.duration)} | " if moderation.expired is False else str(humanize_timedelta(timedelta=moderation.duration)) ) -- 2.45.3 From ee331b7544c6f937687e31cceb01f39e28c4ca6f Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 21:07:37 -0400 Subject: [PATCH 044/376] fix(aurora): fixed an incorrect conditional statement resulting in unintended behavior --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index ab8bd3d..069bc40 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -123,7 +123,7 @@ class PartialUser(AuroraBaseModel): @property def name(self): - return f"{self.username}#{self.discriminator}" if self.discriminator == 0 else self.username + return f"{self.username}#{self.discriminator}" if self.discriminator != 0 else self.username def __str__(self): return self.name -- 2.45.3 From 94f6d6c3b588cc7de63b533d1f1773106d4717df Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 21:15:39 -0400 Subject: [PATCH 045/376] fix(aurora): fixed the changes_factory --- aurora/models.py | 14 ++++++++++++++ aurora/utilities/factory.py | 38 ++++++++++++++----------------------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 069bc40..a7b81a7 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -106,6 +106,10 @@ class Change(AuroraBaseModel): duration: Optional[timedelta] = None end_timestamp: Optional[datetime] = None + @property + def unix_timestamp(self) -> int: + return int(self.timestamp.timestamp()) + def __str__(self): return f"{self.type} {self.user_id} {self.reason}" @@ -114,6 +118,16 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Change": + if data["duration"] is not None: + hours, minutes, seconds = map(int, data["duration"].split(':')) + duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) + else: + duration = None + data.update({ + "timestamp": datetime.fromtimestamp(data["timestamp"]), + "end_timestamp": datetime.fromtimestamp(data["end_timestamp"]) if data["end_timestamp"] else None, + "duration": duration + }) return cls(bot=bot, **data) class PartialUser(AuroraBaseModel): diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 63e8f03..4a0945e 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -2,17 +2,13 @@ from datetime import datetime, timedelta from typing import Union -from discord import (Color, Embed, Guild, Interaction, InteractionMessage, - Member, Role, User) +from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User from redbot.core import commands -from redbot.core.utils.chat_formatting import (bold, box, error, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning from aurora.models import Moderation from aurora.utilities.config import config -from aurora.utilities.utils import (fetch_channel_dict, fetch_user_dict, - get_bool_emoji, get_next_case_number, - get_pagesize_str) +from aurora.utilities.utils import fetch_channel_dict, fetch_user_dict, get_bool_emoji, get_next_case_number, get_pagesize_str async def message_factory( @@ -228,38 +224,32 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E if moderation.changes: for change in moderation.changes: - if change["user_id"] not in memory_dict: - memory_dict[str(change["user_id"])] = await fetch_user_dict( - interaction.client, change["user_id"] - ) + if change.user_id not in memory_dict: + memory_dict[str(change.user_id)] = await change.get_user() - user = memory_dict[str(change["user_id"])] - name = ( - user["name"] - if user["discriminator"] == "0" - else f"{user['name']}#{user['discriminator']}" - ) + user = memory_dict[str(change.user_id)] + name = user["name"] - timestamp = f" | " + timestamp = f" | " - if change["type"] == "ORIGINAL": + if change.type == "ORIGINAL": embed.add_field( name="Original", - value=f"**User:** `{name}` ({user['id']})\n**Reason:** {change['reason']}\n**Timestamp:** {timestamp}", + value=f"**User:** `{name}` ({user['id']})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", inline=False, ) - elif change["type"] == "EDIT": + elif change.type == "EDIT": embed.add_field( name="Edit", - value=f"**User:** `{name}` ({user['id']})\n**Reason:** {change['reason']}\n**Timestamp:** {timestamp}", + value=f"**User:** `{name}` ({user['id']})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", inline=False, ) - elif change["type"] == "RESOLVE": + elif change.type == "RESOLVE": embed.add_field( name="Resolve", - value=f"**User:** `{name}` ({user['id']})\n**Reason:** {change['reason']}\n**Timestamp:** {timestamp}", + value=f"**User:** `{name}` ({user['id']})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", inline=False, ) -- 2.45.3 From 6eeab9ed96ae1f1fd2c92e7d4b2745ea287aa060 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 21:17:03 -0400 Subject: [PATCH 046/376] fix(aurora): fixed a keyerror --- aurora/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index a7b81a7..f00f0b5 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -118,14 +118,14 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Change": - if data["duration"] is not None: + if "duration" in data and data["duration"] is not None: hours, minutes, seconds = map(int, data["duration"].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) else: duration = None data.update({ "timestamp": datetime.fromtimestamp(data["timestamp"]), - "end_timestamp": datetime.fromtimestamp(data["end_timestamp"]) if data["end_timestamp"] else None, + "end_timestamp": datetime.fromtimestamp(data["end_timestamp"]) if "end_timestamp" in data and data["end_timestamp"] else None, "duration": duration }) return cls(bot=bot, **data) -- 2.45.3 From a8414a7918c5da3878d7ba2e7491c6144808a5f0 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 21:19:06 -0400 Subject: [PATCH 047/376] fix(aurora): fixed some subscripting errors in changes_factory --- aurora/utilities/factory.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 4a0945e..4d15092 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -2,13 +2,17 @@ from datetime import datetime, timedelta from typing import Union -from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User +from discord import (Color, Embed, Guild, Interaction, InteractionMessage, + Member, Role, User) from redbot.core import commands -from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (bold, box, error, + humanize_timedelta, warning) -from aurora.models import Moderation +from aurora.models import Moderation, PartialUser from aurora.utilities.config import config -from aurora.utilities.utils import fetch_channel_dict, fetch_user_dict, get_bool_emoji, get_next_case_number, get_pagesize_str +from aurora.utilities.utils import (fetch_channel_dict, fetch_user_dict, + get_bool_emoji, get_next_case_number, + get_pagesize_str) async def message_factory( @@ -227,29 +231,28 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E if change.user_id not in memory_dict: memory_dict[str(change.user_id)] = await change.get_user() - user = memory_dict[str(change.user_id)] - name = user["name"] + user: PartialUser = memory_dict[str(change.user_id)] timestamp = f" | " if change.type == "ORIGINAL": embed.add_field( name="Original", - value=f"**User:** `{name}` ({user['id']})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", + value=f"**User:** `{user.name}` ({user.id})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", inline=False, ) elif change.type == "EDIT": embed.add_field( name="Edit", - value=f"**User:** `{name}` ({user['id']})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", + value=f"**User:** `{user.name}` ({user.id})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", inline=False, ) elif change.type == "RESOLVE": embed.add_field( name="Resolve", - value=f"**User:** `{name}` ({user['id']})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", + value=f"**User:** `{user.name}` ({user.id})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", inline=False, ) -- 2.45.3 From e89db3de5a7334327f32de6353e8f9bb87b2d975 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 21:20:05 -0400 Subject: [PATCH 048/376] misc(aurora): added some markdown formatting --- aurora/utilities/factory.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 4d15092..83bd7f1 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -2,17 +2,13 @@ from datetime import datetime, timedelta from typing import Union -from discord import (Color, Embed, Guild, Interaction, InteractionMessage, - Member, Role, User) +from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User from redbot.core import commands -from redbot.core.utils.chat_formatting import (bold, box, error, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning from aurora.models import Moderation, PartialUser from aurora.utilities.config import config -from aurora.utilities.utils import (fetch_channel_dict, fetch_user_dict, - get_bool_emoji, get_next_case_number, - get_pagesize_str) +from aurora.utilities.utils import fetch_channel_dict, fetch_user_dict, get_bool_emoji, get_next_case_number, get_pagesize_str async def message_factory( @@ -169,7 +165,7 @@ async def case_factory(interaction: Interaction, moderation: Moderation) -> Embe title=f"📕 Case #{moderation.id:,}", color=await interaction.client.get_embed_color(interaction.channel), ) - embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Resolved:** {moderation.resolved}\n**Timestamp:** | " + embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** `{target.name}` ({target.id})\n**Moderator:** `{moderator.name}` ({moderator.id})\n**Resolved:** {moderation.resolved}\n**Timestamp:** | " if moderation.duration: duration_embed = ( @@ -205,7 +201,7 @@ async def case_factory(interaction: Interaction, moderation: Moderation) -> Embe resolved_user = await moderation.get_resolved_by() embed.add_field( name="Resolve Reason", - value=f"Resolved by {resolved_user.name} ({resolved_user.id}) for:\n{box(moderation.resolve_reason)}", + value=f"Resolved by `{resolved_user.name}` ({resolved_user.id}) for:\n{box(moderation.resolve_reason)}", inline=False, ) -- 2.45.3 From fc15b434c7829efa30387bc3c1ae950744f12b6b Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 21:24:37 -0400 Subject: [PATCH 049/376] feat(aurora): finished the factory migrations --- aurora/utilities/factory.py | 45 +++++++++++++------------------------ 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 83bd7f1..5977f26 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -2,13 +2,16 @@ from datetime import datetime, timedelta from typing import Union -from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User +from discord import (Color, Embed, Guild, Interaction, InteractionMessage, + Member, Role, User) from redbot.core import commands -from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (bold, box, error, + humanize_timedelta, warning) from aurora.models import Moderation, PartialUser from aurora.utilities.config import config -from aurora.utilities.utils import fetch_channel_dict, fetch_user_dict, get_bool_emoji, get_next_case_number, get_pagesize_str +from aurora.utilities.utils import (get_bool_emoji, get_next_case_number, + get_pagesize_str) async def message_factory( @@ -258,40 +261,22 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E return embed -async def evidenceformat_factory(interaction: Interaction, case_dict: dict) -> str: +async def evidenceformat_factory(interaction: Interaction, moderation: Moderation) -> str: """This function creates a codeblock in evidence format from set parameters. Args: - interaction (Interaction): The interaction object. - case_dict (dict): The case dictionary. + interaction (discord.Interaction): The interaction object. + moderation (aurora.models.Moderation): The moderation object. """ - if case_dict["target_type"] == "USER": - target_user = await fetch_user_dict(interaction.client, case_dict["target_id"]) - target_name = ( - target_user["name"] - if target_user["discriminator"] == "0" - else f"{target_user['name']}#{target_user['discriminator']}" - ) + target = await moderation.get_target() + moderator = await moderation.get_moderator() - elif case_dict["target_type"] == "CHANNEL": - target_user = await fetch_channel_dict(interaction.guild, case_dict["target_id"]) - target_name = target_user["name"] + content = f"Case: {moderation.id:,} ({str.title(moderation.type)})\nTarget: {target.name} ({target.id})\nModerator: {moderator.name} ({moderator.id})" - moderator_user = await fetch_user_dict(interaction.client, case_dict["moderator_id"]) - moderator_name = ( - moderator_user["name"] - if moderator_user["discriminator"] == "0" - else f"{moderator_user['name']}#{moderator_user['discriminator']}" - ) + if moderation.duration is not None: + content += f"\nDuration: {humanize_timedelta(timedelta=moderation.duration)}" - content = f"Case: {case_dict['moderation_id']:,} ({str.title(case_dict['moderation_type'])})\nTarget: {target_name} ({target_user['id']})\nModerator: {moderator_name} ({moderator_user['id']})" - - if case_dict["duration"] != "NULL": - hours, minutes, seconds = map(int, case_dict["duration"].split(":")) - td = timedelta(hours=hours, minutes=minutes, seconds=seconds) - content += f"\nDuration: {humanize_timedelta(timedelta=td)}" - - content += f"\nReason: {case_dict['reason']}" + content += f"\nReason: {moderation.reason}" return box(content, "prolog") -- 2.45.3 From dc44e8c6de37377a320ffb4ff1a31ba00c59fbeb Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:01:32 -0400 Subject: [PATCH 050/376] feat(aurora): migrated `/edit` to the new model system --- aurora/aurora.py | 148 +++++++++++++++++++---------------------------- aurora/models.py | 31 +++++++++- 2 files changed, 86 insertions(+), 93 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 0cc9546..1572195 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -27,13 +27,13 @@ from aurora.menus.addrole import Addrole from aurora.menus.guild import Guild from aurora.menus.immune import Immune from aurora.menus.overrides import Overrides -from aurora.models import Moderation +from aurora.models import Change, Moderation from aurora.utilities.config import config, register_config from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from aurora.utilities.json import dump, dumps from aurora.utilities.logger import logger -from aurora.utilities.utils import check_moddable, check_permissions, convert_timedelta_to_str, fetch_channel_dict, fetch_user_dict, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from aurora.utilities.utils import check_moddable, check_permissions, fetch_channel_dict, fetch_user_dict, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta class Aurora(commands.Cog): @@ -1490,107 +1490,77 @@ class Aurora(commands.Cog): return if case != 0: - parsed_time = None - case_dict = await fetch_case(case, interaction.guild.id) - if case_dict: - if duration: - parsed_time = parse_timedelta(duration) - if parsed_time is None: - await interaction.response.send_message( - error("Please provide a valid duration!"), ephemeral=True - ) - return - - end_timestamp = case_dict["timestamp"] + parsed_time.total_seconds() - - if case_dict["moderation_type"] == "MUTE": - if ( - time.time() - case_dict["timestamp"] - ) + parsed_time.total_seconds() > 2419200: - await interaction.response.send_message( - error( - "Please provide a duration that is less than 28 days from the initial moderation." - ) - ) - return - - try: - member = await interaction.guild.fetch_member( - case_dict["target_id"] - ) - - await member.timeout( - parsed_time, - reason=f"Case #{case:,} edited by {interaction.user.id}", - ) - except discord.NotFound: - pass - - changes: list = case_dict["changes"] - if len(changes) > 25: - await interaction.response.send_message( + moderation = Moderation.from_sql(interaction.client, case, interaction.guild.id) + old_moderation = moderation + if moderation: + if len(moderation.changes) > 25: + return await interaction.response.send_message( content=error( "Due to limitations with Discord's embed system, you cannot edit a case more than 25 times." ), ephemeral=True, ) - return - if not changes: - changes.append( - { - "type": "ORIGINAL", - "timestamp": case_dict["timestamp"], - "reason": case_dict["reason"], - "user_id": case_dict["moderator_id"], - "duration": case_dict["duration"], - "end_timestamp": case_dict["end_timestamp"], - } - ) - if parsed_time: - changes.append( - { + if duration: + moderation.duration = parse_timedelta(duration) + if moderation.duration is None: + return await interaction.response.send_message( + error("Please provide a valid duration!"), ephemeral=True + ) + + moderation.end_timestamp = moderation.timestamp + moderation.duration.total_seconds() + + if moderation.type == "MUTE": + if ( + time.time() - moderation.unix_timestamp + ) + moderation.duration.total_seconds() > 2419200: + return await interaction.response.send_message( + error( + "Please provide a duration that is less than 28 days from the initial moderation." + ) + ) + + try: + member = await interaction.guild.fetch_member( + moderation.target_id + ) + + await member.timeout( + moderation.duration, + reason=f"Case #{case:,} edited by {interaction.user.id}", + ) + except discord.NotFound: + pass + + if not moderation.changes: + moderation.changes.append(Change.from_dict(interaction.client, { + "type": "ORIGINAL", + "timestamp": old_moderation.timestamp, + "reason": old_moderation.reason, + "user_id": old_moderation.moderator_id, + "duration": old_moderation.duration, + "end_timestamp": old_moderation.end_timestamp, + })) + if duration: + moderation.changes.append(Change.from_dict(interaction.client, { "type": "EDIT", "timestamp": int(time.time()), "reason": reason, "user_id": interaction.user.id, - "duration": convert_timedelta_to_str(parsed_time), - "end_timestamp": end_timestamp, - } - ) + "duration": moderation.duration, + "end_timestamp": moderation.end_timestamp, + })) else: - changes.append( - { + moderation.changes.append(Change.from_dict(interaction.client, { "type": "EDIT", "timestamp": int(time.time()), "reason": reason, "user_id": interaction.user.id, - "duration": case_dict["duration"], - "end_timestamp": case_dict["end_timestamp"], - } - ) + "duration": moderation.duration, + "end_timestamp": moderation.end_timestamp, + })) - database = connect() - cursor = database.cursor() - - if parsed_time: - update_query = f"UPDATE `moderation_{interaction.guild.id}` SET changes = ?, reason = ?, duration = ?, end_timestamp = ? WHERE moderation_id = ?" - cursor.execute( - update_query, - ( - dumps(changes), - reason, - convert_timedelta_to_str(parsed_time), - end_timestamp, - case, - ), - ) - else: - update_query = f"UPDATE `moderation_{interaction.guild.id}` SET changes = ?, reason = ? WHERE moderation_id = ?" - cursor.execute(update_query, (dumps(changes), reason, case)) - database.commit() - - new_case = await fetch_case(case, interaction.guild.id) - embed = await case_factory(interaction=interaction, case_dict=new_case) + moderation.update() + embed = await case_factory(interaction=interaction, moderation=moderation) await interaction.response.send_message( content=f"✅ Moderation #{case:,} edited!", @@ -1599,8 +1569,6 @@ class Aurora(commands.Cog): ) await log(interaction, case) - cursor.close() - database.close() return await interaction.response.send_message( content=error(f"No case with case number `{case}` found."), ephemeral=True diff --git a/aurora/models.py b/aurora/models.py index f00f0b5..dad4028 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -77,6 +77,16 @@ class Moderation(AuroraGuildModel): def __str__(self): return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}" + def update(self): + from aurora.utilities.database import connect + query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" + changes = [change.to_json() for change in self.changes] + + with connect() as database: + cursor = database.cursor() + cursor.execute(query, (self.timestamp, self.moderation_type, self.target_type, self.moderator_id, self.role_id, self.duration, self.end_timestamp, self.reason, self.resolved, self.resolved_by, self.resolve_reason, self.expired, changes, self.metadata, self.moderation_id)) + cursor.close() + @classmethod def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> Optional["Moderation"]: from aurora.utilities.database import connect @@ -118,14 +128,29 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Change": - if "duration" in data and data["duration"] is not None: + if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): hours, minutes, seconds = map(int, data["duration"].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) + elif duration in data and isinstance(data["duration"], timedelta): + duration = data["duration"] else: duration = None + + if "end_timestamp" in data and data["end_timestamp"] and not isinstance(data["end_timestamp"], datetime): + end_timestamp = datetime.fromtimestamp(data["end_timestamp"]) + elif "end_timestamp" in data and isinstance(data["end_timestamp"], datetime): + end_timestamp = data["end_timestamp"] + else: + end_timestamp = None + + if not isinstance(data["timestamp"], datetime): + timestamp = datetime.fromtimestamp(data["timestamp"]) + else: + timestamp = data["timestamp"] + data.update({ - "timestamp": datetime.fromtimestamp(data["timestamp"]), - "end_timestamp": datetime.fromtimestamp(data["end_timestamp"]) if "end_timestamp" in data and data["end_timestamp"] else None, + "timestamp": timestamp, + "end_timestamp": end_timestamp, "duration": duration }) return cls(bot=bot, **data) -- 2.45.3 From b03ce0424551cd63a4961eb3c16e96428e21c593 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:02:31 -0400 Subject: [PATCH 051/376] fix(aurora): fixed an unboundlocalerror in Change.from_dict() --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index dad4028..52cf3b7 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -131,7 +131,7 @@ class Change(AuroraBaseModel): if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): hours, minutes, seconds = map(int, data["duration"].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) - elif duration in data and isinstance(data["duration"], timedelta): + elif "duration" in data and isinstance(data["duration"], timedelta): duration = data["duration"] else: duration = None -- 2.45.3 From 3f8cdf2012fa094e7bbbf395b2ba4eee2afe755e Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:04:29 -0400 Subject: [PATCH 052/376] fix(aurora): fixed an sqlite error --- aurora/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 52cf3b7..cef07fe 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -5,6 +5,7 @@ from discord import Forbidden, HTTPException, InvalidData, NotFound from pydantic import BaseModel, ConfigDict from redbot.core.bot import Red +from aurora.utilities.json import dumps from aurora.utilities.utils import generate_dict @@ -84,7 +85,7 @@ class Moderation(AuroraGuildModel): with connect() as database: cursor = database.cursor() - cursor.execute(query, (self.timestamp, self.moderation_type, self.target_type, self.moderator_id, self.role_id, self.duration, self.end_timestamp, self.reason, self.resolved, self.resolved_by, self.resolve_reason, self.expired, changes, self.metadata, self.moderation_id)) + cursor.execute(query, (self.timestamp, self.moderation_type, self.target_type, self.moderator_id, self.role_id, self.duration, self.end_timestamp, self.reason, self.resolved, self.resolved_by, self.resolve_reason, self.expired, dumps(changes), dumps(self.metadata), self.moderation_id)) cursor.close() @classmethod -- 2.45.3 From 557ac45fccad00c4ccd07f0274a55d739dd7772a Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:05:14 -0400 Subject: [PATCH 053/376] fix(aurora): fixed a circular import --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index cef07fe..198653b 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -5,7 +5,6 @@ from discord import Forbidden, HTTPException, InvalidData, NotFound from pydantic import BaseModel, ConfigDict from redbot.core.bot import Red -from aurora.utilities.json import dumps from aurora.utilities.utils import generate_dict @@ -80,6 +79,7 @@ class Moderation(AuroraGuildModel): def update(self): from aurora.utilities.database import connect + from aurora.utilities.json import dumps query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" changes = [change.to_json() for change in self.changes] -- 2.45.3 From 0b697f9f502103e2dfb2fa84ad60ccbe27a3c729 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:07:51 -0400 Subject: [PATCH 054/376] fix(aurora): change how Moderation.update() works --- aurora/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 198653b..2e0c717 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -81,11 +81,10 @@ class Moderation(AuroraGuildModel): from aurora.utilities.database import connect from aurora.utilities.json import dumps query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" - changes = [change.to_json() for change in self.changes] with connect() as database: cursor = database.cursor() - cursor.execute(query, (self.timestamp, self.moderation_type, self.target_type, self.moderator_id, self.role_id, self.duration, self.end_timestamp, self.reason, self.resolved, self.resolved_by, self.resolve_reason, self.expired, dumps(changes), dumps(self.metadata), self.moderation_id)) + cursor.execute(query, (self.timestamp, self.moderation_type, self.target_type, self.moderator_id, self.role_id, self.duration, self.end_timestamp, self.reason, self.resolved, self.resolved_by, self.resolve_reason, self.expired, dumps(self.changes), dumps(self.metadata), self.moderation_id)) cursor.close() @classmethod -- 2.45.3 From 04d10d2cf8cf9deaf0dbaaac7f423c88abbbd9e1 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:12:00 -0400 Subject: [PATCH 055/376] fix(aurora): strip and replace the json dumps before inserting them into the db --- aurora/models.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 2e0c717..2129ad8 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -84,7 +84,23 @@ class Moderation(AuroraGuildModel): with connect() as database: cursor = database.cursor() - cursor.execute(query, (self.timestamp, self.moderation_type, self.target_type, self.moderator_id, self.role_id, self.duration, self.end_timestamp, self.reason, self.resolved, self.resolved_by, self.resolve_reason, self.expired, dumps(self.changes), dumps(self.metadata), self.moderation_id)) + cursor.execute(query, ( + self.timestamp, + self.moderation_type, + self.target_type, + self.moderator_id, + self.role_id, + self.duration, + self.end_timestamp, + self.reason, + self.resolved, + self.resolved_by, + self.resolve_reason, + self.expired, + dumps(self.changes).strip('"').replace('\\"', '"'), + dumps(self.metadata).strip('"').replace('\\"', '"'), + self.moderation_id + )) cursor.close() @classmethod -- 2.45.3 From acf3b0c68f03a235751c86b86657db686573797d Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:17:52 -0400 Subject: [PATCH 056/376] fix(aurora): added logging for the Moderation.update() method --- aurora/models.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/aurora/models.py b/aurora/models.py index 2129ad8..b542ab4 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -5,6 +5,7 @@ from discord import Forbidden, HTTPException, InvalidData, NotFound from pydantic import BaseModel, ConfigDict from redbot.core.bot import Red +from aurora.utilities.logger import logger from aurora.utilities.utils import generate_dict @@ -103,6 +104,25 @@ class Moderation(AuroraGuildModel): )) cursor.close() + logger.info("Updated moderation case %s in guild %s with the following data:\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", + self.moderation_id, + self.guild_id, + self.timestamp, + self.moderation_type, + self.target_type, + self.moderator_id, + self.role_id, + self.duration, + self.end_timestamp, + self.reason, + self.resolved, + self.resolved_by, + self.resolve_reason, + self.expired, + dumps(self.changes).strip('"').replace('\\"', '"'), + dumps(self.metadata).strip('"').replace('\\"', '"'), + ) + @classmethod def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> Optional["Moderation"]: from aurora.utilities.database import connect -- 2.45.3 From e8d210df2a16a397302f20e24d7986faa08485e2 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:19:29 -0400 Subject: [PATCH 057/376] fix(aurora): removed a %s --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index b542ab4..e80b345 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -104,7 +104,7 @@ class Moderation(AuroraGuildModel): )) cursor.close() - logger.info("Updated moderation case %s in guild %s with the following data:\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", + logger.info("Updated moderation case %s in guild %s with the following data:\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", self.moderation_id, self.guild_id, self.timestamp, -- 2.45.3 From 300d26dc7e2900c78af21af931093892631af1e9 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:50:30 -0400 Subject: [PATCH 058/376] fix(aurora): fixed a bunch of json issues --- aurora/models.py | 8 ++++---- aurora/utilities/utils.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index e80b345..66ed68a 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -98,8 +98,8 @@ class Moderation(AuroraGuildModel): self.resolved_by, self.resolve_reason, self.expired, - dumps(self.changes).strip('"').replace('\\"', '"'), - dumps(self.metadata).strip('"').replace('\\"', '"'), + dumps(self.changes).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), + dumps(self.metadata).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), self.moderation_id )) cursor.close() @@ -119,8 +119,8 @@ class Moderation(AuroraGuildModel): self.resolved_by, self.resolve_reason, self.expired, - dumps(self.changes).strip('"').replace('\\"', '"'), - dumps(self.metadata).strip('"').replace('\\"', '"'), + dumps(self.changes).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), + dumps(self.metadata).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), ) @classmethod diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index b15a865..67fb902 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -134,7 +134,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: duration = None if result[14] is not None: - changes = json.loads(result[14].strip('"').replace('\\"', '"')) + changes = json.loads(result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) change_obj_list = [] for change in changes: change_obj_list.append(Change.from_dict(bot=bot, data=change)) @@ -156,7 +156,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: "resolve_reason": result[12], "expired": bool(result[13]), "changes": change_obj_list if result[14] else [], - "metadata": json.loads(result[15].strip('"').replace('\\"', '"')) if result[15] else {}, + "metadata": json.loads(result[15].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) if result[15] else {}, } return case -- 2.45.3 From 8433c946fd88f09842b4035f9cac7d7e9d38c71f Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:52:54 -0400 Subject: [PATCH 059/376] fix(aurora): added a debug logging statement --- aurora/utilities/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 67fb902..b8e0c7b 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -11,6 +11,7 @@ from redbot.core.bot import Red from redbot.core.utils.chat_formatting import error from aurora.utilities.config import config +from aurora.utilities.logger import logger def check_permissions( @@ -134,6 +135,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: duration = None if result[14] is not None: + logger.debug(result[14]) changes = json.loads(result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) change_obj_list = [] for change in changes: -- 2.45.3 From a6371fd3674b814f9281debac6431efc4f50c761 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:55:17 -0400 Subject: [PATCH 060/376] fix(aurora): changed the logging statement slightly --- aurora/utilities/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index b8e0c7b..61687a7 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -135,7 +135,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: duration = None if result[14] is not None: - logger.debug(result[14]) + logger.debug('%s', result[14]) changes = json.loads(result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) change_obj_list = [] for change in changes: -- 2.45.3 From 293f77c228aebd2ff209579e52afbc6d89473569 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:55:50 -0400 Subject: [PATCH 061/376] fix(aurora): changed the logging statement again --- aurora/utilities/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 61687a7..fc92032 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -135,7 +135,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: duration = None if result[14] is not None: - logger.debug('%s', result[14]) + logger.debug('%s\n%s', result[14], result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) changes = json.loads(result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) change_obj_list = [] for change in changes: -- 2.45.3 From de90f6a8b7187e2c9a07b64d51b35f88bc4e2b57 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:57:34 -0400 Subject: [PATCH 062/376] fix(aurora): troubleshooting this annoying json issue --- aurora/utilities/utils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index fc92032..c6e7b19 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -135,8 +135,9 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: duration = None if result[14] is not None: - logger.debug('%s\n%s', result[14], result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) - changes = json.loads(result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) + json_str = f'{result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')}' + logger.debug('%s\n%s', result[14], json_str) + changes = json.loads(json_str) change_obj_list = [] for change in changes: change_obj_list.append(Change.from_dict(bot=bot, data=change)) -- 2.45.3 From cad24d852c846669bb12e949e2b602a3cf7cc63c Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 22:58:29 -0400 Subject: [PATCH 063/376] =?UTF-8?q?fix(aurora):=20ok=20fine=20bro=20?= =?UTF-8?q?=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aurora/utilities/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index c6e7b19..b856003 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -135,7 +135,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: duration = None if result[14] is not None: - json_str = f'{result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')}' + json_str = result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]') logger.debug('%s\n%s', result[14], json_str) changes = json.loads(json_str) change_obj_list = [] -- 2.45.3 From 278bd9834992e485cc9f18a8a15f5b3a9aa8346b Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 23:01:39 -0400 Subject: [PATCH 064/376] fix(aurora): trying ast --- aurora/utilities/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index b856003..b728a30 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -1,5 +1,6 @@ # pylint: disable=cyclic-import import json +from ast import literal_eval from datetime import datetime, timedelta from typing import Optional, Union @@ -137,7 +138,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: if result[14] is not None: json_str = result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]') logger.debug('%s\n%s', result[14], json_str) - changes = json.loads(json_str) + changes = literal_eval(json_str) change_obj_list = [] for change in changes: change_obj_list.append(Change.from_dict(bot=bot, data=change)) -- 2.45.3 From 4c8cd7bd1684aec166c8b997cc6d92b28c1d8f9a Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Sat, 4 May 2024 23:02:57 -0400 Subject: [PATCH 065/376] Revert "fix(aurora): trying ast" This reverts commit 278bd9834992e485cc9f18a8a15f5b3a9aa8346b. --- aurora/utilities/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index b728a30..b856003 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -1,6 +1,5 @@ # pylint: disable=cyclic-import import json -from ast import literal_eval from datetime import datetime, timedelta from typing import Optional, Union @@ -138,7 +137,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: if result[14] is not None: json_str = result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]') logger.debug('%s\n%s', result[14], json_str) - changes = literal_eval(json_str) + changes = json.loads(json_str) change_obj_list = [] for change in changes: change_obj_list.append(Change.from_dict(bot=bot, data=change)) -- 2.45.3 From 85a935f9b34ecc7c32450206f72c7b37fb9e3872 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 13:27:09 -0400 Subject: [PATCH 066/376] fix(aurora): fixed the json issue from yesterday --- aurora/utilities/utils.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index b856003..1f9c7e4 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -1,5 +1,6 @@ # pylint: disable=cyclic-import import json +from ast import literal_eval from datetime import datetime, timedelta from typing import Optional, Union @@ -11,7 +12,6 @@ from redbot.core.bot import Red from redbot.core.utils.chat_formatting import error from aurora.utilities.config import config -from aurora.utilities.logger import logger def check_permissions( @@ -135,9 +135,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: duration = None if result[14] is not None: - json_str = result[14].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]') - logger.debug('%s\n%s', result[14], json_str) - changes = json.loads(json_str) + changes = literal_eval(json.loads(result[14])) change_obj_list = [] for change in changes: change_obj_list.append(Change.from_dict(bot=bot, data=change)) -- 2.45.3 From 6745f0a4860034c56a51b6a2fd8ccc46869f3327 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 13:44:48 -0400 Subject: [PATCH 067/376] fix(aurora): fixed an issue with importing changes --- aurora/importers/aurora.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index d1905e7..fce790e 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -72,6 +72,10 @@ class ImportAuroraView(ui.View): if "changes" not in case or not case["changes"]: case["changes"] = [] + else: + case["changes"] = json.loads(case["changes"]) + if isinstance(case["changes"], str): + case["changes"] = json.loads(case["changes"]) if "metadata" not in case: metadata = {} -- 2.45.3 From 0553856aa90b8a110689fdc9fdcf2883100d1f90 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 13:51:23 -0400 Subject: [PATCH 068/376] fix(aurora): fixed utils.generate_dict() using literal_eval still even when it's unnecessary --- aurora/utilities/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 1f9c7e4..63a894a 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -1,6 +1,5 @@ # pylint: disable=cyclic-import import json -from ast import literal_eval from datetime import datetime, timedelta from typing import Optional, Union @@ -135,7 +134,7 @@ def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: duration = None if result[14] is not None: - changes = literal_eval(json.loads(result[14])) + changes = json.loads(result[14]) change_obj_list = [] for change in changes: change_obj_list.append(Change.from_dict(bot=bot, data=change)) -- 2.45.3 From 37e471fbaa5ceba0990335e42a1d8e7990dce4b6 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:15:05 -0400 Subject: [PATCH 069/376] fix(aurora): fixing a whole bunch of stuff --- aurora/importers/aurora.py | 6 +- aurora/models.py | 114 +++++++++++++++++++++++++++++++++-- aurora/utilities/database.py | 7 ++- aurora/utilities/utils.py | 4 +- 4 files changed, 118 insertions(+), 13 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index fce790e..0885ee9 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -8,7 +8,8 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands from redbot.core.utils.chat_formatting import box, warning -from ..utilities.database import connect, create_guild_table, mysql_log +from aurora.models import Moderation +from aurora.utilities.database import connect, create_guild_table class ImportAuroraView(ui.View): @@ -91,7 +92,8 @@ class ImportAuroraView(ui.View): else: duration = None - await mysql_log( + Moderation.log( + interaction.client, self.ctx.guild.id, case["moderator_id"], case["moderation_type"], diff --git a/aurora/models.py b/aurora/models.py index 66ed68a..9d70330 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,4 +1,6 @@ +import sqlite3 from datetime import datetime, timedelta +from time import time from typing import Any, Dict, List, Literal, Optional, Union from discord import Forbidden, HTTPException, InvalidData, NotFound @@ -6,7 +8,7 @@ from pydantic import BaseModel, ConfigDict from redbot.core.bot import Red from aurora.utilities.logger import logger -from aurora.utilities.utils import generate_dict +from aurora.utilities.utils import generate_dict, get_next_case_number class AuroraBaseModel(BaseModel): @@ -80,7 +82,6 @@ class Moderation(AuroraGuildModel): def update(self): from aurora.utilities.database import connect - from aurora.utilities.json import dumps query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" with connect() as database: @@ -98,8 +99,8 @@ class Moderation(AuroraGuildModel): self.resolved_by, self.resolve_reason, self.expired, - dumps(self.changes).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), - dumps(self.metadata).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), + self.changes, + self.metadata, self.moderation_id )) cursor.close() @@ -119,8 +120,8 @@ class Moderation(AuroraGuildModel): self.resolved_by, self.resolve_reason, self.expired, - dumps(self.changes).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), - dumps(self.metadata).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), + self.changes, + self.metadata, ) @classmethod @@ -144,6 +145,107 @@ class Moderation(AuroraGuildModel): def from_dict(cls, bot: Red, data: dict) -> "Moderation": return cls(bot=bot, **data) + @classmethod + def log( + cls, + bot: Red, + guild_id: int, + author_id: int, + moderation_type: str, + target_type: str, + target_id: int, + role_id: int, + duration: timedelta = None, + reason: str = None, + database: sqlite3.Connection = None, + timestamp: datetime = None, + resolved: bool = False, + resolved_by: int = None, + resolved_reason: str = None, + expired: bool = None, + changes: list = None, + metadata: dict = None, + ) -> "Moderation": + from aurora.utilities.database import connect + if not timestamp: + timestamp = datetime.fromtimestamp(time()) + elif not isinstance(timestamp, datetime): + timestamp = datetime.fromtimestamp(timestamp) + + if duration != "NULL" and duration is not None: + end_timedelta = timestamp + duration + end_timestamp = int(end_timedelta.timestamp()) + else: + duration = None + end_timestamp = None + + if not expired: + if timestamp.timestamp() > end_timestamp: + expired = True + else: + expired = False + + if reason == "NULL": + reason = None + + if resolved_by == "NULL": + resolved_by = None + + if resolved_reason == "NULL": + resolved_reason = None + + if role_id == 0: + role_id = None + + if not database: + database = connect() + close_db = True + else: + close_db = False + cursor = database.cursor() + + moderation_id = get_next_case_number(guild_id=guild_id, cursor=cursor) + + case = { + "guild_id": guild_id, + "moderation_id": moderation_id, + "timestamp": timestamp, + "moderation_type": moderation_type, + "target_type": target_type, + "target_id": target_id, + "moderator_id": author_id, + "role_id": role_id, + "duration": duration, + "end_timestamp": end_timestamp, + "reason": reason, + "resolved": resolved, + "resolved_by": resolved_by, + "resolve_reason": resolved_reason, + "expired": expired, + "changes": changes, + "metadata": metadata + } + + case_safe = case.copy() + case_safe.pop("guild_id") + case_safe["timestamp"] = case_safe["timestamp"].timestamp() + case_safe["end_timestamp"] = case_safe["end_timestamp"].timestamp() if case_safe["end_timestamp"] else None + + sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + cursor.execute(sql, case_safe.values()) + + cursor.close() + database.commit() + if close_db: + database.close() + + logger.debug( + "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", + guild_id, case_safe.values() + ) + + return cls.from_dict(bot=bot, **case) + class Change(AuroraBaseModel): type: Literal["ORIGINAL", "RESOLVE", "EDIT"] timestamp: datetime diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index 95ad7c8..88cec8b 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -8,7 +8,8 @@ from discord import Guild from redbot.core import data_manager from .logger import logger -from .utils import convert_timedelta_to_str, generate_dict, get_next_case_number +from .utils import (convert_timedelta_to_str, generate_dict, + get_next_case_number) def connect() -> sqlite3.Connection: @@ -103,7 +104,7 @@ async def create_guild_table(guild: Guild): database.close() -async def mysql_log( +def mysql_log( guild_id: str, author_id: str, moderation_type: str, @@ -158,7 +159,7 @@ async def mysql_log( close_db = False cursor = database.cursor() - moderation_id = await get_next_case_number(guild_id=guild_id, cursor=cursor) + moderation_id = get_next_case_number(guild_id=guild_id, cursor=cursor) sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" val = ( diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 63a894a..fcc8d61 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -111,9 +111,9 @@ async def check_moddable( return True -async def get_next_case_number(guild_id: str, cursor=None) -> int: +def get_next_case_number(guild_id: str, cursor=None) -> int: """This function returns the next case number from the MySQL table for a specific guild.""" - from .database import connect + from aurora.utilities.database import connect if not cursor: database = connect() -- 2.45.3 From a86348fae3faf137cd9a837782f821f418b26b5c Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:16:51 -0400 Subject: [PATCH 070/376] fix(aurora): fixed a programming error --- aurora/models.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/aurora/models.py b/aurora/models.py index 9d70330..7a63220 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -167,6 +167,7 @@ class Moderation(AuroraGuildModel): metadata: dict = None, ) -> "Moderation": from aurora.utilities.database import connect + from aurora.utilities.json import dumps if not timestamp: timestamp = datetime.fromtimestamp(time()) elif not isinstance(timestamp, datetime): @@ -230,6 +231,11 @@ class Moderation(AuroraGuildModel): case_safe.pop("guild_id") case_safe["timestamp"] = case_safe["timestamp"].timestamp() case_safe["end_timestamp"] = case_safe["end_timestamp"].timestamp() if case_safe["end_timestamp"] else None + case_safe["duration"] = str(case_safe["duration"]) + case_safe["resolved"] = int(case_safe["resolved"]) + case_safe["expired"] = int(case_safe["expired"]) + case_safe["changes"] = dumps(case_safe["changes"]) + case_safe["metadata"] = dumps(case_safe["metadata"]) sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" cursor.execute(sql, case_safe.values()) -- 2.45.3 From e591b2c4a50b3bf23b917d7de75585a19d185d6b Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:18:54 -0400 Subject: [PATCH 071/376] fix(aurora): convert floats to ints --- aurora/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 7a63220..07a4d04 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -229,8 +229,8 @@ class Moderation(AuroraGuildModel): case_safe = case.copy() case_safe.pop("guild_id") - case_safe["timestamp"] = case_safe["timestamp"].timestamp() - case_safe["end_timestamp"] = case_safe["end_timestamp"].timestamp() if case_safe["end_timestamp"] else None + case_safe["timestamp"] = int(case_safe["timestamp"].timestamp()) + case_safe["end_timestamp"] = int(case_safe["end_timestamp"].timestamp()) if case_safe["end_timestamp"] else None case_safe["duration"] = str(case_safe["duration"]) case_safe["resolved"] = int(case_safe["resolved"]) case_safe["expired"] = int(case_safe["expired"]) -- 2.45.3 From 65bb9af7a6678981d2c9f047b3112892cd4f82bf Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:20:49 -0400 Subject: [PATCH 072/376] fix(aurora): fixed an issue with dictionary values not being converted to a tuple --- aurora/models.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 07a4d04..c31675b 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -167,7 +167,6 @@ class Moderation(AuroraGuildModel): metadata: dict = None, ) -> "Moderation": from aurora.utilities.database import connect - from aurora.utilities.json import dumps if not timestamp: timestamp = datetime.fromtimestamp(time()) elif not isinstance(timestamp, datetime): @@ -229,16 +228,11 @@ class Moderation(AuroraGuildModel): case_safe = case.copy() case_safe.pop("guild_id") - case_safe["timestamp"] = int(case_safe["timestamp"].timestamp()) - case_safe["end_timestamp"] = int(case_safe["end_timestamp"].timestamp()) if case_safe["end_timestamp"] else None - case_safe["duration"] = str(case_safe["duration"]) - case_safe["resolved"] = int(case_safe["resolved"]) - case_safe["expired"] = int(case_safe["expired"]) - case_safe["changes"] = dumps(case_safe["changes"]) - case_safe["metadata"] = dumps(case_safe["metadata"]) + case_safe["timestamp"] = case_safe["timestamp"].timestamp() + case_safe["end_timestamp"] = case_safe["end_timestamp"].timestamp() if case_safe["end_timestamp"] else None sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - cursor.execute(sql, case_safe.values()) + cursor.execute(sql, tuple(case_safe.values())) cursor.close() database.commit() -- 2.45.3 From 52fcdcc96a2ed1ea4c03a05b06ee78826d14aad9 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:21:57 -0400 Subject: [PATCH 073/376] fix(aurora): fixed a logging issue --- aurora/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aurora/models.py b/aurora/models.py index c31675b..7caf331 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -167,6 +167,7 @@ class Moderation(AuroraGuildModel): metadata: dict = None, ) -> "Moderation": from aurora.utilities.database import connect + from aurora.utilities.json import dumps if not timestamp: timestamp = datetime.fromtimestamp(time()) elif not isinstance(timestamp, datetime): @@ -230,6 +231,8 @@ class Moderation(AuroraGuildModel): case_safe.pop("guild_id") case_safe["timestamp"] = case_safe["timestamp"].timestamp() case_safe["end_timestamp"] = case_safe["end_timestamp"].timestamp() if case_safe["end_timestamp"] else None + case_safe["changes"] = dumps(case_safe["changes"]) + case_safe["metadata"] = dumps(case_safe["metadata"]) sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" cursor.execute(sql, tuple(case_safe.values())) -- 2.45.3 From 158e7560f8f45dcfbdab85aacbe87b196c948209 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:22:40 -0400 Subject: [PATCH 074/376] fix(aurora): fixed a broken logging statement --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 7caf331..27375c4 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -244,7 +244,7 @@ class Moderation(AuroraGuildModel): logger.debug( "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", - guild_id, case_safe.values() + guild_id, tuple(case_safe.values()) ) return cls.from_dict(bot=bot, **case) -- 2.45.3 From 5b6b04dfe0c8f76aae44b500120dd99ea35876bd Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:25:42 -0400 Subject: [PATCH 075/376] fix(aurora): actually fixed a broken logging statement --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 27375c4..4dfa38a 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -244,7 +244,7 @@ class Moderation(AuroraGuildModel): logger.debug( "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", - guild_id, tuple(case_safe.values()) + tuple(guild_id, case_safe.values()) ) return cls.from_dict(bot=bot, **case) -- 2.45.3 From 1b322dfe50cb435cde8b974347a15a3910b3a757 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:29:09 -0400 Subject: [PATCH 076/376] fix(aurora): actually actually fixed the broken logging statement --- aurora/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 4dfa38a..091ff03 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,5 +1,6 @@ import sqlite3 from datetime import datetime, timedelta +from itertools import chain from time import time from typing import Any, Dict, List, Literal, Optional, Union @@ -244,7 +245,7 @@ class Moderation(AuroraGuildModel): logger.debug( "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", - tuple(guild_id, case_safe.values()) + tuple(chain({"guild_id": guild_id}.values() + case_safe.values())) ) return cls.from_dict(bot=bot, **case) -- 2.45.3 From 335d1a2a4c531bcc10b27c3f4a249910ea79d3e5 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:29:57 -0400 Subject: [PATCH 077/376] fix(aurora): actually actually ACTUALLY fixed the broken logging statement --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 091ff03..cae9d23 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -245,7 +245,7 @@ class Moderation(AuroraGuildModel): logger.debug( "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", - tuple(chain({"guild_id": guild_id}.values() + case_safe.values())) + tuple(chain({"guild_id": guild_id}.values(), case_safe.values())) ) return cls.from_dict(bot=bot, **case) -- 2.45.3 From 0386cb346ef1f06500b7499dc8c9d93e98035b9f Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:35:02 -0400 Subject: [PATCH 078/376] fix(aurora): finally fixed the debug logging statement (maybe) --- aurora/models.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index cae9d23..b758bab 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,6 +1,5 @@ import sqlite3 from datetime import datetime, timedelta -from itertools import chain from time import time from typing import Any, Dict, List, Literal, Optional, Union @@ -229,23 +228,25 @@ class Moderation(AuroraGuildModel): } case_safe = case.copy() - case_safe.pop("guild_id") case_safe["timestamp"] = case_safe["timestamp"].timestamp() case_safe["end_timestamp"] = case_safe["end_timestamp"].timestamp() if case_safe["end_timestamp"] else None case_safe["changes"] = dumps(case_safe["changes"]) case_safe["metadata"] = dumps(case_safe["metadata"]) + case_sql = case_safe.copy() + case_sql.pop("guild_id") sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - cursor.execute(sql, tuple(case_safe.values())) + cursor.execute(sql, tuple(case_sql.values())) cursor.close() database.commit() if close_db: database.close() + case_safe.update({"guild_id": guild_id}) logger.debug( "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", - tuple(chain({"guild_id": guild_id}.values(), case_safe.values())) + tuple(case_safe.values()) ) return cls.from_dict(bot=bot, **case) -- 2.45.3 From 70c00a59d620f607d81c9ee4b49e443cbbe5950d Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:40:14 -0400 Subject: [PATCH 079/376] fix(aurora): fixed the broken logging statement --- aurora/models.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index b758bab..3304909 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -150,7 +150,7 @@ class Moderation(AuroraGuildModel): cls, bot: Red, guild_id: int, - author_id: int, + moderator_id: int, moderation_type: str, target_type: str, target_id: int, @@ -214,7 +214,7 @@ class Moderation(AuroraGuildModel): "moderation_type": moderation_type, "target_type": target_type, "target_id": target_id, - "moderator_id": author_id, + "moderator_id": moderator_id, "role_id": role_id, "duration": duration, "end_timestamp": end_timestamp, @@ -228,15 +228,14 @@ class Moderation(AuroraGuildModel): } case_safe = case.copy() + case_safe.pop("guild_id") case_safe["timestamp"] = case_safe["timestamp"].timestamp() case_safe["end_timestamp"] = case_safe["end_timestamp"].timestamp() if case_safe["end_timestamp"] else None case_safe["changes"] = dumps(case_safe["changes"]) case_safe["metadata"] = dumps(case_safe["metadata"]) - case_sql = case_safe.copy() - case_sql.pop("guild_id") sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - cursor.execute(sql, tuple(case_sql.values())) + cursor.execute(sql, tuple(case_safe.values())) cursor.close() database.commit() @@ -246,7 +245,23 @@ class Moderation(AuroraGuildModel): case_safe.update({"guild_id": guild_id}) logger.debug( "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", - tuple(case_safe.values()) + guild_id, + case_safe["moderation_id"], + case_safe["timestamp"], + case_safe["moderation_type"], + case_safe["target_type"], + case_safe["target_id"], + case_safe["moderator_id"], + case_safe["role_id"], + case_safe["duration"], + case_safe["end_timestamp"], + case_safe["reason"], + case_safe["resolved"], + case_safe["resolved_by"], + case_safe["resolve_reason"], + case_safe["expired"], + case_safe["changes"], + case_safe["metadata"], ) return cls.from_dict(bot=bot, **case) -- 2.45.3 From 84235d6504a87af114716c561418a567c8993233 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:41:16 -0400 Subject: [PATCH 080/376] fix(aurora): call from_dict properly --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 3304909..57c8a80 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -264,7 +264,7 @@ class Moderation(AuroraGuildModel): case_safe["metadata"], ) - return cls.from_dict(bot=bot, **case) + return cls.from_dict(bot=bot, data=case) class Change(AuroraBaseModel): type: Literal["ORIGINAL", "RESOLVE", "EDIT"] -- 2.45.3 From b7b6dc2f2e68cabaa871f1d160ab0e98c9da4e8d Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:44:06 -0400 Subject: [PATCH 081/376] fix(aurora): don't convert end_timestamp to an integer --- aurora/models.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 57c8a80..4792f4a 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -174,14 +174,13 @@ class Moderation(AuroraGuildModel): timestamp = datetime.fromtimestamp(timestamp) if duration != "NULL" and duration is not None: - end_timedelta = timestamp + duration - end_timestamp = int(end_timedelta.timestamp()) + end_timestamp = timestamp + duration else: duration = None end_timestamp = None if not expired: - if timestamp.timestamp() > end_timestamp: + if timestamp > end_timestamp: expired = True else: expired = False -- 2.45.3 From 1e865643a03487d065ceebf03ced17a9971672c8 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:45:04 -0400 Subject: [PATCH 082/376] fix(aurora): fixed duration being a timedelta in case_safe --- aurora/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aurora/models.py b/aurora/models.py index 4792f4a..81963a0 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -228,6 +228,7 @@ class Moderation(AuroraGuildModel): case_safe = case.copy() case_safe.pop("guild_id") + case_safe["duration"] = str(case_safe["duration"]) if case_safe["duration"] else None case_safe["timestamp"] = case_safe["timestamp"].timestamp() case_safe["end_timestamp"] = case_safe["end_timestamp"].timestamp() if case_safe["end_timestamp"] else None case_safe["changes"] = dumps(case_safe["changes"]) -- 2.45.3 From 9c7e0b0b8953a9f01289de6e9639bbd7fff9c29f Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:48:16 -0400 Subject: [PATCH 083/376] fix(aurora): fixed a missing parameter --- aurora/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aurora/models.py b/aurora/models.py index 81963a0..589e198 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -264,6 +264,9 @@ class Moderation(AuroraGuildModel): case_safe["metadata"], ) + for change in case["changes"]: + change.update({"bot": bot}) + return cls.from_dict(bot=bot, data=case) class Change(AuroraBaseModel): -- 2.45.3 From a4e11fd82870b477edda3f4ebc96993d7c00604e Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 14:55:36 -0400 Subject: [PATCH 084/376] fix(aurora): fixing some model stuff --- aurora/models.py | 90 +++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 589e198..e857e5f 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -82,48 +82,53 @@ class Moderation(AuroraGuildModel): def update(self): from aurora.utilities.database import connect + from aurora.utilities.json import dumps query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" with connect() as database: cursor = database.cursor() cursor.execute(query, ( - self.timestamp, + self.timestamp.timestamp(), self.moderation_type, self.target_type, self.moderator_id, self.role_id, - self.duration, - self.end_timestamp, + str(self.duration) if self.duration else None, + self.end_timestamp.timestamp() if self.end_timestamp else None, self.reason, self.resolved, self.resolved_by, self.resolve_reason, self.expired, - self.changes, - self.metadata, - self.moderation_id + dumps(self.changes), + dumps(self.metadata), + self.moderation_id, )) cursor.close() logger.info("Updated moderation case %s in guild %s with the following data:\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", self.moderation_id, self.guild_id, - self.timestamp, + self.timestamp.timestamp(), self.moderation_type, self.target_type, self.moderator_id, self.role_id, - self.duration, - self.end_timestamp, + str(self.duration) if self.duration else None, + self.end_timestamp.timestamp() if self.end_timestamp else None, self.reason, self.resolved, self.resolved_by, self.resolve_reason, self.expired, - self.changes, - self.metadata, + dumps(self.changes), + dumps(self.metadata), ) + @classmethod + def from_dict(cls, bot: Red, data: dict) -> "Moderation": + return cls(bot=bot, **data) + @classmethod def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> Optional["Moderation"]: from aurora.utilities.database import connect @@ -141,10 +146,6 @@ class Moderation(AuroraGuildModel): return None - @classmethod - def from_dict(cls, bot: Red, data: dict) -> "Moderation": - return cls(bot=bot, **data) - @classmethod def log( cls, @@ -207,67 +208,54 @@ class Moderation(AuroraGuildModel): moderation_id = get_next_case_number(guild_id=guild_id, cursor=cursor) case = { - "guild_id": guild_id, "moderation_id": moderation_id, - "timestamp": timestamp, + "timestamp": timestamp.timestamp(), "moderation_type": moderation_type, "target_type": target_type, "target_id": target_id, "moderator_id": moderator_id, "role_id": role_id, - "duration": duration, - "end_timestamp": end_timestamp, + "duration": str(duration) if duration else None, + "end_timestamp": end_timestamp.timestamp() if end_timestamp else None, "reason": reason, "resolved": resolved, "resolved_by": resolved_by, "resolve_reason": resolved_reason, "expired": expired, - "changes": changes, - "metadata": metadata + "changes": dumps(changes), + "metadata": dumps(metadata) } - case_safe = case.copy() - case_safe.pop("guild_id") - case_safe["duration"] = str(case_safe["duration"]) if case_safe["duration"] else None - case_safe["timestamp"] = case_safe["timestamp"].timestamp() - case_safe["end_timestamp"] = case_safe["end_timestamp"].timestamp() if case_safe["end_timestamp"] else None - case_safe["changes"] = dumps(case_safe["changes"]) - case_safe["metadata"] = dumps(case_safe["metadata"]) - sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - cursor.execute(sql, tuple(case_safe.values())) + cursor.execute(sql, tuple(case.values())) cursor.close() database.commit() if close_db: database.close() - case_safe.update({"guild_id": guild_id}) logger.debug( "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", guild_id, - case_safe["moderation_id"], - case_safe["timestamp"], - case_safe["moderation_type"], - case_safe["target_type"], - case_safe["target_id"], - case_safe["moderator_id"], - case_safe["role_id"], - case_safe["duration"], - case_safe["end_timestamp"], - case_safe["reason"], - case_safe["resolved"], - case_safe["resolved_by"], - case_safe["resolve_reason"], - case_safe["expired"], - case_safe["changes"], - case_safe["metadata"], + case["moderation_id"], + case["timestamp"], + case["moderation_type"], + case["target_type"], + case["target_id"], + case["moderator_id"], + case["role_id"], + case["duration"], + case["end_timestamp"], + case["reason"], + case["resolved"], + case["resolved_by"], + case["resolve_reason"], + case["expired"], + case["changes"], + case["metadata"], ) - for change in case["changes"]: - change.update({"bot": bot}) - - return cls.from_dict(bot=bot, data=case) + return cls.from_sql(bot=bot, moderation_id=moderation_id, guild_id=guild_id) class Change(AuroraBaseModel): type: Literal["ORIGINAL", "RESOLVE", "EDIT"] -- 2.45.3 From 8d1a57165d2df770ad7618d1321cb8cba0409547 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 15:00:54 -0400 Subject: [PATCH 085/376] fix(aurora): added debug logging --- aurora/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index e857e5f..07c73e6 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -106,7 +106,7 @@ class Moderation(AuroraGuildModel): )) cursor.close() - logger.info("Updated moderation case %s in guild %s with the following data:\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", + logger.info("Row updated in moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", self.moderation_id, self.guild_id, self.timestamp.timestamp(), @@ -277,6 +277,7 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Change": + logger.debug("Creating Change from dict: %s", data) if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): hours, minutes, seconds = map(int, data["duration"].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) -- 2.45.3 From e14845ef85a688a87f6abb5423ad162ff5d58bf5 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 15:03:41 -0400 Subject: [PATCH 086/376] fix(aurora): make sure the user_id in changes is always an integer --- aurora/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 07c73e6..7f32944 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -301,7 +301,8 @@ class Change(AuroraBaseModel): data.update({ "timestamp": timestamp, "end_timestamp": end_timestamp, - "duration": duration + "duration": duration, + "user_id": int(data["user_id"]) }) return cls(bot=bot, **data) -- 2.45.3 From 5be5a39c54a055c610ab7808e6cf878f95c511a4 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 15:06:10 -0400 Subject: [PATCH 087/376] fix(aurora): check type of dictionary in debug log --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 7f32944..20b1bf4 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -277,7 +277,7 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Change": - logger.debug("Creating Change from dict: %s", data) + logger.debug("Creating Change from dict (%s): %s", type(data), data) if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): hours, minutes, seconds = map(int, data["duration"].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) -- 2.45.3 From 16af26f93e4a0bfe56250ba27929fa259dbd4eff Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 15:11:11 -0400 Subject: [PATCH 088/376] fix(aurora): fixed a logging statement --- aurora/models.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 20b1bf4..396671e 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,3 +1,4 @@ +import json import sqlite3 from datetime import datetime, timedelta from time import time @@ -106,7 +107,7 @@ class Moderation(AuroraGuildModel): )) cursor.close() - logger.info("Row updated in moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", + logger.debug("Row updated in moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", self.moderation_id, self.guild_id, self.timestamp.timestamp(), @@ -278,6 +279,9 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Change": logger.debug("Creating Change from dict (%s): %s", type(data), data) + if isinstance(data, str): + data = json.loads(data) + logger.debug("Change data was a string, converted to dict: %s", data) if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): hours, minutes, seconds = map(int, data["duration"].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) -- 2.45.3 From dcda128f113ef9093806667178a81420671ff29b Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 15:15:54 -0400 Subject: [PATCH 089/376] fix(aurora): edit command will now edit reasons as intended --- aurora/aurora.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 1572195..9731767 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -19,7 +19,8 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (box, error, humanize_list, + humanize_timedelta, warning) from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -29,11 +30,19 @@ from aurora.menus.immune import Immune from aurora.menus.overrides import Overrides from aurora.models import Change, Moderation from aurora.utilities.config import config, register_config -from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log -from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed +from aurora.utilities.database import (connect, create_guild_table, fetch_case, + mysql_log) +from aurora.utilities.factory import (addrole_embed, case_factory, + changes_factory, evidenceformat_factory, + guild_embed, immune_embed, + message_factory, overrides_embed) from aurora.utilities.json import dump, dumps from aurora.utilities.logger import logger -from aurora.utilities.utils import check_moddable, check_permissions, fetch_channel_dict, fetch_user_dict, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from aurora.utilities.utils import (check_moddable, check_permissions, + fetch_channel_dict, fetch_user_dict, + generate_dict, get_footer_image, log, + send_evidenceformat, + timedelta_from_relativedelta) class Aurora(commands.Cog): @@ -1531,6 +1540,9 @@ class Aurora(commands.Cog): except discord.NotFound: pass + if reason: + moderation.reason = reason + if not moderation.changes: moderation.changes.append(Change.from_dict(interaction.client, { "type": "ORIGINAL", -- 2.45.3 From d375716fbf24f596bb44bfa40822c728cf7341dc Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 15:29:48 -0400 Subject: [PATCH 090/376] feat(aurora): added a resolve function to the Moderation model --- aurora/models.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/aurora/models.py b/aurora/models.py index 396671e..2ad8de2 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta from time import time from typing import Any, Dict, List, Literal, Optional, Union +import discord from discord import Forbidden, HTTPException, InvalidData, NotFound from pydantic import BaseModel, ConfigDict from redbot.core.bot import Red @@ -81,6 +82,50 @@ class Moderation(AuroraGuildModel): def __str__(self): return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}" + async def resolve(self, resolved_by: int, reason: str): + if self.resolved: + raise ValueError("Case is already resolved!") + + self.resolved = True + self.resolved_by = resolved_by + self.resolve_reason = reason + + if self.type == "MUTE": + try: + guild: discord.Guild = await self.bot.fetch_guild(self.guild_id) + member = await guild.fetch_member(self.target_id) + + await member.timeout( + None, reason=f"Case {self.moderation_id} resolved by {resolved_by}{" for" + reason if reason else ""}" + ) + except NotFound: + pass + + if self.type in ["BAN", "TEMPBAN"]: + try: + guild: discord.Guild = await self.bot.fetch_guild(self.guild_id) + await guild.unban(await self.get_target(), reason=f"Case {self.moderation_id} resolved by {resolved_by}{" for" + reason if reason else ""}") + except NotFound: + pass + + if not self.changes: + self.changes.append(Change.from_dict(self.bot, { + "type": "ORIGINAL", + "timestamp": self.timestamp, + "reason": self.reason, + "user_id": self.moderator_id, + "duration": self.duration, + "end_timestamp": self.end_timestamp, + })) + self.changes.append(Change.from_dict(self.bot, { + "type": "RESOLVE", + "timestamp": datetime.now(), + "reason": reason, + "user_id": resolved_by, + })) + + self.update() + def update(self): from aurora.utilities.database import connect from aurora.utilities.json import dumps -- 2.45.3 From 834d116b2035dfa2a1f116d8c9f0defe65db7ddd Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 15:32:01 -0400 Subject: [PATCH 091/376] fix(aurora): fixed a syntax error --- aurora/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index 2ad8de2..6c37bd5 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -96,7 +96,7 @@ class Moderation(AuroraGuildModel): member = await guild.fetch_member(self.target_id) await member.timeout( - None, reason=f"Case {self.moderation_id} resolved by {resolved_by}{" for" + reason if reason else ""}" + None, reason=f"Case {self.moderation_id} resolved by {resolved_by}{' for '+ reason if reason else ''}" ) except NotFound: pass @@ -104,7 +104,7 @@ class Moderation(AuroraGuildModel): if self.type in ["BAN", "TEMPBAN"]: try: guild: discord.Guild = await self.bot.fetch_guild(self.guild_id) - await guild.unban(await self.get_target(), reason=f"Case {self.moderation_id} resolved by {resolved_by}{" for" + reason if reason else ""}") + await guild.unban(await self.get_target(), reason=f"Case {self.moderation_id} resolved by {resolved_by}{' for '+ reason if reason else ''}") except NotFound: pass -- 2.45.3 From f8968e8e9ee0a1ac3ca9791df17ac0f5ea3e37a2 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 15:59:43 -0400 Subject: [PATCH 092/376] feat(aurora): updated `/history` command --- aurora/aurora.py | 491 ++++++++++++++++++----------------------------- aurora/models.py | 13 +- 2 files changed, 199 insertions(+), 305 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 9731767..d764521 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -11,6 +11,7 @@ import sqlite3 import time from datetime import datetime, timedelta, timezone from math import ceil +from typing import List import discord from discord import Object @@ -19,8 +20,7 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import (box, error, humanize_list, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -30,19 +30,11 @@ from aurora.menus.immune import Immune from aurora.menus.overrides import Overrides from aurora.models import Change, Moderation from aurora.utilities.config import config, register_config -from aurora.utilities.database import (connect, create_guild_table, fetch_case, - mysql_log) -from aurora.utilities.factory import (addrole_embed, case_factory, - changes_factory, evidenceformat_factory, - guild_embed, immune_embed, - message_factory, overrides_embed) -from aurora.utilities.json import dump, dumps +from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log +from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed +from aurora.utilities.json import dump from aurora.utilities.logger import logger -from aurora.utilities.utils import (check_moddable, check_permissions, - fetch_channel_dict, fetch_user_dict, - generate_dict, get_footer_image, log, - send_evidenceformat, - timedelta_from_relativedelta) +from aurora.utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta class Aurora(commands.Cog): @@ -1122,15 +1114,15 @@ class Aurora(commands.Cog): cursor.execute(query) results = cursor.fetchall() - result_dict_list = [] + moderation_list: List[Moderation] = [] for result in results: - case_dict = generate_dict(result) - if case_dict["moderation_id"] == 0: - continue - result_dict_list.append(case_dict) + if result["moderation_id"] != 0: + result.update({"guild_id": interaction.guild.id}) + moderation = Moderation.from_dict(interaction.client, dict(result)) + moderation_list.append(moderation) - case_quantity = len(result_dict_list) + case_quantity = len(moderation_list) page_quantity = ceil(case_quantity / pagesize) start_index = (page - 1) * pagesize end_index = page * pagesize @@ -1143,74 +1135,44 @@ class Aurora(commands.Cog): memory_dict = {} - for case in result_dict_list[start_index:end_index]: - if case["target_id"] not in memory_dict: - if case["target_type"] == "USER": - memory_dict[str(case["target_id"])] = await fetch_user_dict( - interaction.client, case["target_id"] - ) - elif case["target_type"] == "CHANNEL": - memory_dict[str(case["target_id"])] = await fetch_channel_dict( - interaction.guild, case["target_id"] - ) - target_user = memory_dict[str(case["target_id"])] + for mod in moderation_list[start_index:end_index]: + if mod.target_id not in memory_dict: + memory_dict.update({ + str(mod.target_id): await mod.get_target() + }) + target = memory_dict[str(mod.target_id)] - if case["target_type"] == "USER": - target_name = ( - f"`{target_user['name']}`" - if target_user["discriminator"] == "0" - else f"`{target_user['name']}#{target_user['discriminator']}`" - ) - elif case["target_type"] == "CHANNEL": - target_name = f"`{target_user['mention']}`" - - if case["moderator_id"] not in memory_dict: - memory_dict[str(case["moderator_id"])] = await fetch_user_dict( - interaction.client, case["moderator_id"] - ) - moderator_user = memory_dict[str(case["moderator_id"])] - moderator_name = ( - f"`{moderator_user['name']}`" - if moderator_user["discriminator"] == "0" - else f"`{moderator_user['name']}#{moderator_user['discriminator']}`" - ) + if mod.moderator_id not in memory_dict: + memory_dict.update({ + str(mod.moderator_id): await mod.get_moderator() + }) + moderator = memory_dict[str(mod.moderator_id)] field_name = f"Case #{case['moderation_id']:,} ({str.title(case['moderation_type'])})" - field_value = f"**Target:** {target_name} ({target_user['id']})\n**Moderator:** {moderator_name} ({moderator_user['id']})" + field_value = f"**Target:** `{target.name}` ({target.id})\n**Moderator:** `{moderator.name}` ({moderator.id})" if len(case["reason"]) > 125: - field_value += f"\n**Reason:** `{str(case['reason'])[:125]}...`" + field_value += f"\n**Reason:** `{str(mod.reason)[:125]}...`" else: - field_value += f"\n**Reason:** `{str(case['reason'])}`" + field_value += f"\n**Reason:** `{str(mod.reason)}`" - if case["duration"] != "NULL": - td = timedelta( - **{ - unit: int(val) - for unit, val in zip( - ["hours", "minutes", "seconds"], case["duration"].split(":") - ) - } - ) + if mod.duration: duration_embed = ( - f"{humanize_timedelta(timedelta=td)} | " - if bool(case["expired"]) is False - else f"{humanize_timedelta(timedelta=td)} | Expired" + f"{humanize_timedelta(timedelta=mod.duration)} | " + if mod.expired is False + else f"{humanize_timedelta(timedelta=mod.duration)} | Expired" ) field_value += f"\n**Duration:** {duration_embed}" field_value += ( - f"\n**Timestamp:** | " + f"\n**Timestamp:** | " ) - if case["role_id"] != "0": - role = interaction.guild.get_role(int(case["role_id"])) - if role is not None: - field_value += f"\n**Role:** {role.mention}" - else: - field_value += f"\n**Role:** Deleted Role ({case['role_id']})" + if mod.role_id: + role = await mod.get_role() + field_value += f"\n**Role:** {role.mention} ({role.id})" - if bool(case["resolved"]): + if mod.resolved: field_value += "\n**Resolved:** True" embed.add_field(name=field_name, value=field_value, inline=inline) @@ -1243,39 +1205,14 @@ class Aurora(commands.Cog): ) return - database = connect() - cursor = database.cursor() - - query_1 = ( - f"SELECT * FROM moderation_{interaction.guild.id} WHERE moderation_id = ?;" - ) - cursor.execute(query_1, (case,)) - result_1 = cursor.fetchone() - if result_1 is None or case == 0: + try: + moderation = Moderation.from_sql(interaction.client, case, interaction.guild.id) + except ValueError: await interaction.response.send_message( - content=error(f"There is no moderation with a case number of {case}."), - ephemeral=True, + content=error(f"Case #{case:,} does not exist!"), ephemeral=True ) return - - query_2 = f"SELECT * FROM moderation_{interaction.guild.id} WHERE moderation_id = ? AND resolved = 0;" - cursor.execute(query_2, (case,)) - result_2 = cursor.fetchone() - if result_2 is None: - await interaction.response.send_message( - content=error( - f"This moderation has already been resolved!\nUse `/case {case}` for more information." - ), - ephemeral=True, - ) - return - - case_dict = generate_dict(result_2) - if reason is None: - reason = "No reason given." - - changes: list = case_dict["changes"] - if len(changes) > 25: + if len(moderation.changes) > 25: await interaction.response.send_message( content=error( "Due to limitations with Discord's embed system, you cannot edit a case more than 25 times." @@ -1283,68 +1220,18 @@ class Aurora(commands.Cog): ephemeral=True, ) return - if not changes: - changes.append( - { - "type": "ORIGINAL", - "timestamp": case_dict["timestamp"], - "reason": case_dict["reason"], - "user_id": case_dict["moderator_id"], - } - ) - changes.append( - { - "type": "RESOLVE", - "timestamp": int(time.time()), - "reason": reason, - "user_id": interaction.user.id, - } - ) - if case_dict["moderation_type"] in ["UNMUTE", "UNBAN"]: - await interaction.response.send_message( - content=error("You cannot resolve this type of moderation!"), - ephemeral=True, - ) - return - - if case_dict["moderation_type"] in ["MUTE", "TEMPBAN", "BAN"]: - if case_dict["moderation_type"] == "MUTE": - try: - member = await interaction.guild.fetch_member( - case_dict["target_id"] - ) - - await member.timeout( - None, reason=f"Case #{case:,} resolved by {interaction.user.id}" - ) - except discord.NotFound: - pass - - if case_dict["moderation_type"] in ["TEMPBAN", "BAN"]: - try: - user = await interaction.client.fetch_user(case_dict["target_id"]) - - await interaction.guild.unban( - user, reason=f"Case #{case} resolved by {interaction.user.id}" - ) - except discord.NotFound: - pass - - resolve_query = f"UPDATE `moderation_{interaction.guild.id}` SET resolved = 1, changes = ?, resolved_by = ?, resolve_reason = ? WHERE moderation_id = ?" - else: - resolve_query = f"UPDATE `moderation_{interaction.guild.id}` SET resolved = 1, changes = ?, resolved_by = ?, resolve_reason = ? WHERE moderation_id = ?" - - cursor.execute( - resolve_query, - ( - dumps(changes), - interaction.user.id, - reason, - case_dict["moderation_id"], - ), - ) - database.commit() + try: + await moderation.resolve(interaction.user.id, reason) + except (ValueError, TypeError) as e: + if e == ValueError: + await interaction.response.send_message( + content=error("This case has already been resolved!"), ephemeral=True + ) + elif e == TypeError: + await interaction.response.send_message( + content=error("This case type cannot be resolved!"), ephemeral=True + ) embed = await case_factory( interaction=interaction, @@ -1355,9 +1242,6 @@ class Aurora(commands.Cog): ) await log(interaction, case, resolved=True) - cursor.close() - database.close() - @app_commands.command(name="case") @app_commands.choices( export=[ @@ -1405,67 +1289,69 @@ class Aurora(commands.Cog): or False ) - if case != 0: + try: mod = Moderation.from_sql(interaction.client, case, interaction.guild.id) - if mod: - if export: - if export.value == "file" or len(mod.to_json(2)) > 1800: - filename = ( - str(data_manager.cog_data_path(cog_instance=self)) - + str(os.sep) - + f"moderation_{interaction.guild.id}_case_{case}.json" - ) + except ValueError: + await interaction.response.send_message( + content=error(f"Case #{case:,} does not exist!"), ephemeral=True + ) + return - with open(filename, "w", encoding="utf-8") as f: - mod.to_json(2, f) - if export.value == "codeblock": - content = f"Case #{case:,} exported.\n" + warning( - "Case was too large to export as codeblock, so it has been uploaded as a `.json` file." - ) - else: - content = f"Case #{case:,} exported." + if export: + if export.value == "file" or len(mod.to_json(2)) > 1800: + filename = ( + str(data_manager.cog_data_path(cog_instance=self)) + + str(os.sep) + + f"moderation_{interaction.guild.id}_case_{case}.json" + ) - await interaction.response.send_message( - content=content, - file=discord.File( - filename, - f"moderation_{interaction.guild.id}_case_{case}.json", - ), - ephemeral=ephemeral, - ) - - os.remove(filename) - return - await interaction.response.send_message( - content=box(mod.to_json(2), 'json'), - ephemeral=ephemeral, - ) - return - if changes: - embed = await changes_factory( - interaction=interaction, moderation=mod - ) - await interaction.response.send_message( - embed=embed, ephemeral=ephemeral - ) - elif evidenceformat: - content = await evidenceformat_factory( - interaction=interaction, moderation=mod - ) - await interaction.response.send_message( - content=content, ephemeral=ephemeral + with open(filename, "w", encoding="utf-8") as f: + mod.to_json(2, f) + if export.value == "codeblock": + content = f"Case #{case:,} exported.\n" + warning( + "Case was too large to export as codeblock, so it has been uploaded as a `.json` file." ) else: - embed = await case_factory( - interaction=interaction, moderation=mod - ) - await interaction.response.send_message( - embed=embed, ephemeral=ephemeral - ) + content = f"Case #{case:,} exported." + + await interaction.response.send_message( + content=content, + file=discord.File( + filename, + f"moderation_{interaction.guild.id}_case_{case}.json", + ), + ephemeral=ephemeral, + ) + + os.remove(filename) return - await interaction.response.send_message( - content=f"No case with case number `{case}` found.", ephemeral=True - ) + await interaction.response.send_message( + content=box(mod.to_json(2), 'json'), + ephemeral=ephemeral, + ) + return + if changes: + embed = await changes_factory( + interaction=interaction, moderation=mod + ) + await interaction.response.send_message( + embed=embed, ephemeral=ephemeral + ) + elif evidenceformat: + content = await evidenceformat_factory( + interaction=interaction, moderation=mod + ) + await interaction.response.send_message( + content=content, ephemeral=ephemeral + ) + else: + embed = await case_factory( + interaction=interaction, moderation=mod + ) + await interaction.response.send_message( + embed=embed, ephemeral=ephemeral + ) + return @app_commands.command(name="edit") async def edit( @@ -1498,93 +1384,96 @@ class Aurora(commands.Cog): ) return - if case != 0: + try: moderation = Moderation.from_sql(interaction.client, case, interaction.guild.id) old_moderation = moderation - if moderation: - if len(moderation.changes) > 25: - return await interaction.response.send_message( - content=error( - "Due to limitations with Discord's embed system, you cannot edit a case more than 25 times." - ), - ephemeral=True, - ) - if duration: - moderation.duration = parse_timedelta(duration) - if moderation.duration is None: - return await interaction.response.send_message( - error("Please provide a valid duration!"), ephemeral=True - ) + except ValueError: + await interaction.response.send_message( + content=error(f"Case #{case:,} does not exist!"), ephemeral=True + ) + return - moderation.end_timestamp = moderation.timestamp + moderation.duration.total_seconds() + if len(moderation.changes) > 25: + return await interaction.response.send_message( + content=error( + "Due to limitations with Discord's embed system, you cannot edit a case more than 25 times." + ), + ephemeral=True, + ) - if moderation.type == "MUTE": - if ( - time.time() - moderation.unix_timestamp - ) + moderation.duration.total_seconds() > 2419200: - return await interaction.response.send_message( - error( - "Please provide a duration that is less than 28 days from the initial moderation." - ) - ) - - try: - member = await interaction.guild.fetch_member( - moderation.target_id - ) - - await member.timeout( - moderation.duration, - reason=f"Case #{case:,} edited by {interaction.user.id}", - ) - except discord.NotFound: - pass - - if reason: - moderation.reason = reason - - if not moderation.changes: - moderation.changes.append(Change.from_dict(interaction.client, { - "type": "ORIGINAL", - "timestamp": old_moderation.timestamp, - "reason": old_moderation.reason, - "user_id": old_moderation.moderator_id, - "duration": old_moderation.duration, - "end_timestamp": old_moderation.end_timestamp, - })) - if duration: - moderation.changes.append(Change.from_dict(interaction.client, { - "type": "EDIT", - "timestamp": int(time.time()), - "reason": reason, - "user_id": interaction.user.id, - "duration": moderation.duration, - "end_timestamp": moderation.end_timestamp, - })) - else: - moderation.changes.append(Change.from_dict(interaction.client, { - "type": "EDIT", - "timestamp": int(time.time()), - "reason": reason, - "user_id": interaction.user.id, - "duration": moderation.duration, - "end_timestamp": moderation.end_timestamp, - })) - - moderation.update() - embed = await case_factory(interaction=interaction, moderation=moderation) - - await interaction.response.send_message( - content=f"✅ Moderation #{case:,} edited!", - embed=embed, - ephemeral=True, + if duration: + moderation.duration = parse_timedelta(duration) + if moderation.duration is None: + return await interaction.response.send_message( + error("Please provide a valid duration!"), ephemeral=True ) - await log(interaction, case) - return + moderation.end_timestamp = moderation.timestamp + moderation.duration.total_seconds() + + if moderation.type == "MUTE": + if ( + time.time() - moderation.unix_timestamp + ) + moderation.duration.total_seconds() > 2419200: + return await interaction.response.send_message( + error( + "Please provide a duration that is less than 28 days from the initial moderation." + ) + ) + + try: + member = await interaction.guild.fetch_member( + moderation.target_id + ) + + await member.timeout( + moderation.duration, + reason=f"Case #{case:,} edited by {interaction.user.id}", + ) + except discord.NotFound: + pass + + if reason: + moderation.reason = reason + + if not moderation.changes: + moderation.changes.append(Change.from_dict(interaction.client, { + "type": "ORIGINAL", + "timestamp": old_moderation.timestamp, + "reason": old_moderation.reason, + "user_id": old_moderation.moderator_id, + "duration": old_moderation.duration, + "end_timestamp": old_moderation.end_timestamp, + })) + if duration: + moderation.changes.append(Change.from_dict(interaction.client, { + "type": "EDIT", + "timestamp": int(time.time()), + "reason": reason, + "user_id": interaction.user.id, + "duration": moderation.duration, + "end_timestamp": moderation.end_timestamp, + })) + else: + moderation.changes.append(Change.from_dict(interaction.client, { + "type": "EDIT", + "timestamp": int(time.time()), + "reason": reason, + "user_id": interaction.user.id, + "duration": moderation.duration, + "end_timestamp": moderation.end_timestamp, + })) + + moderation.update() + embed = await case_factory(interaction=interaction, moderation=moderation) + await interaction.response.send_message( - content=error(f"No case with case number `{case}` found."), ephemeral=True + content=f"✅ Moderation #{case:,} edited!", + embed=embed, + ephemeral=True, ) + await log(interaction, case) + + return @tasks.loop(minutes=1) async def handle_expiry(self): diff --git a/aurora/models.py b/aurora/models.py index 6c37bd5..8d42e21 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -90,6 +90,9 @@ class Moderation(AuroraGuildModel): self.resolved_by = resolved_by self.resolve_reason = reason + if self.type in ["UNMUTE", "UNBAN"]: + raise TypeError("Cannot resolve an unmute or unban case!") + if self.type == "MUTE": try: guild: discord.Guild = await self.bot.fetch_guild(self.guild_id) @@ -176,7 +179,7 @@ class Moderation(AuroraGuildModel): return cls(bot=bot, **data) @classmethod - def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> Optional["Moderation"]: + def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": from aurora.utilities.database import connect query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;" @@ -184,13 +187,13 @@ class Moderation(AuroraGuildModel): cursor = database.cursor() cursor.execute(query, (moderation_id,)) result = cursor.fetchone() + cursor.close() - if result: + if result and not moderation_id == 0: case = generate_dict(bot, result, guild_id) - cursor.close() return cls.from_dict(bot, case) - return None + raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") @classmethod def log( @@ -411,6 +414,8 @@ class PartialRole(AuroraGuildModel): @property def mention(self): + if self.name == "Deleted Role" or self.name == "Forbidden Role": + return self.name return f"<@&{self.id}>" def __str__(self): -- 2.45.3 From d7a8fbe36721cb8362f856a554f1038ba5db3f2d Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 16:02:00 -0400 Subject: [PATCH 093/376] fix(aurora): ignore moderations with the id 0 in the history command --- aurora/aurora.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index d764521..e071f15 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -20,7 +20,8 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (box, error, humanize_list, + humanize_timedelta, warning) from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -30,11 +31,17 @@ from aurora.menus.immune import Immune from aurora.menus.overrides import Overrides from aurora.models import Change, Moderation from aurora.utilities.config import config, register_config -from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log -from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed +from aurora.utilities.database import (connect, create_guild_table, fetch_case, + mysql_log) +from aurora.utilities.factory import (addrole_embed, case_factory, + changes_factory, evidenceformat_factory, + guild_embed, immune_embed, + message_factory, overrides_embed) from aurora.utilities.json import dump from aurora.utilities.logger import logger -from aurora.utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from aurora.utilities.utils import (check_moddable, check_permissions, + get_footer_image, log, send_evidenceformat, + timedelta_from_relativedelta) class Aurora(commands.Cog): @@ -1098,18 +1105,19 @@ class Aurora(commands.Cog): if target: query = f"""SELECT * FROM moderation_{interaction.guild.id} - WHERE target_id = ? + WHERE target_id = ? AND moderation_id != 0 ORDER BY moderation_id DESC;""" cursor.execute(query, (target.id,)) elif moderator: query = f"""SELECT * FROM moderation_{interaction.guild.id} - WHERE moderator_id = ? + WHERE moderator_id = ? AND moderation_id != 0 ORDER BY moderation_id DESC;""" cursor.execute(query, (moderator.id,)) else: query = f"""SELECT * FROM moderation_{interaction.guild.id} + WHERE moderation_id != 0 ORDER BY moderation_id DESC;""" cursor.execute(query) @@ -1117,10 +1125,9 @@ class Aurora(commands.Cog): moderation_list: List[Moderation] = [] for result in results: - if result["moderation_id"] != 0: - result.update({"guild_id": interaction.guild.id}) - moderation = Moderation.from_dict(interaction.client, dict(result)) - moderation_list.append(moderation) + result.update({"guild_id": interaction.guild.id}) + moderation = Moderation.from_dict(interaction.client, dict(result)) + moderation_list.append(moderation) case_quantity = len(moderation_list) page_quantity = ceil(case_quantity / pagesize) -- 2.45.3 From 53b67e1c9513c01e9937a961a76855212031d2a8 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 16:07:35 -0400 Subject: [PATCH 094/376] fix(aurora): convert results into a dictionary before making a Moderation instance out of them --- aurora/aurora.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index e071f15..5777031 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -20,8 +20,7 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import (box, error, humanize_list, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -31,17 +30,11 @@ from aurora.menus.immune import Immune from aurora.menus.overrides import Overrides from aurora.models import Change, Moderation from aurora.utilities.config import config, register_config -from aurora.utilities.database import (connect, create_guild_table, fetch_case, - mysql_log) -from aurora.utilities.factory import (addrole_embed, case_factory, - changes_factory, evidenceformat_factory, - guild_embed, immune_embed, - message_factory, overrides_embed) +from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log +from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from aurora.utilities.json import dump from aurora.utilities.logger import logger -from aurora.utilities.utils import (check_moddable, check_permissions, - get_footer_image, log, send_evidenceformat, - timedelta_from_relativedelta) +from aurora.utilities.utils import check_moddable, check_permissions, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta class Aurora(commands.Cog): @@ -1125,8 +1118,8 @@ class Aurora(commands.Cog): moderation_list: List[Moderation] = [] for result in results: - result.update({"guild_id": interaction.guild.id}) - moderation = Moderation.from_dict(interaction.client, dict(result)) + result_dictionary = generate_dict(result) + moderation = Moderation.from_dict(interaction.client, result_dictionary) moderation_list.append(moderation) case_quantity = len(moderation_list) -- 2.45.3 From d7ca5cab46e9cae8a7e962f15e8b8bf3c3d81b35 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 16:34:08 -0400 Subject: [PATCH 095/376] feat(aurora): cleaned up the codebase and fixed a whole bunch of bugs --- aurora/aurora.py | 165 ++++++++++++++++---------------- aurora/importers/galacticbot.py | 19 ++-- aurora/models.py | 42 +++++++- aurora/utilities/database.py | 138 ++------------------------ aurora/utilities/utils.py | 127 +++--------------------- 5 files changed, 148 insertions(+), 343 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 5777031..695320b 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -20,7 +20,8 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (box, error, humanize_list, + humanize_timedelta, warning) from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -30,11 +31,17 @@ from aurora.menus.immune import Immune from aurora.menus.overrides import Overrides from aurora.models import Change, Moderation from aurora.utilities.config import config, register_config -from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log -from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed +from aurora.utilities.database import connect, create_guild_table +from aurora.utilities.factory import (addrole_embed, case_factory, + changes_factory, evidenceformat_factory, + guild_embed, immune_embed, + message_factory, overrides_embed) + from aurora.utilities.json import dump from aurora.utilities.logger import logger -from aurora.utilities.utils import check_moddable, check_permissions, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from aurora.utilities.utils import (check_moddable, check_permissions, + get_footer_image, log, send_evidenceformat, + timedelta_from_relativedelta) class Aurora(commands.Cog): @@ -142,7 +149,7 @@ class Aurora(commands.Cog): if entry.user.id == self.bot.user.id: return - duration = "NULL" + duration = None if entry.reason: reason = entry.reason + " (This action was performed without the bot.)" @@ -175,13 +182,14 @@ class Aurora(commands.Cog): else: return - await mysql_log( + Moderation.log( + self.bot, entry.guild.id, entry.user.id, moderation_type, "USER", entry.target.id, - 0, + None, duration, reason, ) @@ -231,23 +239,22 @@ class Aurora(commands.Cog): except discord.errors.HTTPException: pass - moderation_id = await mysql_log( + moderation = Moderation.log( + interaction.client, interaction.guild.id, interaction.user.id, "NOTE", "USER", target.id, - 0, - "NULL", + None, + None, reason, ) await interaction.edit_original_response( - content=f"{target.mention} has received a note! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" + content=f"{target.mention} has received a note! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" ) - await log(interaction, moderation_id) - - case = await fetch_case(moderation_id, interaction.guild.id) - await send_evidenceformat(interaction, case) + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="warn") async def warn( @@ -290,23 +297,22 @@ class Aurora(commands.Cog): except discord.errors.HTTPException: pass - moderation_id = await mysql_log( + moderation = Moderation.log( + interaction.client, interaction.guild.id, interaction.user.id, "WARN", "USER", target.id, - 0, - "NULL", + None, + None, reason, ) await interaction.edit_original_response( - content=f"{target.mention} has been warned! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" + content=f"{target.mention} has been warned! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" ) - await log(interaction, moderation_id) - - case = await fetch_case(moderation_id, interaction.guild.id) - await send_evidenceformat(interaction, case) + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="addrole") async def addrole( @@ -349,7 +355,7 @@ class Aurora(commands.Cog): ) return else: - parsed_time = "NULL" + parsed_time = None if role.id not in addrole_whitelist: await interaction.response.send_message( @@ -396,7 +402,8 @@ class Aurora(commands.Cog): content=f"{target.mention} has been given the {role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" ) - moderation_id = await mysql_log( + moderation = Moderation.log( + interaction.client, interaction.guild.id, interaction.user.id, "ADDROLE", @@ -407,12 +414,10 @@ class Aurora(commands.Cog): reason, ) await response.edit( - content=f"{target.mention} has been given the {role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`", + content=f"{target.mention} has been given the {role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`", ) - await log(interaction, moderation_id) - - case = await fetch_case(moderation_id, interaction.guild.id) - await send_evidenceformat(interaction, case) + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="removerole") async def removerole( @@ -455,7 +460,7 @@ class Aurora(commands.Cog): ) return else: - parsed_time = "NULL" + parsed_time = None if role.id not in addrole_whitelist: await interaction.response.send_message( @@ -502,7 +507,8 @@ class Aurora(commands.Cog): content=f"{target.mention} has had the {role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" ) - moderation_id = await mysql_log( + moderation = Moderation.log( + interaction.client, interaction.guild.id, interaction.user.id, "REMOVEROLE", @@ -513,12 +519,10 @@ class Aurora(commands.Cog): reason, ) await response.edit( - content=f"{target.mention} has had the {role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`", + content=f"{target.mention} has had the {role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`", ) - await log(interaction, moderation_id) - - case = await fetch_case(moderation_id, interaction.guild.id) - await send_evidenceformat(interaction, case) + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="mute") async def mute( @@ -590,23 +594,22 @@ class Aurora(commands.Cog): except discord.errors.HTTPException: pass - moderation_id = await mysql_log( + moderation = Moderation.log( + interaction.client, interaction.guild.id, interaction.user.id, "MUTE", "USER", target.id, - 0, + None, parsed_time, reason, ) await interaction.edit_original_response( - content=f"{target.mention} has been muted for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" + content=f"{target.mention} has been muted for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" ) - await log(interaction, moderation_id) - - case = await fetch_case(moderation_id, interaction.guild.id) - await send_evidenceformat(interaction, case) + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="unmute") async def unmute( @@ -665,23 +668,22 @@ class Aurora(commands.Cog): except discord.errors.HTTPException: pass - moderation_id = await mysql_log( + moderation = await Moderation.log( + interaction.client, interaction.guild.id, interaction.user.id, "UNMUTE", "USER", target.id, - 0, - "NULL", + None, + None, reason, ) await interaction.edit_original_response( - content=f"{target.mention} has been unmuted! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" + content=f"{target.mention} has been unmuted! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" ) - await log(interaction, moderation_id) - - case = await fetch_case(moderation_id, interaction.guild.id) - await send_evidenceformat(interaction, case) + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="kick") async def kick( @@ -726,23 +728,22 @@ class Aurora(commands.Cog): await target.kick(reason=f"Kicked by {interaction.user.id} for: {reason}") - moderation_id = await mysql_log( + moderation = Moderation.log( + interaction.client, interaction.guild.id, interaction.user.id, "KICK", "USER", target.id, - 0, - "NULL", + None, + None, reason, ) await interaction.edit_original_response( - content=f"{target.mention} has been kicked! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" + content=f"{target.mention} has been kicked! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" ) - await log(interaction, moderation_id) - - case = await fetch_case(moderation_id, interaction.guild.id) - await send_evidenceformat(interaction, case) + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="ban") @app_commands.choices( @@ -834,23 +835,22 @@ class Aurora(commands.Cog): delete_message_seconds=delete_messages_seconds, ) - moderation_id = await mysql_log( + moderation = Moderation.log( + interaction.client, interaction.guild.id, interaction.user.id, "TEMPBAN", "USER", target.id, - 0, + None, parsed_time, reason, ) await interaction.edit_original_response( - content=f"{target.mention} has been banned for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation_id}`)\n**Reason** - `{reason}`" + content=f"{target.mention} has been banned for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation.id}`)\n**Reason** - `{reason}`" ) - await log(interaction, moderation_id) - - case = await fetch_case(moderation_id, interaction.guild.id) - await send_evidenceformat(interaction, case) + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) else: await interaction.response.send_message( content=f"{target.mention} has been banned!\n**Reason** - `{reason}`" @@ -878,7 +878,8 @@ class Aurora(commands.Cog): delete_message_seconds=delete_messages_seconds, ) - moderation_id = await mysql_log( + moderation = Moderation.log( + interaction.client, interaction.guild.id, interaction.user.id, "BAN", @@ -889,12 +890,10 @@ class Aurora(commands.Cog): reason, ) await interaction.edit_original_response( - content=f"{target.mention} has been banned! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" + content=f"{target.mention} has been banned! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" ) - await log(interaction, moderation_id) - - case = await fetch_case(moderation_id, interaction.guild.id) - await send_evidenceformat(interaction, case) + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="unban") async def unban( @@ -955,23 +954,22 @@ class Aurora(commands.Cog): except discord.errors.HTTPException: pass - moderation_id = await mysql_log( + moderation = Moderation.log( + interaction.client, interaction.guild.id, interaction.user.id, "UNBAN", "USER", target.id, - 0, - "NULL", + None, + None, reason, ) await interaction.edit_original_response( - content=f"{target.mention} has been unbanned! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" + content=f"{target.mention} has been unbanned! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" ) - await log(interaction, moderation_id) - - case = await fetch_case(moderation_id, interaction.guild.id) - await send_evidenceformat(interaction, case) + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="history") async def history( @@ -1118,8 +1116,7 @@ class Aurora(commands.Cog): moderation_list: List[Moderation] = [] for result in results: - result_dictionary = generate_dict(result) - moderation = Moderation.from_dict(interaction.client, result_dictionary) + moderation = Moderation.from_result(interaction.client, result, interaction.guild.id) moderation_list.append(moderation) case_quantity = len(moderation_list) @@ -1235,7 +1232,7 @@ class Aurora(commands.Cog): embed = await case_factory( interaction=interaction, - case_dict=await fetch_case(case, interaction.guild.id), + moderation=moderation, ) await interaction.response.send_message( content=f"✅ Moderation #{case:,} resolved!", embed=embed diff --git a/aurora/importers/galacticbot.py b/aurora/importers/galacticbot.py index 3d13b8e..574d5ad 100644 --- a/aurora/importers/galacticbot.py +++ b/aurora/importers/galacticbot.py @@ -7,7 +7,8 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands from redbot.core.utils.chat_formatting import box, warning -from ..utilities.database import connect, create_guild_table, mysql_log +from aurora.models import Change, Moderation +from aurora.utilities.database import connect, create_guild_table class ImportGalacticBotView(ui.View): @@ -99,37 +100,37 @@ class ImportGalacticBotView(ui.View): if resolved_timestamp is None: resolved_timestamp = timestamp changes = [ - { + Change.from_dict({ "type": "ORIGINAL", "reason": case["reason"], "user_id": case["executor"], "timestamp": timestamp, - }, - { + }), + Change.from_dict({ "type": "RESOLVE", "reason": resolved_reason, "user_id": resolved_by, "timestamp": resolved_timestamp, - }, + }), ] else: - resolved = 0 + resolved = None resolved_by = None resolved_reason = None - changes = [] + changes = None if case["reason"] and case["reason"] != "N/A": reason = case["reason"] else: reason = None - await mysql_log( + Moderation.log( self.ctx.guild.id, case["executor"], case["type"], case["targetType"], case["target"], - 0, + None, duration, reason, timestamp=timestamp, diff --git a/aurora/models.py b/aurora/models.py index 8d42e21..0e8e751 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -2,7 +2,7 @@ import json import sqlite3 from datetime import datetime, timedelta from time import time -from typing import Any, Dict, List, Literal, Optional, Union +from typing import Any, Dict, Iterable, List, Literal, Optional, Union import discord from discord import Forbidden, HTTPException, InvalidData, NotFound @@ -10,7 +10,7 @@ from pydantic import BaseModel, ConfigDict from redbot.core.bot import Red from aurora.utilities.logger import logger -from aurora.utilities.utils import generate_dict, get_next_case_number +from aurora.utilities.utils import get_next_case_number class AuroraBaseModel(BaseModel): @@ -178,6 +178,41 @@ class Moderation(AuroraGuildModel): def from_dict(cls, bot: Red, data: dict) -> "Moderation": return cls(bot=bot, **data) + @classmethod + def from_result(bot: Red, result: Iterable, guild_id: int) -> dict: + if result[7] is not None: + hours, minutes, seconds = map(int, result[7].split(':')) + duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) + else: + duration = None + + if result[14] is not None: + changes = json.loads(result[14]) + change_obj_list = [] + for change in changes: + change_obj_list.append(Change.from_dict(bot=bot, data=change)) + + case = { + "moderation_id": int(result[0]), + "guild_id": int(guild_id), + "timestamp": datetime.fromtimestamp(result[1]), + "moderation_type": str(result[2]), + "target_type": str(result[3]), + "target_id": int(result[4]), + "moderator_id": int(result[5]), + "role_id": int(result[6]) if result[6] is not None else None, + "duration": duration, + "end_timestamp": datetime.fromtimestamp(result[8]) if result[8] is not None else None, + "reason": result[9], + "resolved": bool(result[10]), + "resolved_by": result[11], + "resolve_reason": result[12], + "expired": bool(result[13]), + "changes": change_obj_list if result[14] else [], + "metadata": json.loads(result[15].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) if result[15] else {}, + } + return case + @classmethod def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": from aurora.utilities.database import connect @@ -190,8 +225,7 @@ class Moderation(AuroraGuildModel): cursor.close() if result and not moderation_id == 0: - case = generate_dict(bot, result, guild_id) - return cls.from_dict(bot, case) + return cls.from_result(bot, result, guild_id) raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index 88cec8b..588ad35 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -1,15 +1,11 @@ # pylint: disable=cyclic-import import json import sqlite3 -import time -from datetime import datetime, timedelta from discord import Guild from redbot.core import data_manager from .logger import logger -from .utils import (convert_timedelta_to_str, generate_dict, - get_next_case_number) def connect() -> sqlite3.Connection: @@ -79,13 +75,13 @@ async def create_guild_table(guild: Guild): "NULL", 0, 0, + None, + None, + None, + None, 0, - "NULL", - 0, - "NULL", - 0, - "NULL", - "NULL", + None, + None, 0, json.dumps([]), json.dumps({}), @@ -102,125 +98,3 @@ async def create_guild_table(guild: Guild): ) database.close() - - -def mysql_log( - guild_id: str, - author_id: str, - moderation_type: str, - target_type: str, - target_id: int, - role_id: int, - duration: timedelta = None, - reason: str = None, - database: sqlite3.Connection = None, - timestamp: int = None, - resolved: bool = False, - resolved_by: str = None, - resolved_reason: str = None, - expired: bool = None, - changes: list = None, - metadata: dict = None, -) -> int: - if not timestamp: - timestamp = int(time.time()) - - if duration != "NULL" and duration is not None: - end_timedelta = datetime.fromtimestamp(timestamp) + duration - end_timestamp = int(end_timedelta.timestamp()) - - duration = convert_timedelta_to_str(duration) - else: - duration = None - end_timestamp = None - - if not expired: - if int(time.time()) > end_timestamp: - expired = 1 - else: - expired = 0 - - if reason == "NULL": - reason = None - - if resolved_by == "NULL": - resolved_by = None - - if resolved_reason == "NULL": - resolved_reason = None - - if role_id == 0: - role_id = None - - if not database: - database = connect() - close_db = True - else: - close_db = False - cursor = database.cursor() - - moderation_id = get_next_case_number(guild_id=guild_id, cursor=cursor) - - sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - val = ( - moderation_id, - timestamp, - moderation_type, - target_type, - target_id, - author_id, - role_id, - duration, - end_timestamp, - reason, - int(resolved), - resolved_by, - resolved_reason, - expired, - json.dumps(changes if changes else []), - json.dumps(metadata if metadata else {}), - ) - cursor.execute(sql, val) - - cursor.close() - database.commit() - if close_db: - database.close() - - logger.debug( - "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", - guild_id, - moderation_id, - timestamp, - moderation_type, - target_type, - target_id, - author_id, - role_id, - duration, - end_timestamp, - reason, - int(resolved), - resolved_by, - resolved_reason, - expired, - changes, - metadata, - ) - - return moderation_id - - -async def fetch_case(moderation_id: int, guild_id: str) -> dict: - """This method fetches a case from the database and returns the case's dictionary.""" - database = connect() - cursor = database.cursor() - - query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;" - cursor.execute(query, (moderation_id,)) - result = cursor.fetchone() - - cursor.close() - database.close() - - return generate_dict(result) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index fcc8d61..bf3f23b 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -1,13 +1,11 @@ # pylint: disable=cyclic-import -import json from datetime import datetime, timedelta from typing import Optional, Union from dateutil.relativedelta import relativedelta as rd from discord import File, Guild, Interaction, Member, SelectOption, User -from discord.errors import Forbidden, NotFound +from discord.errors import Forbidden from redbot.core import commands, data_manager -from redbot.core.bot import Red from redbot.core.utils.chat_formatting import error from aurora.utilities.config import config @@ -125,123 +123,32 @@ def get_next_case_number(guild_id: str, cursor=None) -> int: return (result[0] + 1) if result else 1 -def generate_dict(bot: Red, result: dict, guild_id: int) -> dict: - from aurora.models import Change - if result[7] is not None: - hours, minutes, seconds = map(int, result[7].split(':')) - duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) - else: - duration = None - - if result[14] is not None: - changes = json.loads(result[14]) - change_obj_list = [] - for change in changes: - change_obj_list.append(Change.from_dict(bot=bot, data=change)) - - case = { - "moderation_id": int(result[0]), - "guild_id": int(guild_id), - "timestamp": datetime.fromtimestamp(result[1]), - "moderation_type": str(result[2]), - "target_type": str(result[3]), - "target_id": int(result[4]), - "moderator_id": int(result[5]), - "role_id": int(result[6]) if result[6] is not None else None, - "duration": duration, - "end_timestamp": datetime.fromtimestamp(result[8]) if result[8] is not None else None, - "reason": result[9], - "resolved": bool(result[10]), - "resolved_by": result[11], - "resolve_reason": result[12], - "expired": bool(result[13]), - "changes": change_obj_list if result[14] else [], - "metadata": json.loads(result[15].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) if result[15] else {}, - } - return case - - -async def fetch_user_dict(client: commands.Bot, user_id: str) -> dict: - """This function returns a dictionary containing either user information or a standard deleted user template.""" - if user_id == "?": - user_dict = {"id": "?", "name": "Unknown User", "discriminator": "0"} - - else: - try: - user = client.get_user(int(user_id)) - if user is None: - user = await client.fetch_user(int(user_id)) - - user_dict = { - "id": user.id, - "name": user.name, - "discriminator": user.discriminator, - } - - except NotFound: - user_dict = { - "id": user_id, - "name": "Deleted User", - "discriminator": "0", - } - - - return user_dict - - -async def fetch_channel_dict(guild: Guild, channel_id: int) -> dict: - """This function returns a dictionary containing either channel information or a standard deleted channel template.""" - try: - channel = guild.get_channel(int(channel_id)) - if not channel: - channel = await guild.fetch_channel(channel_id) - - channel_dict = { - "id": channel.id, - "name": channel.name, - "mention": channel.mention, - } - - except NotFound: - channel_dict = {"id": channel_id, "name": "Deleted Channel", "mention": None} - - return channel_dict - - -async def fetch_role_dict(guild: Guild, role_id: int) -> dict: - """This function returns a dictionary containing either role information or a standard deleted role template.""" - role = guild.get_role(int(role_id)) - if not role: - role_dict = {"id": role_id, "name": "Deleted Role"} - - role_dict = {"id": role.id, "name": role.name} - - return role_dict - - async def log(interaction: Interaction, moderation_id: int, resolved: bool = False) -> None: """This function sends a message to the guild's configured logging channel when an infraction takes place.""" - from .database import fetch_case - from .factory import log_factory + from aurora.models import Moderation + from aurora.utilities.factory import log_factory logging_channel_id = await config.guild(interaction.guild).log_channel() if logging_channel_id != " ": logging_channel = interaction.guild.get_channel(logging_channel_id) - case = await fetch_case(moderation_id, interaction.guild.id) - if case: + try: + moderation = Moderation.from_sql(interaction.client, moderation_id) embed = await log_factory( - interaction=interaction, case_dict=case, resolved=resolved + interaction=interaction, moderation=moderation, resolved=resolved ) try: await logging_channel.send(embed=embed) except Forbidden: return + except ValueError: + return -async def send_evidenceformat(interaction: Interaction, case_dict: dict) -> None: +async def send_evidenceformat(interaction: Interaction, moderation_id: int) -> None: """This function sends an ephemeral message to the moderator who took the moderation action, with a pre-made codeblock for use in the mod-evidence channel.""" - from .factory import evidenceformat_factory + from aurora.models import Moderation + from aurora.utilities.factory import evidenceformat_factory send_evidence_bool = ( await config.user(interaction.user).auto_evidenceformat() @@ -251,19 +158,11 @@ async def send_evidenceformat(interaction: Interaction, case_dict: dict) -> None if send_evidence_bool is False: return - content = await evidenceformat_factory(interaction=interaction, case_dict=case_dict) + moderation = Moderation.from_sql(interaction.client, moderation_id) + content = await evidenceformat_factory(interaction=interaction, moderation=moderation) await interaction.followup.send(content=content, ephemeral=True) -def convert_timedelta_to_str(td: timedelta) -> str: - """This function converts a timedelta object to a string.""" - total_seconds = int(td.total_seconds()) - hours = total_seconds // 3600 - minutes = (total_seconds % 3600) // 60 - seconds = total_seconds % 60 - return f"{hours}:{minutes}:{seconds}" - - def get_bool_emoji(value: Optional[bool]) -> str: """Returns a unicode emoji based on a boolean value.""" if value is True: -- 2.45.3 From c2e017339e37d7217a6e717a078cc80ff4e22a4f Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 16:35:06 -0400 Subject: [PATCH 096/376] fix(aurora): fixed a broken classmethod --- aurora/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models.py b/aurora/models.py index 0e8e751..e1821f0 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -179,7 +179,7 @@ class Moderation(AuroraGuildModel): return cls(bot=bot, **data) @classmethod - def from_result(bot: Red, result: Iterable, guild_id: int) -> dict: + def from_result(cls, bot: Red, result: Iterable, guild_id: int) -> dict: if result[7] is not None: hours, minutes, seconds = map(int, result[7].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) -- 2.45.3 From bb5ab8e61bd5e4ca4f1dcd273cf3731aeb11aab8 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 16:36:27 -0400 Subject: [PATCH 097/376] fix(aurora): make Moderration.from_result() return a Moderation object instead of a dictionary --- aurora/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index e1821f0..f6ef0b9 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -179,7 +179,7 @@ class Moderation(AuroraGuildModel): return cls(bot=bot, **data) @classmethod - def from_result(cls, bot: Red, result: Iterable, guild_id: int) -> dict: + def from_result(cls, bot: Red, result: Iterable, guild_id: int) -> "Moderation": if result[7] is not None: hours, minutes, seconds = map(int, result[7].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) @@ -211,7 +211,7 @@ class Moderation(AuroraGuildModel): "changes": change_obj_list if result[14] else [], "metadata": json.loads(result[15].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) if result[15] else {}, } - return case + return cls.from_dict(bot=bot, data=case) @classmethod def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": -- 2.45.3 From 15ccd5530a461010543a02d6ff9e60aa94af4241 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 16:37:52 -0400 Subject: [PATCH 098/376] fix(aurora): fixed a few unboundlocalerrors --- aurora/aurora.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 695320b..cacee63 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -20,8 +20,7 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import (box, error, humanize_list, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -32,17 +31,10 @@ from aurora.menus.overrides import Overrides from aurora.models import Change, Moderation from aurora.utilities.config import config, register_config from aurora.utilities.database import connect, create_guild_table -from aurora.utilities.factory import (addrole_embed, case_factory, - changes_factory, evidenceformat_factory, - guild_embed, immune_embed, - message_factory, overrides_embed) - +from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from aurora.utilities.json import dump from aurora.utilities.logger import logger -from aurora.utilities.utils import (check_moddable, check_permissions, - get_footer_image, log, send_evidenceformat, - timedelta_from_relativedelta) - +from aurora.utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta class Aurora(commands.Cog): """Aurora is a fully-featured moderation system. @@ -1145,10 +1137,10 @@ class Aurora(commands.Cog): }) moderator = memory_dict[str(mod.moderator_id)] - field_name = f"Case #{case['moderation_id']:,} ({str.title(case['moderation_type'])})" + field_name = f"Case #{mod.id:,} ({str.title(mod.type)})" field_value = f"**Target:** `{target.name}` ({target.id})\n**Moderator:** `{moderator.name}` ({moderator.id})" - if len(case["reason"]) > 125: + if len(mod.reason) > 125: field_value += f"\n**Reason:** `{str(mod.reason)[:125]}...`" else: field_value += f"\n**Reason:** `{str(mod.reason)}`" -- 2.45.3 From 09471a40272e60a9c18bfcad02bd7c52c1248ab8 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 16:39:13 -0400 Subject: [PATCH 099/376] misc(aurora): change the logging severity of Change.from_dict()'s logs to trace --- aurora/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models.py b/aurora/models.py index f6ef0b9..f5f758b 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -360,10 +360,10 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Change": - logger.debug("Creating Change from dict (%s): %s", type(data), data) + logger.trace("Creating Change from dict (%s): %s", type(data), data) if isinstance(data, str): data = json.loads(data) - logger.debug("Change data was a string, converted to dict: %s", data) + logger.trace("Change data was a string, converted to dict: %s", data) if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): hours, minutes, seconds = map(int, data["duration"].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) -- 2.45.3 From ac8cefd779de5c109a1ddf85f174cbd849585f56 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 16:47:21 -0400 Subject: [PATCH 100/376] fix(aurora): pylint fixes --- aurora/aurora.py | 18 ++++++++++++------ aurora/importers/galacticbot.py | 4 ++-- aurora/models.py | 16 ++++++---------- aurora/utilities/factory.py | 11 ++++------- aurora/utilities/json.py | 1 - aurora/utilities/utils.py | 6 +++--- 6 files changed, 27 insertions(+), 29 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index cacee63..6e2e2fc 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -20,7 +20,8 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (box, error, humanize_list, + humanize_timedelta, warning) from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -31,10 +32,17 @@ from aurora.menus.overrides import Overrides from aurora.models import Change, Moderation from aurora.utilities.config import config, register_config from aurora.utilities.database import connect, create_guild_table -from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed +from aurora.utilities.factory import (addrole_embed, case_factory, + changes_factory, evidenceformat_factory, + guild_embed, immune_embed, + message_factory, overrides_embed) + from aurora.utilities.json import dump from aurora.utilities.logger import logger -from aurora.utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from aurora.utilities.utils import (check_moddable, check_permissions, + get_footer_image, log, send_evidenceformat, + timedelta_from_relativedelta) + class Aurora(commands.Cog): """Aurora is a fully-featured moderation system. @@ -1327,9 +1335,7 @@ class Aurora(commands.Cog): embed=embed, ephemeral=ephemeral ) elif evidenceformat: - content = await evidenceformat_factory( - interaction=interaction, moderation=mod - ) + content = await evidenceformat_factory(moderation=mod) await interaction.response.send_message( content=content, ephemeral=ephemeral ) diff --git a/aurora/importers/galacticbot.py b/aurora/importers/galacticbot.py index 574d5ad..4cdc42e 100644 --- a/aurora/importers/galacticbot.py +++ b/aurora/importers/galacticbot.py @@ -100,13 +100,13 @@ class ImportGalacticBotView(ui.View): if resolved_timestamp is None: resolved_timestamp = timestamp changes = [ - Change.from_dict({ + Change.from_dict(interaction.client, { "type": "ORIGINAL", "reason": case["reason"], "user_id": case["executor"], "timestamp": timestamp, }), - Change.from_dict({ + Change.from_dict(interaction.client, { "type": "RESOLVE", "reason": resolved_reason, "user_id": resolved_by, diff --git a/aurora/models.py b/aurora/models.py index f5f758b..ab63be1 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -19,7 +19,7 @@ class AuroraBaseModel(BaseModel): bot: Red def to_json(self, indent: int = None, file: Any = None, **kwargs): - from aurora.utilities.json import dump, dumps + from aurora.utilities.json import dump, dumps # pylint: disable=cyclic-import return dump(self.model_dump(exclude={"bot"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) class AuroraGuildModel(AuroraBaseModel): @@ -27,7 +27,7 @@ class AuroraGuildModel(AuroraBaseModel): guild_id: int def to_json(self, indent: int = None, file: Any = None, **kwargs): - from aurora.utilities.json import dump, dumps + from aurora.utilities.json import dump, dumps # pylint: disable=cyclic-import return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) class Moderation(AuroraGuildModel): @@ -66,8 +66,7 @@ class Moderation(AuroraGuildModel): async def get_target(self) -> Union["PartialUser", "PartialChannel"]: if self.target_type == "USER": return await PartialUser.from_id(self.bot, self.target_id) - else: - return await PartialChannel.from_id(self.bot, self.target_id) + return await PartialChannel.from_id(self.bot, self.target_id) async def get_resolved_by(self) -> Optional["PartialUser"]: if self.resolved_by: @@ -264,10 +263,7 @@ class Moderation(AuroraGuildModel): end_timestamp = None if not expired: - if timestamp > end_timestamp: - expired = True - else: - expired = False + expired = bool(timestamp > end_timestamp) if reason == "NULL": reason = None @@ -422,7 +418,7 @@ class PartialChannel(AuroraGuildModel): @property def mention(self): - if self.name == "Deleted Channel" or self.name == "Forbidden Channel": + if self.name in ["Deleted Channel", "Forbidden Channel"]: return self.name return f"<#{self.id}>" @@ -448,7 +444,7 @@ class PartialRole(AuroraGuildModel): @property def mention(self): - if self.name == "Deleted Role" or self.name == "Forbidden Role": + if self.name in ["Deleted Role", "Forbidden Role"]: return self.name return f"<@&{self.id}>" diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 5977f26..11d00b9 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -2,16 +2,13 @@ from datetime import datetime, timedelta from typing import Union -from discord import (Color, Embed, Guild, Interaction, InteractionMessage, - Member, Role, User) +from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User from redbot.core import commands -from redbot.core.utils.chat_formatting import (bold, box, error, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning from aurora.models import Moderation, PartialUser from aurora.utilities.config import config -from aurora.utilities.utils import (get_bool_emoji, get_next_case_number, - get_pagesize_str) +from aurora.utilities.utils import get_bool_emoji, get_next_case_number, get_pagesize_str async def message_factory( @@ -261,7 +258,7 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E return embed -async def evidenceformat_factory(interaction: Interaction, moderation: Moderation) -> str: +async def evidenceformat_factory(moderation: Moderation) -> str: """This function creates a codeblock in evidence format from set parameters. Args: diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index cad264e..554679d 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -3,7 +3,6 @@ from datetime import datetime, timedelta from redbot.core.bot import Red - from aurora.models import AuroraBaseModel diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index bf3f23b..ca9cc85 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -133,7 +133,7 @@ async def log(interaction: Interaction, moderation_id: int, resolved: bool = Fal logging_channel = interaction.guild.get_channel(logging_channel_id) try: - moderation = Moderation.from_sql(interaction.client, moderation_id) + moderation = Moderation.from_sql(interaction.client, moderation_id, interaction.guild_id) embed = await log_factory( interaction=interaction, moderation=moderation, resolved=resolved ) @@ -158,8 +158,8 @@ async def send_evidenceformat(interaction: Interaction, moderation_id: int) -> N if send_evidence_bool is False: return - moderation = Moderation.from_sql(interaction.client, moderation_id) - content = await evidenceformat_factory(interaction=interaction, moderation=moderation) + moderation = Moderation.from_sql(interaction.client, moderation_id, interaction.guild.id) + content = await evidenceformat_factory(moderation=moderation) await interaction.followup.send(content=content, ephemeral=True) -- 2.45.3 From 7dfe94869c299603e761486552b38158d3fb1df1 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 17:23:59 -0400 Subject: [PATCH 101/376] misc(aurora): codebase cleanup --- aurora/aurora.py | 17 +-- aurora/importers/aurora.py | 2 +- aurora/importers/galacticbot.py | 2 +- aurora/models/base.py | 24 ++++ aurora/models/change.py | 62 +++++++++ aurora/{models.py => models/moderation.py} | 151 +-------------------- aurora/models/partials.py | 79 +++++++++++ aurora/utilities/database.py | 2 +- aurora/utilities/factory.py | 3 +- aurora/utilities/json.py | 2 +- aurora/utilities/utils.py | 4 +- 11 files changed, 183 insertions(+), 165 deletions(-) create mode 100644 aurora/models/base.py create mode 100644 aurora/models/change.py rename aurora/{models.py => models/moderation.py} (65%) create mode 100644 aurora/models/partials.py diff --git a/aurora/aurora.py b/aurora/aurora.py index 6e2e2fc..309bbb7 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -20,8 +20,7 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import (box, error, humanize_list, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -29,20 +28,14 @@ from aurora.menus.addrole import Addrole from aurora.menus.guild import Guild from aurora.menus.immune import Immune from aurora.menus.overrides import Overrides -from aurora.models import Change, Moderation +from aurora.models.change import Change +from aurora.models.moderation import Moderation from aurora.utilities.config import config, register_config from aurora.utilities.database import connect, create_guild_table -from aurora.utilities.factory import (addrole_embed, case_factory, - changes_factory, evidenceformat_factory, - guild_embed, immune_embed, - message_factory, overrides_embed) - +from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from aurora.utilities.json import dump from aurora.utilities.logger import logger -from aurora.utilities.utils import (check_moddable, check_permissions, - get_footer_image, log, send_evidenceformat, - timedelta_from_relativedelta) - +from aurora.utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta class Aurora(commands.Cog): """Aurora is a fully-featured moderation system. diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 0885ee9..7d1b273 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -8,7 +8,7 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands from redbot.core.utils.chat_formatting import box, warning -from aurora.models import Moderation +from aurora.models.moderation import Moderation from aurora.utilities.database import connect, create_guild_table diff --git a/aurora/importers/galacticbot.py b/aurora/importers/galacticbot.py index 4cdc42e..50d51b9 100644 --- a/aurora/importers/galacticbot.py +++ b/aurora/importers/galacticbot.py @@ -7,7 +7,7 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands from redbot.core.utils.chat_formatting import box, warning -from aurora.models import Change, Moderation +from aurora.models.moderation import Change, Moderation from aurora.utilities.database import connect, create_guild_table diff --git a/aurora/models/base.py b/aurora/models/base.py new file mode 100644 index 0000000..31d01ac --- /dev/null +++ b/aurora/models/base.py @@ -0,0 +1,24 @@ +from typing import Any + +from pydantic import BaseModel, ConfigDict +from redbot.core.bot import Red + + +class AuroraBaseModel(BaseModel): + """Base class for all models in Aurora.""" + model_config = ConfigDict(ignored_types=(Red,), arbitrary_types_allowed=True) + bot: Red + + def to_json(self, indent: int = None, file: Any = None, **kwargs): + from aurora.utilities.json import ( # pylint: disable=cyclic-import + dump, dumps) + return dump(self.model_dump(exclude={"bot"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) + +class AuroraGuildModel(AuroraBaseModel): + """Subclass of AuroraBaseModel that includes a guild_id attribute, and a modified to_json() method to match.""" + guild_id: int + + def to_json(self, indent: int = None, file: Any = None, **kwargs): + from aurora.utilities.json import ( # pylint: disable=cyclic-import + dump, dumps) + return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) diff --git a/aurora/models/change.py b/aurora/models/change.py new file mode 100644 index 0000000..ceb4641 --- /dev/null +++ b/aurora/models/change.py @@ -0,0 +1,62 @@ +import json +from datetime import datetime, timedelta +from typing import Literal, Optional + +from redbot.core.bot import Red + +from aurora.models.base import AuroraBaseModel +from aurora.models.partials import PartialUser +from aurora.utilities.logger import logger + + +class Change(AuroraBaseModel): + type: Literal["ORIGINAL", "RESOLVE", "EDIT"] + timestamp: datetime + reason: str + user_id: int + duration: Optional[timedelta] = None + end_timestamp: Optional[datetime] = None + + @property + def unix_timestamp(self) -> int: + return int(self.timestamp.timestamp()) + + def __str__(self): + return f"{self.type} {self.user_id} {self.reason}" + + async def get_user(self) -> "PartialUser": + return await PartialUser.from_id(self.bot, self.user_id) + + @classmethod + def from_dict(cls, bot: Red, data: dict) -> "Change": + logger.trace("Creating Change from dict (%s): %s", type(data), data) + if isinstance(data, str): + data = json.loads(data) + logger.trace("Change data was a string, converted to dict: %s", data) + if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): + hours, minutes, seconds = map(int, data["duration"].split(':')) + duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) + elif "duration" in data and isinstance(data["duration"], timedelta): + duration = data["duration"] + else: + duration = None + + if "end_timestamp" in data and data["end_timestamp"] and not isinstance(data["end_timestamp"], datetime): + end_timestamp = datetime.fromtimestamp(data["end_timestamp"]) + elif "end_timestamp" in data and isinstance(data["end_timestamp"], datetime): + end_timestamp = data["end_timestamp"] + else: + end_timestamp = None + + if not isinstance(data["timestamp"], datetime): + timestamp = datetime.fromtimestamp(data["timestamp"]) + else: + timestamp = data["timestamp"] + + data.update({ + "timestamp": timestamp, + "end_timestamp": end_timestamp, + "duration": duration, + "user_id": int(data["user_id"]) + }) + return cls(bot=bot, **data) diff --git a/aurora/models.py b/aurora/models/moderation.py similarity index 65% rename from aurora/models.py rename to aurora/models/moderation.py index ab63be1..7bea736 100644 --- a/aurora/models.py +++ b/aurora/models/moderation.py @@ -2,34 +2,19 @@ import json import sqlite3 from datetime import datetime, timedelta from time import time -from typing import Any, Dict, Iterable, List, Literal, Optional, Union +from typing import Dict, Iterable, List, Optional, Union import discord -from discord import Forbidden, HTTPException, InvalidData, NotFound -from pydantic import BaseModel, ConfigDict +from discord import NotFound from redbot.core.bot import Red +from aurora.models.base import AuroraGuildModel +from aurora.models.change import Change +from aurora.models.partials import PartialChannel, PartialRole, PartialUser from aurora.utilities.logger import logger from aurora.utilities.utils import get_next_case_number -class AuroraBaseModel(BaseModel): - """Base class for all models in Aurora.""" - model_config = ConfigDict(ignored_types=(Red,), arbitrary_types_allowed=True) - bot: Red - - def to_json(self, indent: int = None, file: Any = None, **kwargs): - from aurora.utilities.json import dump, dumps # pylint: disable=cyclic-import - return dump(self.model_dump(exclude={"bot"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) - -class AuroraGuildModel(AuroraBaseModel): - """Subclass of AuroraBaseModel that includes a guild_id attribute, and a modified to_json() method to match.""" - guild_id: int - - def to_json(self, indent: int = None, file: Any = None, **kwargs): - from aurora.utilities.json import dump, dumps # pylint: disable=cyclic-import - return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) - class Moderation(AuroraGuildModel): moderation_id: int timestamp: datetime @@ -335,129 +320,3 @@ class Moderation(AuroraGuildModel): ) return cls.from_sql(bot=bot, moderation_id=moderation_id, guild_id=guild_id) - -class Change(AuroraBaseModel): - type: Literal["ORIGINAL", "RESOLVE", "EDIT"] - timestamp: datetime - reason: str - user_id: int - duration: Optional[timedelta] = None - end_timestamp: Optional[datetime] = None - - @property - def unix_timestamp(self) -> int: - return int(self.timestamp.timestamp()) - - def __str__(self): - return f"{self.type} {self.user_id} {self.reason}" - - async def get_user(self) -> "PartialUser": - return await PartialUser.from_id(self.bot, self.user_id) - - @classmethod - def from_dict(cls, bot: Red, data: dict) -> "Change": - logger.trace("Creating Change from dict (%s): %s", type(data), data) - if isinstance(data, str): - data = json.loads(data) - logger.trace("Change data was a string, converted to dict: %s", data) - if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): - hours, minutes, seconds = map(int, data["duration"].split(':')) - duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) - elif "duration" in data and isinstance(data["duration"], timedelta): - duration = data["duration"] - else: - duration = None - - if "end_timestamp" in data and data["end_timestamp"] and not isinstance(data["end_timestamp"], datetime): - end_timestamp = datetime.fromtimestamp(data["end_timestamp"]) - elif "end_timestamp" in data and isinstance(data["end_timestamp"], datetime): - end_timestamp = data["end_timestamp"] - else: - end_timestamp = None - - if not isinstance(data["timestamp"], datetime): - timestamp = datetime.fromtimestamp(data["timestamp"]) - else: - timestamp = data["timestamp"] - - data.update({ - "timestamp": timestamp, - "end_timestamp": end_timestamp, - "duration": duration, - "user_id": int(data["user_id"]) - }) - return cls(bot=bot, **data) - -class PartialUser(AuroraBaseModel): - id: int - username: str - discriminator: int - - @property - def name(self): - return f"{self.username}#{self.discriminator}" if self.discriminator != 0 else self.username - - def __str__(self): - return self.name - - @classmethod - async def from_id(cls, bot: Red, user_id: int) -> "PartialUser": - user = bot.get_user(user_id) - if not user: - try: - user = await bot.fetch_user(user_id) - return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator) - except NotFound: - return cls(bot=bot, id=user_id, username="Deleted User", discriminator=0) - return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator) - - -class PartialChannel(AuroraGuildModel): - id: int - name: str - - @property - def mention(self): - if self.name in ["Deleted Channel", "Forbidden Channel"]: - return self.name - return f"<#{self.id}>" - - def __str__(self): - return self.mention - - @classmethod - async def from_id(cls, bot: Red, channel_id: int) -> "PartialChannel": - channel = bot.get_channel(channel_id) - if not channel: - try: - channel = await bot.fetch_channel(channel_id) - return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, username=channel.name) - except (NotFound, InvalidData, HTTPException, Forbidden) as e: - if e == Forbidden: - return cls(bot=bot, guild_id=0, id=channel_id, name="Forbidden Channel") - return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel") - return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, username=channel.name) - -class PartialRole(AuroraGuildModel): - id: int - name: str - - @property - def mention(self): - if self.name in ["Deleted Role", "Forbidden Role"]: - return self.name - return f"<@&{self.id}>" - - def __str__(self): - return self.mention - - @classmethod - async def from_id(cls, bot: Red, guild_id: int, role_id: int) -> "PartialRole": - try: - guild = await bot.fetch_guild(guild_id, with_counts=False) - except (Forbidden, HTTPException): - return cls(bot=bot, guild_id=guild_id, id=role_id, name="Forbidden Role") - role = guild.get_role(role_id) - if not role: - return cls(bot=bot, guild_id=guild_id, id=role_id, name="Deleted Role") - return cls(bot=bot, guild_id=guild_id, id=role.id, name=role.name) diff --git a/aurora/models/partials.py b/aurora/models/partials.py new file mode 100644 index 0000000..48ff2a0 --- /dev/null +++ b/aurora/models/partials.py @@ -0,0 +1,79 @@ +from discord import Forbidden, HTTPException, InvalidData, NotFound +from redbot.core.bot import Red + +from aurora.models.base import AuroraBaseModel, AuroraGuildModel + + +class PartialUser(AuroraBaseModel): + id: int + username: str + discriminator: int + + @property + def name(self): + return f"{self.username}#{self.discriminator}" if self.discriminator != 0 else self.username + + def __str__(self): + return self.name + + @classmethod + async def from_id(cls, bot: Red, user_id: int) -> "PartialUser": + user = bot.get_user(user_id) + if not user: + try: + user = await bot.fetch_user(user_id) + return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator) + except NotFound: + return cls(bot=bot, id=user_id, username="Deleted User", discriminator=0) + return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator) + + +class PartialChannel(AuroraGuildModel): + id: int + name: str + + @property + def mention(self): + if self.name in ["Deleted Channel", "Forbidden Channel"]: + return self.name + return f"<#{self.id}>" + + def __str__(self): + return self.mention + + @classmethod + async def from_id(cls, bot: Red, channel_id: int) -> "PartialChannel": + channel = bot.get_channel(channel_id) + if not channel: + try: + channel = await bot.fetch_channel(channel_id) + return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, username=channel.name) + except (NotFound, InvalidData, HTTPException, Forbidden) as e: + if e == Forbidden: + return cls(bot=bot, guild_id=0, id=channel_id, name="Forbidden Channel") + return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel") + return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, username=channel.name) + +class PartialRole(AuroraGuildModel): + id: int + name: str + + @property + def mention(self): + if self.name in ["Deleted Role", "Forbidden Role"]: + return self.name + return f"<@&{self.id}>" + + def __str__(self): + return self.mention + + @classmethod + async def from_id(cls, bot: Red, guild_id: int, role_id: int) -> "PartialRole": + try: + guild = await bot.fetch_guild(guild_id, with_counts=False) + except (Forbidden, HTTPException): + return cls(bot=bot, guild_id=guild_id, id=role_id, name="Forbidden Role") + role = guild.get_role(role_id) + if not role: + return cls(bot=bot, guild_id=guild_id, id=role_id, name="Deleted Role") + return cls(bot=bot, guild_id=guild_id, id=role.id, name=role.name) diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index 588ad35..16f8a7e 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -5,7 +5,7 @@ import sqlite3 from discord import Guild from redbot.core import data_manager -from .logger import logger +from aurora.utilities.logger import logger def connect() -> sqlite3.Connection: diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 11d00b9..1b508bc 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -6,7 +6,8 @@ from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member from redbot.core import commands from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning -from aurora.models import Moderation, PartialUser +from aurora.models.moderation import Moderation +from aurora.models.partials import PartialUser from aurora.utilities.config import config from aurora.utilities.utils import get_bool_emoji, get_next_case_number, get_pagesize_str diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index 554679d..73595ee 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -3,7 +3,7 @@ from datetime import datetime, timedelta from redbot.core.bot import Red -from aurora.models import AuroraBaseModel +from aurora.models.base import AuroraBaseModel class JSONEncoder(json.JSONEncoder): diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index ca9cc85..e85fd58 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -125,7 +125,7 @@ def get_next_case_number(guild_id: str, cursor=None) -> int: async def log(interaction: Interaction, moderation_id: int, resolved: bool = False) -> None: """This function sends a message to the guild's configured logging channel when an infraction takes place.""" - from aurora.models import Moderation + from aurora.models.moderation import Moderation from aurora.utilities.factory import log_factory logging_channel_id = await config.guild(interaction.guild).log_channel() @@ -147,7 +147,7 @@ async def log(interaction: Interaction, moderation_id: int, resolved: bool = Fal async def send_evidenceformat(interaction: Interaction, moderation_id: int) -> None: """This function sends an ephemeral message to the moderator who took the moderation action, with a pre-made codeblock for use in the mod-evidence channel.""" - from aurora.models import Moderation + from aurora.models.moderation import Moderation from aurora.utilities.factory import evidenceformat_factory send_evidence_bool = ( -- 2.45.3 From 2b79e3b6a8baf83134da9bdcba1c2c95a36d48d5 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 17:29:57 -0400 Subject: [PATCH 102/376] fix(aurora): added an __init__.py to a directory that was missing one --- aurora/models/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 aurora/models/__init__.py diff --git a/aurora/models/__init__.py b/aurora/models/__init__.py new file mode 100644 index 0000000..e69de29 -- 2.45.3 From c69b3cd032a5a192b54afdacab9a05f26750e7de Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 17:33:28 -0400 Subject: [PATCH 103/376] misc(aurora): import change --- aurora/aurora.py | 14 +++++++++++--- aurora/utilities/factory.py | 9 ++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 309bbb7..3eb5a2e 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -20,7 +20,8 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (box, error, humanize_list, + humanize_timedelta, warning) from aurora.importers.aurora import ImportAuroraView from aurora.importers.galacticbot import ImportGalacticBotView @@ -32,10 +33,17 @@ from aurora.models.change import Change from aurora.models.moderation import Moderation from aurora.utilities.config import config, register_config from aurora.utilities.database import connect, create_guild_table -from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed +from aurora.utilities.factory import (addrole_embed, case_factory, + changes_factory, evidenceformat_factory, + guild_embed, immune_embed, + message_factory, overrides_embed) + from aurora.utilities.json import dump from aurora.utilities.logger import logger -from aurora.utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from aurora.utilities.utils import (check_moddable, check_permissions, + get_footer_image, log, send_evidenceformat, + timedelta_from_relativedelta) + class Aurora(commands.Cog): """Aurora is a fully-featured moderation system. diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 1b508bc..d5978c7 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -2,14 +2,17 @@ from datetime import datetime, timedelta from typing import Union -from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User +from discord import (Color, Embed, Guild, Interaction, InteractionMessage, + Member, Role, User) from redbot.core import commands -from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (bold, box, error, + humanize_timedelta, warning) from aurora.models.moderation import Moderation from aurora.models.partials import PartialUser from aurora.utilities.config import config -from aurora.utilities.utils import get_bool_emoji, get_next_case_number, get_pagesize_str +from aurora.utilities.utils import (get_bool_emoji, get_next_case_number, + get_pagesize_str) async def message_factory( -- 2.45.3 From 260dd3ef4c737ccce840986969fc7ae60b770a10 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 17:35:43 -0400 Subject: [PATCH 104/376] fix(aurora): fixing a ModuleNotFound error --- aurora/__init__.py | 2 +- aurora/aurora.py | 18 +++++------------- aurora/importers/{aurora.py => auroraview.py} | 0 .../{galacticbot.py => galacticbotview.py} | 0 4 files changed, 6 insertions(+), 14 deletions(-) rename aurora/importers/{aurora.py => auroraview.py} (100%) rename aurora/importers/{galacticbot.py => galacticbotview.py} (100%) diff --git a/aurora/__init__.py b/aurora/__init__.py index 49ef5ec..a66006c 100644 --- a/aurora/__init__.py +++ b/aurora/__init__.py @@ -1,4 +1,4 @@ -from .aurora import Aurora +from aurora.aurora import Aurora async def setup(bot): diff --git a/aurora/aurora.py b/aurora/aurora.py index 3eb5a2e..4d7780f 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -20,11 +20,10 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import (box, error, humanize_list, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning -from aurora.importers.aurora import ImportAuroraView -from aurora.importers.galacticbot import ImportGalacticBotView +from aurora.importers.auroraview import ImportAuroraView +from aurora.importers.galacticbotview import ImportGalacticBotView from aurora.menus.addrole import Addrole from aurora.menus.guild import Guild from aurora.menus.immune import Immune @@ -33,17 +32,10 @@ from aurora.models.change import Change from aurora.models.moderation import Moderation from aurora.utilities.config import config, register_config from aurora.utilities.database import connect, create_guild_table -from aurora.utilities.factory import (addrole_embed, case_factory, - changes_factory, evidenceformat_factory, - guild_embed, immune_embed, - message_factory, overrides_embed) - +from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from aurora.utilities.json import dump from aurora.utilities.logger import logger -from aurora.utilities.utils import (check_moddable, check_permissions, - get_footer_image, log, send_evidenceformat, - timedelta_from_relativedelta) - +from aurora.utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta class Aurora(commands.Cog): """Aurora is a fully-featured moderation system. diff --git a/aurora/importers/aurora.py b/aurora/importers/auroraview.py similarity index 100% rename from aurora/importers/aurora.py rename to aurora/importers/auroraview.py diff --git a/aurora/importers/galacticbot.py b/aurora/importers/galacticbotview.py similarity index 100% rename from aurora/importers/galacticbot.py rename to aurora/importers/galacticbotview.py -- 2.45.3 From bcc4aa384f7f4d92f89c6b4f75588397a29f90ce Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 17:41:14 -0400 Subject: [PATCH 105/376] fix(aurora): hopefully fixed the module not found issue? --- aurora/__init__.py | 2 +- aurora/{aurora.py => main.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename aurora/{aurora.py => main.py} (100%) diff --git a/aurora/__init__.py b/aurora/__init__.py index a66006c..c9a519d 100644 --- a/aurora/__init__.py +++ b/aurora/__init__.py @@ -1,4 +1,4 @@ -from aurora.aurora import Aurora +from aurora.main import Aurora async def setup(bot): diff --git a/aurora/aurora.py b/aurora/main.py similarity index 100% rename from aurora/aurora.py rename to aurora/main.py -- 2.45.3 From 946e14ee3c9d80a234f74a419a603f51440ec5eb Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 20:45:22 -0400 Subject: [PATCH 106/376] fix(aurora): something idk --- aurora/__init__.py | 2 +- aurora/{main.py => aurora.py} | 18 +++++-- aurora/importers/{auroraview.py => aurora.py} | 0 .../{galacticbotview.py => galacticbot.py} | 0 poetry.lock | 48 ++++++++++++++++++- pyproject.toml | 1 + 6 files changed, 62 insertions(+), 7 deletions(-) rename aurora/{main.py => aurora.py} (98%) rename aurora/importers/{auroraview.py => aurora.py} (100%) rename aurora/importers/{galacticbotview.py => galacticbot.py} (100%) diff --git a/aurora/__init__.py b/aurora/__init__.py index c9a519d..a66006c 100644 --- a/aurora/__init__.py +++ b/aurora/__init__.py @@ -1,4 +1,4 @@ -from aurora.main import Aurora +from aurora.aurora import Aurora async def setup(bot): diff --git a/aurora/main.py b/aurora/aurora.py similarity index 98% rename from aurora/main.py rename to aurora/aurora.py index 4d7780f..3eb5a2e 100644 --- a/aurora/main.py +++ b/aurora/aurora.py @@ -20,10 +20,11 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import (box, error, humanize_list, + humanize_timedelta, warning) -from aurora.importers.auroraview import ImportAuroraView -from aurora.importers.galacticbotview import ImportGalacticBotView +from aurora.importers.aurora import ImportAuroraView +from aurora.importers.galacticbot import ImportGalacticBotView from aurora.menus.addrole import Addrole from aurora.menus.guild import Guild from aurora.menus.immune import Immune @@ -32,10 +33,17 @@ from aurora.models.change import Change from aurora.models.moderation import Moderation from aurora.utilities.config import config, register_config from aurora.utilities.database import connect, create_guild_table -from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed +from aurora.utilities.factory import (addrole_embed, case_factory, + changes_factory, evidenceformat_factory, + guild_embed, immune_embed, + message_factory, overrides_embed) + from aurora.utilities.json import dump from aurora.utilities.logger import logger -from aurora.utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from aurora.utilities.utils import (check_moddable, check_permissions, + get_footer_image, log, send_evidenceformat, + timedelta_from_relativedelta) + class Aurora(commands.Cog): """Aurora is a fully-featured moderation system. diff --git a/aurora/importers/auroraview.py b/aurora/importers/aurora.py similarity index 100% rename from aurora/importers/auroraview.py rename to aurora/importers/aurora.py diff --git a/aurora/importers/galacticbotview.py b/aurora/importers/galacticbot.py similarity index 100% rename from aurora/importers/galacticbotview.py rename to aurora/importers/galacticbot.py diff --git a/poetry.lock b/poetry.lock index 0a5918b..6f6d265 100644 --- a/poetry.lock +++ b/poetry.lock @@ -195,6 +195,20 @@ files = [ {file = "apsw-3.45.2.0.tar.gz", hash = "sha256:4fe81f5e390969d08d3048f357a68b347316b8f09455ff4657d94c56acfa255c"}, ] +[[package]] +name = "argcomplete" +version = "3.3.0" +description = "Bash tab completion for argparse" +optional = false +python-versions = ">=3.8" +files = [ + {file = "argcomplete-3.3.0-py3-none-any.whl", hash = "sha256:c168c3723482c031df3c207d4ba8fa702717ccb9fc0bfe4117166c1f537b4a54"}, + {file = "argcomplete-3.3.0.tar.gz", hash = "sha256:fd03ff4a5b9e6580569d34b273f741e85cd9e072f3feeeee3eba4891c70eda62"}, +] + +[package.extras] +test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] + [[package]] name = "astroid" version = "3.1.0" @@ -1491,6 +1505,24 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa typing = ["typing-extensions"] xmp = ["defusedxml"] +[[package]] +name = "pipx" +version = "1.5.0" +description = "Install and Run Python Applications in Isolated Environments" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pipx-1.5.0-py3-none-any.whl", hash = "sha256:801a55a9d58004bb18a464f668508e79fbffc22deb6f07982832d3ce3ff3756d"}, + {file = "pipx-1.5.0.tar.gz", hash = "sha256:2371af2b772954cdb5c1dbfa0170219e3d2c09d9ff9b18e975f65562eeb7ab0a"}, +] + +[package.dependencies] +argcomplete = ">=1.9.4" +colorama = {version = ">=0.4.4", markers = "sys_platform == \"win32\""} +packaging = ">=20" +platformdirs = ">=2.1" +userpath = ">=1.6,<1.9.0 || >1.9.0" + [[package]] name = "platformdirs" version = "4.2.0" @@ -2262,6 +2294,20 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "userpath" +version = "1.9.2" +description = "Cross-platform tool for adding locations to the user PATH" +optional = false +python-versions = ">=3.7" +files = [ + {file = "userpath-1.9.2-py3-none-any.whl", hash = "sha256:2cbf01a23d655a1ff8fc166dfb78da1b641d1ceabf0fe5f970767d380b14e89d"}, + {file = "userpath-1.9.2.tar.gz", hash = "sha256:6c52288dab069257cc831846d15d48133522455d4677ee69a9781f11dbefd815"}, +] + +[package.dependencies] +click = "*" + [[package]] name = "uvloop" version = "0.19.0" @@ -2545,4 +2591,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "67eb5e616951979332b6f32bcb39d85171cbf8377f566ea1862c51b5068b52f3" +content-hash = "25dce93989e94b49932b4f5bb8489eb37b2e9aa5860679f7150e2beca8b0471c" diff --git a/pyproject.toml b/pyproject.toml index 91c350e..507b821 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ optional = true [tool.poetry.group.dev.dependencies] ruff = "^0.3.1" pylint = "^3.1.0" +pipx = "^1.5.0" [tool.poetry.group.docs] optional = true -- 2.45.3 From ab878739c4eecdfe92077a47b438270d9ab02adc Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 21:04:08 -0400 Subject: [PATCH 107/376] misc(aurora): pep 604 compliance --- aurora/aurora.py | 48 ++++++++++++++++++------------------- aurora/menus/addrole.py | 2 +- aurora/menus/guild.py | 2 +- aurora/menus/immune.py | 2 +- aurora/menus/overrides.py | 2 +- aurora/models/base.py | 4 ++-- aurora/models/moderation.py | 18 +++++++------- aurora/utilities/factory.py | 8 +++---- aurora/utilities/utils.py | 4 ++-- 9 files changed, 45 insertions(+), 45 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 3eb5a2e..fe9abcb 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -205,7 +205,7 @@ class Aurora(commands.Cog): interaction: discord.Interaction, target: discord.User, reason: str, - silent: bool = None, + silent: bool | None = None, ): """Add a note to a user. @@ -263,7 +263,7 @@ class Aurora(commands.Cog): interaction: discord.Interaction, target: discord.Member, reason: str, - silent: bool = None, + silent: bool | None = None, ): """Warn a user. @@ -322,8 +322,8 @@ class Aurora(commands.Cog): target: discord.Member, role: discord.Role, reason: str, - duration: str = None, - silent: bool = None, + duration: str | None = None, + silent: bool | None = None, ): """Add a role to a user. @@ -427,8 +427,8 @@ class Aurora(commands.Cog): target: discord.Member, role: discord.Role, reason: str, - duration: str = None, - silent: bool = None, + duration: str | None = None, + silent: bool | None = None, ): """Remove a role from a user. @@ -532,7 +532,7 @@ class Aurora(commands.Cog): target: discord.Member, duration: str, reason: str, - silent: bool = None, + silent: bool | None = None, ): """Mute a user. @@ -617,8 +617,8 @@ class Aurora(commands.Cog): self, interaction: discord.Interaction, target: discord.Member, - reason: str = None, - silent: bool = None, + reason: str | None = None, + silent: bool | None = None, ): """Unmute a user. @@ -692,7 +692,7 @@ class Aurora(commands.Cog): interaction: discord.Interaction, target: discord.Member, reason: str, - silent: bool = None, + silent: bool | None = None, ): """Kick a user. @@ -762,9 +762,9 @@ class Aurora(commands.Cog): interaction: discord.Interaction, target: discord.User, reason: str, - duration: str = None, - delete_messages: Choice[int] = None, - silent: bool = None, + duration: str | None = None, + delete_messages: Choice[int] | None = None, + silent: bool | None = None, ): """Ban a user. @@ -901,8 +901,8 @@ class Aurora(commands.Cog): self, interaction: discord.Interaction, target: discord.User, - reason: str = None, - silent: bool = None, + reason: str | None = None, + silent: bool | None = None, ): """Unban a user. @@ -976,12 +976,12 @@ class Aurora(commands.Cog): async def history( self, interaction: discord.Interaction, - target: discord.User = None, - moderator: discord.User = None, - pagesize: app_commands.Range[int, 1, 20] = None, + target: discord.User | None = None, + moderator: discord.User | None = None, + pagesize: app_commands.Range[int, 1, 20] | None = None, page: int = 1, - ephemeral: bool = None, - inline: bool = None, + ephemeral: bool | None = None, + inline: bool | None = None, export: bool = False, ): """List previous infractions. @@ -1179,7 +1179,7 @@ class Aurora(commands.Cog): @app_commands.command(name="resolve") async def resolve( - self, interaction: discord.Interaction, case: int, reason: str = None + self, interaction: discord.Interaction, case: int, reason: str | None = None ): """Resolve a specific case. @@ -1251,10 +1251,10 @@ class Aurora(commands.Cog): self, interaction: discord.Interaction, case: int, - ephemeral: bool = None, + ephemeral: bool | None = None, evidenceformat: bool = False, changes: bool = False, - export: Choice[str] = None, + export: Choice[str] | None = None, ): """Check the details of a specific case. @@ -1355,7 +1355,7 @@ class Aurora(commands.Cog): interaction: discord.Interaction, case: int, reason: str, - duration: str = None, + duration: str | None = None, ): """Edit the reason of a specific case. diff --git a/aurora/menus/addrole.py b/aurora/menus/addrole.py index 11f6b32..9f4d1ff 100644 --- a/aurora/menus/addrole.py +++ b/aurora/menus/addrole.py @@ -7,7 +7,7 @@ from aurora.utilities.factory import addrole_embed class Addrole(ui.View): - def __init__(self, ctx: commands.Context, message: Message, timeout: int = None): + def __init__(self, ctx: commands.Context, message: Message, timeout: int | None = None): super().__init__() self.ctx = ctx self.message = message diff --git a/aurora/menus/guild.py b/aurora/menus/guild.py index f99e552..ece8131 100644 --- a/aurora/menus/guild.py +++ b/aurora/menus/guild.py @@ -7,7 +7,7 @@ from aurora.utilities.utils import create_pagesize_options class Guild(ui.View): - def __init__(self, ctx: commands.Context, message: Message, timeout: int = None): + def __init__(self, ctx: commands.Context, message: Message, timeout: int | None = None): super().__init__() self.ctx = ctx self.message = message diff --git a/aurora/menus/immune.py b/aurora/menus/immune.py index 2a5c007..7d85d12 100644 --- a/aurora/menus/immune.py +++ b/aurora/menus/immune.py @@ -7,7 +7,7 @@ from aurora.utilities.factory import immune_embed class Immune(ui.View): - def __init__(self, ctx: commands.Context, message: Message, timeout: int = None): + def __init__(self, ctx: commands.Context, message: Message, timeout: int | None = None): super().__init__() self.ctx = ctx self.message = message diff --git a/aurora/menus/overrides.py b/aurora/menus/overrides.py index c5d0e68..beefaef 100644 --- a/aurora/menus/overrides.py +++ b/aurora/menus/overrides.py @@ -7,7 +7,7 @@ from aurora.utilities.utils import create_pagesize_options class Overrides(ui.View): - def __init__(self, ctx: commands.Context, message: Message, timeout: int = None): + def __init__(self, ctx: commands.Context, message: Message, timeout: int | None = None): super().__init__() self.ctx = ctx self.message = message diff --git a/aurora/models/base.py b/aurora/models/base.py index 31d01ac..45c8a60 100644 --- a/aurora/models/base.py +++ b/aurora/models/base.py @@ -9,7 +9,7 @@ class AuroraBaseModel(BaseModel): model_config = ConfigDict(ignored_types=(Red,), arbitrary_types_allowed=True) bot: Red - def to_json(self, indent: int = None, file: Any = None, **kwargs): + def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs): from aurora.utilities.json import ( # pylint: disable=cyclic-import dump, dumps) return dump(self.model_dump(exclude={"bot"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) @@ -18,7 +18,7 @@ class AuroraGuildModel(AuroraBaseModel): """Subclass of AuroraBaseModel that includes a guild_id attribute, and a modified to_json() method to match.""" guild_id: int - def to_json(self, indent: int = None, file: Any = None, **kwargs): + def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs): from aurora.utilities.json import ( # pylint: disable=cyclic-import dump, dumps) return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 7bea736..11678b6 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -223,16 +223,16 @@ class Moderation(AuroraGuildModel): target_type: str, target_id: int, role_id: int, - duration: timedelta = None, - reason: str = None, - database: sqlite3.Connection = None, - timestamp: datetime = None, + duration: timedelta | None = None, + reason: str | None = None, + database: sqlite3.Connection | None = None, + timestamp: datetime | None = None, resolved: bool = False, - resolved_by: int = None, - resolved_reason: str = None, - expired: bool = None, - changes: list = None, - metadata: dict = None, + resolved_by: int | None = None, + resolved_reason: str | None = None, + expired: bool | None = None, + changes: list | None = None, + metadata: dict | None = None, ) -> "Moderation": from aurora.utilities.database import connect from aurora.utilities.json import dumps diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index d5978c7..e7886ff 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -20,10 +20,10 @@ async def message_factory( guild: Guild, reason: str, moderation_type: str, - moderator: Union[Member, User] = None, - duration: timedelta = None, - response: InteractionMessage = None, - role: Role = None, + moderator: Union[Member, User] | None = None, + duration: timedelta | None = None, + response: InteractionMessage | None = None, + role: Role | None = None, ) -> Embed: """This function creates a message from set parameters, meant for contacting the moderated user. diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index e85fd58..ff950b1 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -14,8 +14,8 @@ from aurora.utilities.config import config def check_permissions( user: User, permissions: list, - ctx: Union[commands.Context, Interaction] = None, - guild: Guild = None, + ctx: Union[commands.Context, Interaction] | None = None, + guild: Guild | None = None, ) -> Union[bool, str]: """Checks if a user has a specific permission (or a list of permissions) in a channel.""" if ctx: -- 2.45.3 From d91a4f49f9bc36d4d751012f6e6a91ede2912a73 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 21:39:43 -0400 Subject: [PATCH 108/376] fix(aurora): fixed import errors --- aurora/aurora.py | 38 ++++++++++++++++----------------- aurora/importers/aurora.py | 4 ++-- aurora/importers/galacticbot.py | 4 ++-- aurora/menus/addrole.py | 4 ++-- aurora/menus/guild.py | 6 +++--- aurora/menus/immune.py | 4 ++-- aurora/menus/overrides.py | 6 +++--- aurora/models/change.py | 6 +++--- aurora/models/moderation.py | 10 ++++----- aurora/models/partials.py | 2 +- aurora/utilities/database.py | 2 +- aurora/utilities/factory.py | 16 ++++++-------- aurora/utilities/json.py | 2 +- aurora/utilities/utils.py | 12 +++++------ 14 files changed, 55 insertions(+), 61 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index fe9abcb..01655a9 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -23,26 +23,24 @@ from redbot.core.commands.converter import parse_relativedelta, parse_timedelta from redbot.core.utils.chat_formatting import (box, error, humanize_list, humanize_timedelta, warning) -from aurora.importers.aurora import ImportAuroraView -from aurora.importers.galacticbot import ImportGalacticBotView -from aurora.menus.addrole import Addrole -from aurora.menus.guild import Guild -from aurora.menus.immune import Immune -from aurora.menus.overrides import Overrides -from aurora.models.change import Change -from aurora.models.moderation import Moderation -from aurora.utilities.config import config, register_config -from aurora.utilities.database import connect, create_guild_table -from aurora.utilities.factory import (addrole_embed, case_factory, - changes_factory, evidenceformat_factory, - guild_embed, immune_embed, - message_factory, overrides_embed) - -from aurora.utilities.json import dump -from aurora.utilities.logger import logger -from aurora.utilities.utils import (check_moddable, check_permissions, - get_footer_image, log, send_evidenceformat, - timedelta_from_relativedelta) +from .importers.aurora import ImportAuroraView +from .importers.galacticbot import ImportGalacticBotView +from .menus.addrole import Addrole +from .menus.guild import Guild +from .menus.immune import Immune +from .menus.overrides import Overrides +from .models.change import Change +from .models.moderation import Moderation +from .utilities.config import config, register_config +from .utilities.database import connect, create_guild_table +from .utilities.factory import (addrole_embed, case_factory, changes_factory, + evidenceformat_factory, guild_embed, + immune_embed, message_factory, overrides_embed) +from .utilities.json import dump +from .utilities.logger import logger +from .utilities.utils import (check_moddable, check_permissions, + get_footer_image, log, send_evidenceformat, + timedelta_from_relativedelta) class Aurora(commands.Cog): diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 7d1b273..e9622a4 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -8,8 +8,8 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands from redbot.core.utils.chat_formatting import box, warning -from aurora.models.moderation import Moderation -from aurora.utilities.database import connect, create_guild_table +from ..models.moderation import Moderation +from ..utilities.database import connect, create_guild_table class ImportAuroraView(ui.View): diff --git a/aurora/importers/galacticbot.py b/aurora/importers/galacticbot.py index 50d51b9..a7c2d27 100644 --- a/aurora/importers/galacticbot.py +++ b/aurora/importers/galacticbot.py @@ -7,8 +7,8 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands from redbot.core.utils.chat_formatting import box, warning -from aurora.models.moderation import Change, Moderation -from aurora.utilities.database import connect, create_guild_table +from ..models.moderation import Change, Moderation +from ..utilities.database import connect, create_guild_table class ImportGalacticBotView(ui.View): diff --git a/aurora/menus/addrole.py b/aurora/menus/addrole.py index 9f4d1ff..36c9056 100644 --- a/aurora/menus/addrole.py +++ b/aurora/menus/addrole.py @@ -2,8 +2,8 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands from redbot.core.utils.chat_formatting import error -from aurora.utilities.config import config -from aurora.utilities.factory import addrole_embed +from ..utilities.config import config +from ..utilities.factory import addrole_embed class Addrole(ui.View): diff --git a/aurora/menus/guild.py b/aurora/menus/guild.py index ece8131..71186b7 100644 --- a/aurora/menus/guild.py +++ b/aurora/menus/guild.py @@ -1,9 +1,9 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands -from aurora.utilities.config import config -from aurora.utilities.factory import guild_embed -from aurora.utilities.utils import create_pagesize_options +from ..utilities.config import config +from ..utilities.factory import guild_embed +from ..utilities.utils import create_pagesize_options class Guild(ui.View): diff --git a/aurora/menus/immune.py b/aurora/menus/immune.py index 7d85d12..dd710b1 100644 --- a/aurora/menus/immune.py +++ b/aurora/menus/immune.py @@ -2,8 +2,8 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands from redbot.core.utils.chat_formatting import error -from aurora.utilities.config import config -from aurora.utilities.factory import immune_embed +from ..utilities.config import config +from ..utilities.factory import immune_embed class Immune(ui.View): diff --git a/aurora/menus/overrides.py b/aurora/menus/overrides.py index beefaef..4327131 100644 --- a/aurora/menus/overrides.py +++ b/aurora/menus/overrides.py @@ -1,9 +1,9 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands -from aurora.utilities.config import config -from aurora.utilities.factory import overrides_embed -from aurora.utilities.utils import create_pagesize_options +from ..utilities.config import config +from ..utilities.factory import overrides_embed +from ..utilities.utils import create_pagesize_options class Overrides(ui.View): diff --git a/aurora/models/change.py b/aurora/models/change.py index ceb4641..029f76b 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -4,9 +4,9 @@ from typing import Literal, Optional from redbot.core.bot import Red -from aurora.models.base import AuroraBaseModel -from aurora.models.partials import PartialUser -from aurora.utilities.logger import logger +from ..models.base import AuroraBaseModel +from ..models.partials import PartialUser +from ..utilities.logger import logger class Change(AuroraBaseModel): diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 11678b6..d63df3e 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -8,11 +8,11 @@ import discord from discord import NotFound from redbot.core.bot import Red -from aurora.models.base import AuroraGuildModel -from aurora.models.change import Change -from aurora.models.partials import PartialChannel, PartialRole, PartialUser -from aurora.utilities.logger import logger -from aurora.utilities.utils import get_next_case_number +from ..models.base import AuroraGuildModel +from ..models.change import Change +from ..models.partials import PartialChannel, PartialRole, PartialUser +from ..utilities.logger import logger +from ..utilities.utils import get_next_case_number class Moderation(AuroraGuildModel): diff --git a/aurora/models/partials.py b/aurora/models/partials.py index 48ff2a0..0402e88 100644 --- a/aurora/models/partials.py +++ b/aurora/models/partials.py @@ -1,7 +1,7 @@ from discord import Forbidden, HTTPException, InvalidData, NotFound from redbot.core.bot import Red -from aurora.models.base import AuroraBaseModel, AuroraGuildModel +from ..models.base import AuroraBaseModel, AuroraGuildModel class PartialUser(AuroraBaseModel): diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index 16f8a7e..588ad35 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -5,7 +5,7 @@ import sqlite3 from discord import Guild from redbot.core import data_manager -from aurora.utilities.logger import logger +from .logger import logger def connect() -> sqlite3.Connection: diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index e7886ff..e032a6e 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -2,18 +2,14 @@ from datetime import datetime, timedelta from typing import Union -from discord import (Color, Embed, Guild, Interaction, InteractionMessage, - Member, Role, User) +from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User from redbot.core import commands -from redbot.core.utils.chat_formatting import (bold, box, error, - humanize_timedelta, warning) - -from aurora.models.moderation import Moderation -from aurora.models.partials import PartialUser -from aurora.utilities.config import config -from aurora.utilities.utils import (get_bool_emoji, get_next_case_number, - get_pagesize_str) +from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning +from ..models.moderation import Moderation +from ..models.partials import PartialUser +from .config import config +from .utils import get_bool_emoji, get_next_case_number, get_pagesize_str async def message_factory( color: Color, diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index 73595ee..7a0cd15 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -3,7 +3,7 @@ from datetime import datetime, timedelta from redbot.core.bot import Red -from aurora.models.base import AuroraBaseModel +from ..models.base import AuroraBaseModel class JSONEncoder(json.JSONEncoder): diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index ff950b1..ed115de 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -8,7 +8,7 @@ from discord.errors import Forbidden from redbot.core import commands, data_manager from redbot.core.utils.chat_formatting import error -from aurora.utilities.config import config +from ..utilities.config import config def check_permissions( @@ -111,7 +111,7 @@ async def check_moddable( def get_next_case_number(guild_id: str, cursor=None) -> int: """This function returns the next case number from the MySQL table for a specific guild.""" - from aurora.utilities.database import connect + from .database import connect if not cursor: database = connect() @@ -125,8 +125,8 @@ def get_next_case_number(guild_id: str, cursor=None) -> int: async def log(interaction: Interaction, moderation_id: int, resolved: bool = False) -> None: """This function sends a message to the guild's configured logging channel when an infraction takes place.""" - from aurora.models.moderation import Moderation - from aurora.utilities.factory import log_factory + from ..models.moderation import Moderation + from .factory import log_factory logging_channel_id = await config.guild(interaction.guild).log_channel() if logging_channel_id != " ": @@ -147,8 +147,8 @@ async def log(interaction: Interaction, moderation_id: int, resolved: bool = Fal async def send_evidenceformat(interaction: Interaction, moderation_id: int) -> None: """This function sends an ephemeral message to the moderator who took the moderation action, with a pre-made codeblock for use in the mod-evidence channel.""" - from aurora.models.moderation import Moderation - from aurora.utilities.factory import evidenceformat_factory + from ..models.moderation import Moderation + from .factory import evidenceformat_factory send_evidence_bool = ( await config.user(interaction.user).auto_evidenceformat() -- 2.45.3 From 92d221ff70f3a5c7b33726b3a786ab96c0be0731 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 21:43:08 -0400 Subject: [PATCH 109/376] fix(aurora): forgot a file! --- aurora/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/__init__.py b/aurora/__init__.py index a66006c..49ef5ec 100644 --- a/aurora/__init__.py +++ b/aurora/__init__.py @@ -1,4 +1,4 @@ -from aurora.aurora import Aurora +from .aurora import Aurora async def setup(bot): -- 2.45.3 From 904fd1c914882ade025b86612b969e9ccacf1d4c Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Mon, 6 May 2024 21:46:01 -0400 Subject: [PATCH 110/376] fix(aurora): fixed more import errors --- aurora/models/base.py | 6 ++---- aurora/models/moderation.py | 10 +++++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/aurora/models/base.py b/aurora/models/base.py index 45c8a60..08e1cd1 100644 --- a/aurora/models/base.py +++ b/aurora/models/base.py @@ -10,8 +10,7 @@ class AuroraBaseModel(BaseModel): bot: Red def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs): - from aurora.utilities.json import ( # pylint: disable=cyclic-import - dump, dumps) + from ..utilities.json import dump, dumps # pylint: disable=cyclic-import return dump(self.model_dump(exclude={"bot"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) class AuroraGuildModel(AuroraBaseModel): @@ -19,6 +18,5 @@ class AuroraGuildModel(AuroraBaseModel): guild_id: int def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs): - from aurora.utilities.json import ( # pylint: disable=cyclic-import - dump, dumps) + from ..utilities.json import dump, dumps # pylint: disable=cyclic-import return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index d63df3e..a5c6fc0 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -114,8 +114,8 @@ class Moderation(AuroraGuildModel): self.update() def update(self): - from aurora.utilities.database import connect - from aurora.utilities.json import dumps + from ..utilities.database import connect + from ..utilities.json import dumps query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" with connect() as database: @@ -199,7 +199,7 @@ class Moderation(AuroraGuildModel): @classmethod def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": - from aurora.utilities.database import connect + from ..utilities.database import connect query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;" with connect() as database: @@ -234,8 +234,8 @@ class Moderation(AuroraGuildModel): changes: list | None = None, metadata: dict | None = None, ) -> "Moderation": - from aurora.utilities.database import connect - from aurora.utilities.json import dumps + from ..utilities.database import connect + from ..utilities.json import dumps if not timestamp: timestamp = datetime.fromtimestamp(time()) elif not isinstance(timestamp, datetime): -- 2.45.3 From dc51aa7bdce0bac95b5a1d45540be52ebc789caf Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Thu, 9 May 2024 21:27:26 -0400 Subject: [PATCH 111/376] fix(aurora): import fixes --- aurora/models/change.py | 4 ++-- aurora/models/moderation.py | 11 +++++++---- aurora/models/partials.py | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index 029f76b..0c7148a 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -4,9 +4,9 @@ from typing import Literal, Optional from redbot.core.bot import Red -from ..models.base import AuroraBaseModel -from ..models.partials import PartialUser from ..utilities.logger import logger +from .base import AuroraBaseModel +from .partials import PartialUser class Change(AuroraBaseModel): diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index a5c6fc0..c216218 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -8,11 +8,11 @@ import discord from discord import NotFound from redbot.core.bot import Red -from ..models.base import AuroraGuildModel -from ..models.change import Change -from ..models.partials import PartialChannel, PartialRole, PartialUser from ..utilities.logger import logger from ..utilities.utils import get_next_case_number +from .base import AuroraGuildModel +from .change import Change +from .partials import PartialChannel, PartialRole, PartialUser class Moderation(AuroraGuildModel): @@ -241,7 +241,10 @@ class Moderation(AuroraGuildModel): elif not isinstance(timestamp, datetime): timestamp = datetime.fromtimestamp(timestamp) - if duration != "NULL" and duration is not None: + if duration == "NULL": + duration = None + + if duration is not None: end_timestamp = timestamp + duration else: duration = None diff --git a/aurora/models/partials.py b/aurora/models/partials.py index 0402e88..4b9e2b6 100644 --- a/aurora/models/partials.py +++ b/aurora/models/partials.py @@ -1,7 +1,7 @@ from discord import Forbidden, HTTPException, InvalidData, NotFound from redbot.core.bot import Red -from ..models.base import AuroraBaseModel, AuroraGuildModel +from .base import AuroraBaseModel, AuroraGuildModel class PartialUser(AuroraBaseModel): -- 2.45.3 From 67b33a2eb8e120daa0bb6222a142b3dd564b4a31 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 03:46:20 -0400 Subject: [PATCH 112/376] feat(aurora): added a slowmode command --- aurora/aurora.py | 53 +++++++++++++++++++++++++++++++------ aurora/models/moderation.py | 2 +- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 01655a9..5d4e983 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -20,8 +20,7 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import (box, error, humanize_list, - humanize_timedelta, warning) +from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning from .importers.aurora import ImportAuroraView from .importers.galacticbot import ImportGalacticBotView @@ -33,14 +32,10 @@ from .models.change import Change from .models.moderation import Moderation from .utilities.config import config, register_config from .utilities.database import connect, create_guild_table -from .utilities.factory import (addrole_embed, case_factory, changes_factory, - evidenceformat_factory, guild_embed, - immune_embed, message_factory, overrides_embed) +from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from .utilities.json import dump from .utilities.logger import logger -from .utilities.utils import (check_moddable, check_permissions, - get_footer_image, log, send_evidenceformat, - timedelta_from_relativedelta) +from .utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta class Aurora(commands.Cog): @@ -970,6 +965,48 @@ class Aurora(commands.Cog): await log(interaction, moderation.id) await send_evidenceformat(interaction, moderation.id) + @app_commands.command(name="slowmode") + async def slowmode( + self, + interaction: discord.Interaction, + interval: int, + channel: discord.TextChannel | None = None, + reason: str | None = None, + ): + """Set the slowmode of a channel. + + Parameters + ----------- + interval: int + The slowmode interval in seconds + channel: discord.TextChannel + The channel to set the slowmode in + reason: str + Why are you setting the slowmode?""" + if channel is None: + channel = interaction.channel + + if not await check_moddable(channel, interaction, ["manage_channels"]): + return + + await channel.edit(slowmode_delay=interval) + await interaction.response.send_message(f"Slowmode in {channel.mention} has been set to {interval} seconds!\n**Reason** - `{reason}`") + + moderation = Moderation.log( + interaction.client, + interaction.guild.id, + interaction.user.id, + "SLOWMODE", + "CHANNEL", + channel.id, + None, + None, + reason, + ) + await interaction.edit_original_response(content=f"Slowmode in {channel.mention} has been set to {interval} seconds! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`") + await log(interaction, moderation.id) + await send_evidenceformat(interaction, moderation.id) + @app_commands.command(name="history") async def history( self, diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index c216218..9ebb733 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -222,7 +222,7 @@ class Moderation(AuroraGuildModel): moderation_type: str, target_type: str, target_id: int, - role_id: int, + role_id: int | None = None, duration: timedelta | None = None, reason: str | None = None, database: sqlite3.Connection | None = None, -- 2.45.3 From 0411e3dab732bb4efbc4d5678dccfb8794084829 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 03:49:55 -0400 Subject: [PATCH 113/376] fix(aurora): fixed a typeerror in the check_moddable function --- aurora/utilities/utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index ed115de..42ce1cb 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -3,7 +3,7 @@ from datetime import datetime, timedelta from typing import Optional, Union from dateutil.relativedelta import relativedelta as rd -from discord import File, Guild, Interaction, Member, SelectOption, User +from discord import File, Guild, Interaction, Member, SelectOption, TextChannel, User from discord.errors import Forbidden from redbot.core import commands, data_manager from redbot.core.utils.chat_formatting import error @@ -40,9 +40,10 @@ def check_permissions( async def check_moddable( - target: Union[User, Member], interaction: Interaction, permissions: list + target: Union[User, Member, TextChannel], interaction: Interaction, permissions: list ) -> bool: """Checks if a moderator can moderate a target.""" + is_channel = isinstance(target, TextChannel) if check_permissions(interaction.client.user, permissions, guild=interaction.guild): await interaction.response.send_message( error( @@ -68,7 +69,7 @@ async def check_moddable( ) return False - if target.bot: + if not is_channel and target.bot: await interaction.response.send_message( content="You cannot moderate bots!", ephemeral=True ) -- 2.45.3 From 51d3245703aec322b18ec395a5e329294b86ee1b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 03:51:43 -0400 Subject: [PATCH 114/376] fix(aurora): fixed a typeerror in Moderation.log() --- aurora/models/moderation.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 9ebb733..272a165 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -251,7 +251,10 @@ class Moderation(AuroraGuildModel): end_timestamp = None if not expired: - expired = bool(timestamp > end_timestamp) + if end_timestamp: + expired = bool(timestamp > end_timestamp) + else: + expired = False if reason == "NULL": reason = None -- 2.45.3 From 797fd561c919fef491610cdb0639ab49be161fb4 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 03:53:38 -0400 Subject: [PATCH 115/376] fix(aurora): fixed another typeerror --- aurora/models/moderation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 272a165..10262cc 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -173,8 +173,9 @@ class Moderation(AuroraGuildModel): if result[14] is not None: changes = json.loads(result[14]) change_obj_list = [] - for change in changes: - change_obj_list.append(Change.from_dict(bot=bot, data=change)) + if changes: + for change in changes: + change_obj_list.append(Change.from_dict(bot=bot, data=change)) case = { "moderation_id": int(result[0]), -- 2.45.3 From 599ab8c51dede7bb5d840b3fe3d33425dcba9897 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 03:56:32 -0400 Subject: [PATCH 116/376] fix(aurora): fixed a non-async function being awaited --- aurora/utilities/factory.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index e032a6e..76e83f3 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -11,6 +11,7 @@ from ..models.partials import PartialUser from .config import config from .utils import get_bool_emoji, get_next_case_number, get_pagesize_str + async def message_factory( color: Color, guild: Guild, @@ -87,7 +88,7 @@ async def message_factory( embed.set_author(name=guild.name) embed.set_footer( - text=f"Case #{await get_next_case_number(guild.id):,}", + text=f"Case #{get_next_case_number(guild.id):,}", icon_url="attachment://arrow.png", ) -- 2.45.3 From 0b1d1d29e6c09089d930a789ae39e4490d2a93a4 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 03:57:54 -0400 Subject: [PATCH 117/376] fix(aurora): hopefully fixed a pydantic validation error --- aurora/models/moderation.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 10262cc..555ca0f 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -177,6 +177,9 @@ class Moderation(AuroraGuildModel): for change in changes: change_obj_list.append(Change.from_dict(bot=bot, data=change)) + if result[15] is not None: + metadata = json.loads(result[15]) + case = { "moderation_id": int(result[0]), "guild_id": int(guild_id), @@ -194,7 +197,7 @@ class Moderation(AuroraGuildModel): "resolve_reason": result[12], "expired": bool(result[13]), "changes": change_obj_list if result[14] else [], - "metadata": json.loads(result[15].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) if result[15] else {}, + "metadata": metadata if result[15] else {}, } return cls.from_dict(bot=bot, data=case) -- 2.45.3 From c90796f6b3b603baa64940f0527b06e7514c744e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:01:15 -0400 Subject: [PATCH 118/376] fix(aurora): hopefully actually fixed the pydantic validation error --- aurora/models/moderation.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 555ca0f..381c29a 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -176,9 +176,13 @@ class Moderation(AuroraGuildModel): if changes: for change in changes: change_obj_list.append(Change.from_dict(bot=bot, data=change)) + else: + change_obj_list = [] if result[15] is not None: metadata = json.loads(result[15]) + else: + metadata = {} case = { "moderation_id": int(result[0]), @@ -196,8 +200,8 @@ class Moderation(AuroraGuildModel): "resolved_by": result[11], "resolve_reason": result[12], "expired": bool(result[13]), - "changes": change_obj_list if result[14] else [], - "metadata": metadata if result[15] else {}, + "changes": change_obj_list, + "metadata": metadata, } return cls.from_dict(bot=bot, data=case) -- 2.45.3 From 39cb5feb50c828f2fc2b7286be92395b938756c5 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:02:15 -0400 Subject: [PATCH 119/376] misc(aurora): adding temporary debug logging --- aurora/models/moderation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 381c29a..512ddf7 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -203,6 +203,7 @@ class Moderation(AuroraGuildModel): "changes": change_obj_list, "metadata": metadata, } + logger.debug(case) return cls.from_dict(bot=bot, data=case) @classmethod -- 2.45.3 From ed923f1d9be1a17111af05a9c570d6ce84588e31 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:04:21 -0400 Subject: [PATCH 120/376] fix(aurora): finally actually maybe fixed the pydantic validation error --- aurora/models/moderation.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 512ddf7..caac217 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -176,8 +176,6 @@ class Moderation(AuroraGuildModel): if changes: for change in changes: change_obj_list.append(Change.from_dict(bot=bot, data=change)) - else: - change_obj_list = [] if result[15] is not None: metadata = json.loads(result[15]) @@ -201,7 +199,7 @@ class Moderation(AuroraGuildModel): "resolve_reason": result[12], "expired": bool(result[13]), "changes": change_obj_list, - "metadata": metadata, + "metadata": metadata if metadata else {}, } logger.debug(case) return cls.from_dict(bot=bot, data=case) -- 2.45.3 From 0cc7d6079dd011e6459b89b31a446f7eabf5f784 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:06:05 -0400 Subject: [PATCH 121/376] fix(aurora): removed useless debug statement --- aurora/models/moderation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index caac217..7018909 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -201,7 +201,6 @@ class Moderation(AuroraGuildModel): "changes": change_obj_list, "metadata": metadata if metadata else {}, } - logger.debug(case) return cls.from_dict(bot=bot, data=case) @classmethod -- 2.45.3 From 7a9c9846de5c99e5b934baed4572418523a6a8e1 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:09:27 -0400 Subject: [PATCH 122/376] fix(aurora): fixed a broken from_id method --- aurora/models/partials.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/partials.py b/aurora/models/partials.py index 4b9e2b6..48f4030 100644 --- a/aurora/models/partials.py +++ b/aurora/models/partials.py @@ -47,12 +47,12 @@ class PartialChannel(AuroraGuildModel): if not channel: try: channel = await bot.fetch_channel(channel_id) - return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, username=channel.name) + return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, name=channel.name) except (NotFound, InvalidData, HTTPException, Forbidden) as e: if e == Forbidden: return cls(bot=bot, guild_id=0, id=channel_id, name="Forbidden Channel") return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel") - return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, username=channel.name) + return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, name=channel.name) class PartialRole(AuroraGuildModel): id: int -- 2.45.3 From 9a4f19f4a1c52b144cc31b868b978dab1c57dc86 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:12:28 -0400 Subject: [PATCH 123/376] fix(aurora): show metadata key/value pairs in `/case` --- aurora/aurora.py | 1 + aurora/utilities/factory.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/aurora/aurora.py b/aurora/aurora.py index 5d4e983..0eaee86 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1002,6 +1002,7 @@ class Aurora(commands.Cog): None, None, reason, + metadata={"interval": interval} ) await interaction.edit_original_response(content=f"Slowmode in {channel.mention} has been set to {interval} seconds! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`") await log(interaction, moderation.id) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 76e83f3..f7568d9 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -188,13 +188,17 @@ async def case_factory(interaction: Interaction, moderation: Moderation) -> Embe if moderation.metadata: if moderation.metadata["imported_from"]: + del moderation.metadata["imported_from"] embed.description += ( f"\n**Imported From:** {moderation.metadata['imported_from']}" ) if moderation.metadata["imported_timestamp"]: + del moderation.metadata["imported_timestamp"] embed.description += ( f"\n**Imported Timestamp:** | " ) + for key, value in moderation.metadata.items(): + embed.description += f"\n**{key.title()}:** {value}" embed.add_field(name="Reason", value=box(moderation.reason), inline=False) -- 2.45.3 From 3dcc6379202735abed10f3d77668674dcf7a4bc8 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:15:27 -0400 Subject: [PATCH 124/376] fix(aurora): avoid keyerrors --- aurora/utilities/factory.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index f7568d9..282e02d 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -187,18 +187,19 @@ async def case_factory(interaction: Interaction, moderation: Moderation) -> Embe embed.description += f"\n**Role:** {role.name}" if moderation.metadata: - if moderation.metadata["imported_from"]: - del moderation.metadata["imported_from"] + if moderation.metadata.get("imported_from"): embed.description += ( f"\n**Imported From:** {moderation.metadata['imported_from']}" ) - if moderation.metadata["imported_timestamp"]: - del moderation.metadata["imported_timestamp"] + moderation.metadata.pop("imported_from") + if moderation.metadata.get("imported_timestamp"): embed.description += ( f"\n**Imported Timestamp:** | " ) - for key, value in moderation.metadata.items(): - embed.description += f"\n**{key.title()}:** {value}" + moderation.metadata.pop("imported_timestamp") + if moderation.metadata.items(): + for key, value in moderation.metadata.items(): + embed.description += f"\n**{key.title()}:** {value}" embed.add_field(name="Reason", value=box(moderation.reason), inline=False) -- 2.45.3 From 7f71ca3d6d078a3e054e47c86fe24d7596e4ab96 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:16:48 -0400 Subject: [PATCH 125/376] fix(aurora): change interval metadata --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 0eaee86..e22776a 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1002,7 +1002,7 @@ class Aurora(commands.Cog): None, None, reason, - metadata={"interval": interval} + metadata={"interval": f"{interval} seconds"} ) await interaction.edit_original_response(content=f"Slowmode in {channel.mention} has been set to {interval} seconds! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`") await log(interaction, moderation.id) -- 2.45.3 From bfb4d8768dbee884016476088febcdf1389967dc Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:18:17 -0400 Subject: [PATCH 126/376] fix(aurora): add moderation metadata to the log factory --- aurora/utilities/factory.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 282e02d..50b7067 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -127,6 +127,10 @@ async def log_factory( + f"\n**Duration:** {duration_embed}\n**Expired:** {moderation.expired}" ) + if moderation.metadata.items(): + for key, value in moderation.metadata.items(): + embed.description += f"\n**{key.title()}:** {value}" + embed.add_field(name="Reason", value=box(moderation.reason), inline=False) embed.add_field( @@ -148,6 +152,10 @@ async def log_factory( + f"\n**Duration:** {humanize_timedelta(timedelta=moderation.duration)} | " ) + if moderation.metadata.items(): + for key, value in moderation.metadata.items(): + embed.description += f"\n**{key.title()}:** {value}" + embed.add_field(name="Reason", value=box(moderation.reason), inline=False) return embed -- 2.45.3 From 5b64ee957831eaec8b8a7f35f146280abdf5984e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:22:42 -0400 Subject: [PATCH 127/376] feat(aurora): add metadata to evidenceformat --- aurora/utilities/factory.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 50b7067..0485af7 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -289,6 +289,9 @@ async def evidenceformat_factory(moderation: Moderation) -> str: content += f"\nReason: {moderation.reason}" + for key, value in moderation.metadata.items(): + content += f"\n{key.title()}: {value}" + return box(content, "prolog") -- 2.45.3 From 73c910488248d9a3eb1cc378b0de7264ae449e90 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 24 May 2024 04:26:58 -0400 Subject: [PATCH 128/376] fix(aurora): cast to string before checking length to avoid typeerrors when reason is None --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index e22776a..ec8a0e6 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1185,7 +1185,7 @@ class Aurora(commands.Cog): field_name = f"Case #{mod.id:,} ({str.title(mod.type)})" field_value = f"**Target:** `{target.name}` ({target.id})\n**Moderator:** `{moderator.name}` ({moderator.id})" - if len(mod.reason) > 125: + if len(str(mod.reason)) > 125: field_value += f"\n**Reason:** `{str(mod.reason)[:125]}...`" else: field_value += f"\n**Reason:** `{str(mod.reason)}`" -- 2.45.3 From 641f45d1262c80f2205b72c2dbf1fdf141f3508e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sun, 2 Jun 2024 23:53:19 -0400 Subject: [PATCH 129/376] feat(aurora): add the from_sql_all classmethod to the Moderation model --- aurora/models/moderation.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 7018909..f990693 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -119,8 +119,7 @@ class Moderation(AuroraGuildModel): query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" with connect() as database: - cursor = database.cursor() - cursor.execute(query, ( + database.execute(query, ( self.timestamp.timestamp(), self.moderation_type, self.target_type, @@ -137,7 +136,6 @@ class Moderation(AuroraGuildModel): dumps(self.metadata), self.moderation_id, )) - cursor.close() logger.debug("Row updated in moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", self.moderation_id, @@ -219,6 +217,25 @@ class Moderation(AuroraGuildModel): raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") + @classmethod + def from_sql_all(cls, bot: Red, guild_id: int) -> List["Moderation"]: + from ..utilities.database import connect + query = f"SELECT * FROM moderation_{guild_id};" + + with connect() as database: + cursor = database.cursor() + cursor.execute(query) + results = cursor.fetchall() + cursor.close() + + if results: + cases = [] + for result in results: + cases.append(cls.from_result(bot, result, guild_id)) + return cases + + return [] + @classmethod def log( cls, -- 2.45.3 From 1990b97518a32fca0caed2552c12e90a51a2460d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sun, 2 Jun 2024 23:59:17 -0400 Subject: [PATCH 130/376] fix(aurora): ignore moderation cases where the moderation_id is 0 --- aurora/models/moderation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index f990693..e5c852d 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -231,7 +231,9 @@ class Moderation(AuroraGuildModel): if results: cases = [] for result in results: - cases.append(cls.from_result(bot, result, guild_id)) + case = cls.from_result(bot, result, guild_id) + if case.moderation_id != 0: + cases.append(case) return cases return [] -- 2.45.3 From db477c4744fd4de1e58c3aa60ce744c9b9e5c07d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:07:52 -0400 Subject: [PATCH 131/376] fix(aurora): fixed an issue with json encoding --- aurora/models/base.py | 10 ++++++++-- aurora/utilities/json.py | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/aurora/models/base.py b/aurora/models/base.py index 08e1cd1..e6005ee 100644 --- a/aurora/models/base.py +++ b/aurora/models/base.py @@ -9,14 +9,20 @@ class AuroraBaseModel(BaseModel): model_config = ConfigDict(ignored_types=(Red,), arbitrary_types_allowed=True) bot: Red + def dump(self) -> dict: + return self.model_dump(exclude={"bot"}) + def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs): from ..utilities.json import dump, dumps # pylint: disable=cyclic-import - return dump(self.model_dump(exclude={"bot"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) + return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) class AuroraGuildModel(AuroraBaseModel): """Subclass of AuroraBaseModel that includes a guild_id attribute, and a modified to_json() method to match.""" guild_id: int + def dump(self) -> dict: + return self.model_dump(exclude={"bot", "guild_id"}) + def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs): from ..utilities.json import dump, dumps # pylint: disable=cyclic-import - return dump(self.model_dump(exclude={"bot", "guild_id"}), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) + return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index 7a0cd15..892a227 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -13,7 +13,7 @@ class JSONEncoder(json.JSONEncoder): if isinstance(o, timedelta): return str(o) if isinstance(o, AuroraBaseModel): - return o.to_json() + return o.dump() if isinstance(o, Red): return None return super().default(o) -- 2.45.3 From 21e51dc3208b651e95dcfb0a6a06cd010e3592dc Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:09:39 -0400 Subject: [PATCH 132/376] misc(aurora): minor syntax change --- aurora/utilities/json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index 892a227..80f1259 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -70,7 +70,7 @@ def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, default=default, sort_keys=sort_keys, **kw - ) + ) # This is a wrapper around the json module's dump function that uses our custom JSONEncoder class def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, -- 2.45.3 From 7fc6235abe3382f1f1ac0f0b503fe3e392127636 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:15:17 -0400 Subject: [PATCH 133/376] fix(aurora): remove bot keys from the change import when importing from aurora --- aurora/importers/aurora.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index e9622a4..1a1777d 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -72,11 +72,15 @@ class ImportAuroraView(ui.View): case["moderator_id"] = int(case["moderator_id"]) if "changes" not in case or not case["changes"]: - case["changes"] = [] + changes = [] else: - case["changes"] = json.loads(case["changes"]) - if isinstance(case["changes"], str): - case["changes"] = json.loads(case["changes"]) + changes = json.loads(case["changes"]) + if isinstance(changes, str): + changes: list[dict] = json.loads(changes) + + for change in changes: + if change.get("bot"): + del change["bot"] if "metadata" not in case: metadata = {} @@ -107,7 +111,7 @@ class ImportAuroraView(ui.View): resolved_by=case["resolved_by"], resolved_reason=case["resolve_reason"], expired=case["expired"], - changes=case["changes"], + changes=changes, metadata=metadata, database=database, ) -- 2.45.3 From c35580c576da87c4cd7089f55e92a0480fd43f13 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:17:33 -0400 Subject: [PATCH 134/376] misc(aurora): change to aurora importer log arguments --- aurora/importers/aurora.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 1a1777d..c184c1c 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -97,15 +97,15 @@ class ImportAuroraView(ui.View): duration = None Moderation.log( - interaction.client, - self.ctx.guild.id, - case["moderator_id"], - case["moderation_type"], - case["target_type"], - case["target_id"], - case["role_id"], - duration, - case["reason"], + bot=interaction.client, + guild_id=self.ctx.guild.id, + moderator_id=case["moderator_id"], + moderation_type=case["moderation_type"], + target_type=case["target_type"], + target_id=case["target_id"], + role_id=case["role_id"], + duration=duration, + reason=case["reason"], timestamp=case["timestamp"], resolved=case["resolved"], resolved_by=case["resolved_by"], -- 2.45.3 From 76f176d4ccf7f61f91207f2ac34e8c91c5540915 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:22:32 -0400 Subject: [PATCH 135/376] feat(aurora): change history to use `Moderation.from_sql_all()` --- aurora/aurora.py | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index ec8a0e6..e4f9c2b 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1083,21 +1083,6 @@ class Aurora(commands.Cog): database = connect() if export: - database.row_factory = sqlite3.Row - cursor = database.cursor() - - query = f"""SELECT * - FROM moderation_{interaction.guild.id} - ORDER BY moderation_id DESC;""" - cursor.execute(query) - - results = cursor.fetchall() - - cases = [] - for result in results: - case = dict(result) - cases.append(case) - try: filename = ( str(data_manager.cog_data_path(cog_instance=self)) @@ -1105,8 +1090,10 @@ class Aurora(commands.Cog): + f"moderation_{interaction.guild.id}.json" ) + cases = Moderation.from_sql_all(interaction.client, interaction.guild.id) + with open(filename, "w", encoding="utf-8") as f: - dump(cases, f, indent=2) + dump(obj=cases, fp=f, indent=2) await interaction.followup.send( file=discord.File( @@ -1124,7 +1111,6 @@ class Aurora(commands.Cog): + box(e, "py"), ephemeral=ephemeral, ) - cursor.close() database.close() return -- 2.45.3 From d6467544666a0635da7d3eed22b2515dd7a2076f Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:47:56 -0400 Subject: [PATCH 136/376] feat(aurora): added a bunch of functionality to the Moderation model --- aurora/aurora.py | 2 +- aurora/models/moderation.py | 65 ++++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index e4f9c2b..4497d40 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1090,7 +1090,7 @@ class Aurora(commands.Cog): + f"moderation_{interaction.guild.id}.json" ) - cases = Moderation.from_sql_all(interaction.client, interaction.guild.id) + cases = Moderation.get_all_cases(bot=interaction.client, guild_id=interaction.guild.id) with open(filename, "w", encoding="utf-8") as f: dump(obj=cases, fp=f, indent=2) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index e5c852d..db9e681 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -202,42 +202,63 @@ class Moderation(AuroraGuildModel): return cls.from_dict(bot=bot, data=case) @classmethod - def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": + def execute(cls, bot: Red, query: str, parameters: tuple | None = None) -> List["Moderation"]: from ..utilities.database import connect - query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;" - + if not parameters: + parameters = () with connect() as database: cursor = database.cursor() - cursor.execute(query, (moderation_id,)) - result = cursor.fetchone() - cursor.close() - - if result and not moderation_id == 0: - return cls.from_result(bot, result, guild_id) - - raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") - - @classmethod - def from_sql_all(cls, bot: Red, guild_id: int) -> List["Moderation"]: - from ..utilities.database import connect - query = f"SELECT * FROM moderation_{guild_id};" - - with connect() as database: - cursor = database.cursor() - cursor.execute(query) + cursor.execute(query, parameters=parameters) results = cursor.fetchall() cursor.close() if results: cases = [] for result in results: - case = cls.from_result(bot, result, guild_id) + case = cls.from_result(bot=bot, result=result) if case.moderation_id != 0: cases.append(case) return cases - return [] + @classmethod + def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": + return cls.find_by_id(bot=bot, moderation_id=moderation_id, guild_id=guild_id) + + @classmethod + def find_by_id(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": + query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;" + case = cls.execute(bot=bot, query=query, parameters=(moderation_id,)) + if case: + return case[0] + raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") + + @classmethod + def find_by_target(cls, bot: Red, guild_id: int, target: int, types: list | None = None) -> List["Moderation"]: + query = f"SELECT * FROM moderation_{guild_id} WHERE target_id = ?" + if types: + query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" + query += " ORDER BY moderation_id DESC;" + + return cls.execute(bot=bot, query=query, parameters=(target, *types) if types else (target,)) + + @classmethod + def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: list | None = None) -> List["Moderation"]: + query = f"SELECT * FROM moderation_{guild_id} WHERE moderator_id = ?" + if types: + query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" + query += " ORDER BY moderation_id DESC;" + + return cls.execute(bot=bot, query=query, parameters=(moderator, *types) if types else (moderator,)) + + @classmethod + def get_all_cases(cls, bot: Red, guild_id: int, types: list | None = None) -> List["Moderation"]: + query = f"SELECT * FROM moderation_{guild_id}" + if types: + query += f" WHERE moderation_type IN ({', '.join(['?' for _ in types])})" + query += " ORDER BY moderation_id DESC;" + return cls.execute(bot=bot, query=query, parameters=tuple(iterable=types) if types else None) + @classmethod def log( cls, -- 2.45.3 From 4c284531736422f71afafb349fd5ed4da13497c1 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:49:08 -0400 Subject: [PATCH 137/376] fix(aurora): fixed a TypeError --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index db9e681..23b6a5d 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -208,7 +208,7 @@ class Moderation(AuroraGuildModel): parameters = () with connect() as database: cursor = database.cursor() - cursor.execute(query, parameters=parameters) + cursor.execute(sql=query, parameters=parameters) results = cursor.fetchall() cursor.close() -- 2.45.3 From 028e22ebec7ad44eee0e842ec66fe77548638892 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:50:17 -0400 Subject: [PATCH 138/376] fix(aurora): happy now? --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 23b6a5d..17d4e13 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -208,7 +208,7 @@ class Moderation(AuroraGuildModel): parameters = () with connect() as database: cursor = database.cursor() - cursor.execute(sql=query, parameters=parameters) + cursor.execute(query, parameters) results = cursor.fetchall() cursor.close() -- 2.45.3 From 99d95afe07d5c8f02fd2b20135ea3289f690c4f0 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:51:51 -0400 Subject: [PATCH 139/376] fix(aurora): fixed another TypeError --- aurora/models/moderation.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 17d4e13..17a48f5 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -202,7 +202,7 @@ class Moderation(AuroraGuildModel): return cls.from_dict(bot=bot, data=case) @classmethod - def execute(cls, bot: Red, query: str, parameters: tuple | None = None) -> List["Moderation"]: + def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None) -> List["Moderation"]: from ..utilities.database import connect if not parameters: parameters = () @@ -215,7 +215,7 @@ class Moderation(AuroraGuildModel): if results: cases = [] for result in results: - case = cls.from_result(bot=bot, result=result) + case = cls.from_result(bot=bot, result=result, guild_id=guild_id) if case.moderation_id != 0: cases.append(case) return cases @@ -228,7 +228,7 @@ class Moderation(AuroraGuildModel): @classmethod def find_by_id(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;" - case = cls.execute(bot=bot, query=query, parameters=(moderation_id,)) + case = cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderation_id,)) if case: return case[0] raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") @@ -240,7 +240,7 @@ class Moderation(AuroraGuildModel): query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" query += " ORDER BY moderation_id DESC;" - return cls.execute(bot=bot, query=query, parameters=(target, *types) if types else (target,)) + return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(target, *types) if types else (target,)) @classmethod def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: list | None = None) -> List["Moderation"]: @@ -249,7 +249,7 @@ class Moderation(AuroraGuildModel): query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" query += " ORDER BY moderation_id DESC;" - return cls.execute(bot=bot, query=query, parameters=(moderator, *types) if types else (moderator,)) + return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderator, *types) if types else (moderator,)) @classmethod def get_all_cases(cls, bot: Red, guild_id: int, types: list | None = None) -> List["Moderation"]: @@ -257,7 +257,7 @@ class Moderation(AuroraGuildModel): if types: query += f" WHERE moderation_type IN ({', '.join(['?' for _ in types])})" query += " ORDER BY moderation_id DESC;" - return cls.execute(bot=bot, query=query, parameters=tuple(iterable=types) if types else None) + return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=tuple(iterable=types) if types else None) @classmethod def log( -- 2.45.3 From 499cfbe8a9ddb3e2a4e9afcaa403a2f56dae478e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:55:09 -0400 Subject: [PATCH 140/376] misc(aurora): use tuples instead of lists --- aurora/models/moderation.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 17a48f5..2e5fd5f 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -2,7 +2,7 @@ import json import sqlite3 from datetime import datetime, timedelta from time import time -from typing import Dict, Iterable, List, Optional, Union +from typing import Dict, Iterable, List, Optional, Tuple, Union import discord from discord import NotFound @@ -202,7 +202,7 @@ class Moderation(AuroraGuildModel): return cls.from_dict(bot=bot, data=case) @classmethod - def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None) -> List["Moderation"]: + def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None) -> Tuple["Moderation"]: from ..utilities.database import connect if not parameters: parameters = () @@ -218,8 +218,8 @@ class Moderation(AuroraGuildModel): case = cls.from_result(bot=bot, result=result, guild_id=guild_id) if case.moderation_id != 0: cases.append(case) - return cases - return [] + return tuple(iterable=cases) + return () @classmethod def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": @@ -234,7 +234,7 @@ class Moderation(AuroraGuildModel): raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") @classmethod - def find_by_target(cls, bot: Red, guild_id: int, target: int, types: list | None = None) -> List["Moderation"]: + def find_by_target(cls, bot: Red, guild_id: int, target: int, types: list | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE target_id = ?" if types: query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" @@ -243,7 +243,7 @@ class Moderation(AuroraGuildModel): return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(target, *types) if types else (target,)) @classmethod - def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: list | None = None) -> List["Moderation"]: + def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: list | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE moderator_id = ?" if types: query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" @@ -252,7 +252,7 @@ class Moderation(AuroraGuildModel): return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderator, *types) if types else (moderator,)) @classmethod - def get_all_cases(cls, bot: Red, guild_id: int, types: list | None = None) -> List["Moderation"]: + def get_all_cases(cls, bot: Red, guild_id: int, types: list | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id}" if types: query += f" WHERE moderation_type IN ({', '.join(['?' for _ in types])})" -- 2.45.3 From 22f9ce52d1f3648c72efc41139b91ed53d8daaef Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 00:55:56 -0400 Subject: [PATCH 141/376] fix(aurora): fixed a typeerror --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 2e5fd5f..e3a6e3f 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -218,7 +218,7 @@ class Moderation(AuroraGuildModel): case = cls.from_result(bot=bot, result=result, guild_id=guild_id) if case.moderation_id != 0: cases.append(case) - return tuple(iterable=cases) + return tuple(cases) return () @classmethod -- 2.45.3 From be253b668b4c3cfe3faa3054a3589a876988478f Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 01:07:00 -0400 Subject: [PATCH 142/376] feat(aurora): converted `/history` to use the new Moderation sql queries --- aurora/aurora.py | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 4497d40..8e422e0 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -11,7 +11,6 @@ import sqlite3 import time from datetime import datetime, timedelta, timezone from math import ceil -from typing import List import discord from discord import Object @@ -1114,35 +1113,14 @@ class Aurora(commands.Cog): database.close() return - cursor = database.cursor() - if target: - query = f"""SELECT * - FROM moderation_{interaction.guild.id} - WHERE target_id = ? AND moderation_id != 0 - ORDER BY moderation_id DESC;""" - cursor.execute(query, (target.id,)) + moderations = Moderation.find_by_target(interaction.client, interaction.guild.id, target.id) elif moderator: - query = f"""SELECT * - FROM moderation_{interaction.guild.id} - WHERE moderator_id = ? AND moderation_id != 0 - ORDER BY moderation_id DESC;""" - cursor.execute(query, (moderator.id,)) + moderations = Moderation.find_by_moderator(interaction.client, interaction.guild.id, moderator.id) else: - query = f"""SELECT * - FROM moderation_{interaction.guild.id} - WHERE moderation_id != 0 - ORDER BY moderation_id DESC;""" - cursor.execute(query) + moderations = Moderation.get_all_cases(interaction.client, interaction.guild.id) - results = cursor.fetchall() - moderation_list: List[Moderation] = [] - - for result in results: - moderation = Moderation.from_result(interaction.client, result, interaction.guild.id) - moderation_list.append(moderation) - - case_quantity = len(moderation_list) + case_quantity = len(moderations) page_quantity = ceil(case_quantity / pagesize) start_index = (page - 1) * pagesize end_index = page * pagesize @@ -1155,7 +1133,7 @@ class Aurora(commands.Cog): memory_dict = {} - for mod in moderation_list[start_index:end_index]: + for mod in moderations[start_index:end_index]: if mod.target_id not in memory_dict: memory_dict.update({ str(mod.target_id): await mod.get_target() -- 2.45.3 From bbe8b281d1c3650fbe91b406c42e49eb2a58a98a Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 23:46:22 -0400 Subject: [PATCH 143/376] misc(aurora): changed two typehints in aurora.utilities.utils and added other typehints --- aurora/aurora.py | 2 +- aurora/models/moderation.py | 6 +++--- aurora/utilities/utils.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 8e422e0..1d4052b 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1191,7 +1191,7 @@ class Aurora(commands.Cog): Reason for resolving case""" permissions = check_permissions( interaction.client.user, - ["embed_links", "moderate_members", "ban_members"], + ("embed_links", "moderate_members", "ban_members"), interaction, ) if permissions: diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index e3a6e3f..478768f 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -63,10 +63,10 @@ class Moderation(AuroraGuildModel): return await PartialRole.from_id(self.bot, self.guild_id, self.role_id) return None - def __str__(self): + def __str__(self) -> str: return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}" - async def resolve(self, resolved_by: int, reason: str): + async def resolve(self, resolved_by: int, reason: str) -> None: if self.resolved: raise ValueError("Case is already resolved!") @@ -113,7 +113,7 @@ class Moderation(AuroraGuildModel): self.update() - def update(self): + def update(self) -> None: from ..utilities.database import connect from ..utilities.json import dumps query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 42ce1cb..b70ec83 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -1,6 +1,6 @@ # pylint: disable=cyclic-import from datetime import datetime, timedelta -from typing import Optional, Union +from typing import Optional, Tuple, Union from dateutil.relativedelta import relativedelta as rd from discord import File, Guild, Interaction, Member, SelectOption, TextChannel, User @@ -13,7 +13,7 @@ from ..utilities.config import config def check_permissions( user: User, - permissions: list, + permissions: Tuple[str], ctx: Union[commands.Context, Interaction] | None = None, guild: Guild | None = None, ) -> Union[bool, str]: @@ -40,7 +40,7 @@ def check_permissions( async def check_moddable( - target: Union[User, Member, TextChannel], interaction: Interaction, permissions: list + target: Union[User, Member, TextChannel], interaction: Interaction, permissions: Tuple[str] ) -> bool: """Checks if a moderator can moderate a target.""" is_channel = isinstance(target, TextChannel) -- 2.45.3 From 460d5a31fcc6c6c3cd4a96dcf31283e1d1075912 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 3 Jun 2024 23:48:21 -0400 Subject: [PATCH 144/376] feat(aurora): allow the `Moderation.execute()` classmethod to accept a cursor, to prevent opening a new database connection on every call --- aurora/models/moderation.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 478768f..2874344 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -202,23 +202,30 @@ class Moderation(AuroraGuildModel): return cls.from_dict(bot=bot, data=case) @classmethod - def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None) -> Tuple["Moderation"]: + def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: from ..utilities.database import connect if not parameters: parameters = () - with connect() as database: + if not cursor: + no_cursor = True + database = connect() cursor = database.cursor() - cursor.execute(query, parameters) - results = cursor.fetchall() - cursor.close() + else: + no_cursor = False - if results: - cases = [] - for result in results: - case = cls.from_result(bot=bot, result=result, guild_id=guild_id) - if case.moderation_id != 0: - cases.append(case) - return tuple(cases) + cursor.execute(query, parameters) + results = cursor.fetchall() + if no_cursor: + cursor.close() + database.close() + + if results: + cases = [] + for result in results: + case = cls.from_result(bot=bot, result=result, guild_id=guild_id) + if case.moderation_id != 0: + cases.append(case) + return tuple(cases) return () @classmethod -- 2.45.3 From 9b0f977016d15d04091197f06f40185634546d0b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 00:04:11 -0400 Subject: [PATCH 145/376] feat(aurora): moved `get_next_case_number()` into the `Moderation` class, along with removing `from_sql` and `get_all_cases`. also added some other classmethods to replace those. also modified message_factory and its calls to add a new kwarg --- aurora/aurora.py | 45 +++++++++++++++++++++++-------------- aurora/models/moderation.py | 44 ++++++++++++++++++++---------------- aurora/utilities/factory.py | 7 ++++-- aurora/utilities/utils.py | 18 ++------------- 4 files changed, 60 insertions(+), 54 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 1d4052b..1efb03c 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -221,7 +221,8 @@ class Aurora(commands.Cog): if silent is False: try: embed = await message_factory( - await self.bot.get_embed_color(interaction.channel), + bot=interaction.client, + color=await self.bot.get_embed_color(interaction.channel), guild=interaction.guild, moderator=interaction.user, reason=reason, @@ -279,7 +280,8 @@ class Aurora(commands.Cog): if silent is False: try: embed = await message_factory( - await self.bot.get_embed_color(interaction.channel), + bot=interaction.client, + color=await self.bot.get_embed_color(interaction.channel), guild=interaction.guild, moderator=interaction.user, reason=reason, @@ -374,7 +376,8 @@ class Aurora(commands.Cog): if silent is False: try: embed = await message_factory( - await self.bot.get_embed_color(interaction.channel), + bot=interaction.client, + color=await self.bot.get_embed_color(interaction.channel), guild=interaction.guild, moderator=interaction.user, reason=reason, @@ -479,7 +482,8 @@ class Aurora(commands.Cog): if silent is False: try: embed = await message_factory( - await self.bot.get_embed_color(interaction.channel), + bot=interaction.client, + color=await self.bot.get_embed_color(interaction.channel), guild=interaction.guild, moderator=interaction.user, reason=reason, @@ -575,7 +579,8 @@ class Aurora(commands.Cog): if silent is False: try: embed = await message_factory( - await self.bot.get_embed_color(interaction.channel), + bot=interaction.client, + color=await self.bot.get_embed_color(interaction.channel), guild=interaction.guild, moderator=interaction.user, reason=reason, @@ -650,7 +655,8 @@ class Aurora(commands.Cog): if silent is False: try: embed = await message_factory( - await self.bot.get_embed_color(interaction.channel), + bot=interaction.client, + color=await self.bot.get_embed_color(interaction.channel), guild=interaction.guild, moderator=interaction.user, reason=reason, @@ -708,7 +714,8 @@ class Aurora(commands.Cog): if silent is False: try: embed = await message_factory( - await self.bot.get_embed_color(interaction.channel), + bot=interaction.client, + color=await self.bot.get_embed_color(interaction.channel), guild=interaction.guild, moderator=interaction.user, reason=reason, @@ -810,7 +817,8 @@ class Aurora(commands.Cog): try: embed = await message_factory( - await self.bot.get_embed_color(interaction.channel), + bot=interaction.client, + color=await self.bot.get_embed_color(interaction.channel), guild=interaction.guild, moderator=interaction.user, reason=reason, @@ -853,8 +861,9 @@ class Aurora(commands.Cog): silent = not await config.guild(interaction.guild).dm_users() if silent is False: try: - embed = embed = await message_factory( - await self.bot.get_embed_color(interaction.channel), + embed = await message_factory( + bot=interaction.client, + color=await self.bot.get_embed_color(interaction.channel), guild=interaction.guild, moderator=interaction.user, reason=reason, @@ -936,7 +945,8 @@ class Aurora(commands.Cog): if silent is False: try: embed = await message_factory( - await self.bot.get_embed_color(interaction.channel), + bot=interaction.client, + color=await self.bot.get_embed_color(interaction.channel), guild=interaction.guild, moderator=interaction.user, reason=reason, @@ -1089,7 +1099,7 @@ class Aurora(commands.Cog): + f"moderation_{interaction.guild.id}.json" ) - cases = Moderation.get_all_cases(bot=interaction.client, guild_id=interaction.guild.id) + cases = Moderation.get_latest(bot=interaction.client, guild_id=interaction.guild.id) with open(filename, "w", encoding="utf-8") as f: dump(obj=cases, fp=f, indent=2) @@ -1118,7 +1128,7 @@ class Aurora(commands.Cog): elif moderator: moderations = Moderation.find_by_moderator(interaction.client, interaction.guild.id, moderator.id) else: - moderations = Moderation.get_all_cases(interaction.client, interaction.guild.id) + moderations = Moderation.get_latest(interaction.client, interaction.guild.id) case_quantity = len(moderations) page_quantity = ceil(case_quantity / pagesize) @@ -1204,7 +1214,7 @@ class Aurora(commands.Cog): return try: - moderation = Moderation.from_sql(interaction.client, case, interaction.guild.id) + moderation = Moderation.find_by_id(interaction.client, case, interaction.guild.id) except ValueError: await interaction.response.send_message( content=error(f"Case #{case:,} does not exist!"), ephemeral=True @@ -1288,7 +1298,7 @@ class Aurora(commands.Cog): ) try: - mod = Moderation.from_sql(interaction.client, case, interaction.guild.id) + mod = Moderation.find_by_id(interaction.client, case, interaction.guild.id) except ValueError: await interaction.response.send_message( content=error(f"Case #{case:,} does not exist!"), ephemeral=True @@ -1381,7 +1391,7 @@ class Aurora(commands.Cog): return try: - moderation = Moderation.from_sql(interaction.client, case, interaction.guild.id) + moderation = Moderation.find_by_id(interaction.client, case, interaction.guild.id) old_moderation = moderation except ValueError: await interaction.response.send_message( @@ -1511,7 +1521,8 @@ class Aurora(commands.Cog): ) embed = await message_factory( - await self.bot.get_embed_color(guild.channels[0]), + bot=self.bot, + color=await self.bot.get_embed_color(guild.channels[0]), guild=guild, reason=f"Automatic unban from case #{moderation_id}", moderation_type="unbanned", diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 2874344..5462ba3 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -1,6 +1,7 @@ import json import sqlite3 from datetime import datetime, timedelta +from sqlite3 import Cursor from time import time from typing import Dict, Iterable, List, Optional, Tuple, Union @@ -9,7 +10,6 @@ from discord import NotFound from redbot.core.bot import Red from ..utilities.logger import logger -from ..utilities.utils import get_next_case_number from .base import AuroraGuildModel from .change import Change from .partials import PartialChannel, PartialRole, PartialUser @@ -229,42 +229,48 @@ class Moderation(AuroraGuildModel): return () @classmethod - def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": - return cls.find_by_id(bot=bot, moderation_id=moderation_id, guild_id=guild_id) + def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + params = [] + query = f"SELECT * FROM moderation_{guild_id} ORDER BY moderation_id DESC" + if limit: + query += " LIMIT ?" + params.append(limit) + if types: + query += f" WHERE moderation_type IN ({', '.join(['?' for _ in types])})" + params.extend(types) + query += ";" + return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=tuple(params) if limit else (), cursor=cursor) @classmethod - def find_by_id(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": + def get_next_case_number(cls, bot: Red, guild_id: int, cursor: Cursor | None = None) -> int: + result = cls.get_latest(bot=bot, guild_id=guild_id, cursor=cursor) + return (result[0].moderation_id + 1) if result else 1 + + @classmethod + def find_by_id(cls, bot: Red, moderation_id: int, guild_id: int, cursor: Cursor | None = None) -> "Moderation": query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;" - case = cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderation_id,)) + case = cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderation_id,), cursor=cursor) if case: return case[0] raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") @classmethod - def find_by_target(cls, bot: Red, guild_id: int, target: int, types: list | None = None) -> Tuple["Moderation"]: + def find_by_target(cls, bot: Red, guild_id: int, target: int, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE target_id = ?" if types: query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" query += " ORDER BY moderation_id DESC;" - return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(target, *types) if types else (target,)) + return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(target, *types) if types else (target,), cursor=cursor) @classmethod - def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: list | None = None) -> Tuple["Moderation"]: + def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE moderator_id = ?" if types: query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" query += " ORDER BY moderation_id DESC;" - return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderator, *types) if types else (moderator,)) - - @classmethod - def get_all_cases(cls, bot: Red, guild_id: int, types: list | None = None) -> Tuple["Moderation"]: - query = f"SELECT * FROM moderation_{guild_id}" - if types: - query += f" WHERE moderation_type IN ({', '.join(['?' for _ in types])})" - query += " ORDER BY moderation_id DESC;" - return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=tuple(iterable=types) if types else None) + return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderator, *types) if types else (moderator,), cursor=cursor) @classmethod def log( @@ -328,7 +334,7 @@ class Moderation(AuroraGuildModel): close_db = False cursor = database.cursor() - moderation_id = get_next_case_number(guild_id=guild_id, cursor=cursor) + moderation_id = cls.get_next_case_number(bot=bot, guild_id=guild_id, cursor=cursor) case = { "moderation_id": moderation_id, @@ -378,4 +384,4 @@ class Moderation(AuroraGuildModel): case["metadata"], ) - return cls.from_sql(bot=bot, moderation_id=moderation_id, guild_id=guild_id) + return cls.find_by_id(bot=bot, moderation_id=moderation_id, guild_id=guild_id) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 0485af7..c30ef1b 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -4,15 +4,17 @@ from typing import Union from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User from redbot.core import commands +from redbot.core.bot import Red from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning from ..models.moderation import Moderation from ..models.partials import PartialUser from .config import config -from .utils import get_bool_emoji, get_next_case_number, get_pagesize_str +from .utils import get_bool_emoji, get_pagesize_str async def message_factory( + bot: Red, color: Color, guild: Guild, reason: str, @@ -25,6 +27,7 @@ async def message_factory( """This function creates a message from set parameters, meant for contacting the moderated user. Args: + bot (Red): The bot instance. color (Color): The color of the embed. guild (Guild): The guild the moderation occurred in. reason (str): The reason for the moderation. @@ -88,7 +91,7 @@ async def message_factory( embed.set_author(name=guild.name) embed.set_footer( - text=f"Case #{get_next_case_number(guild.id):,}", + text=f"Case #{Moderation.get_next_case_number(bot=bot, guild_id=guild.id):,}", icon_url="attachment://arrow.png", ) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index b70ec83..96eea2b 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -110,20 +110,6 @@ async def check_moddable( return True -def get_next_case_number(guild_id: str, cursor=None) -> int: - """This function returns the next case number from the MySQL table for a specific guild.""" - from .database import connect - - if not cursor: - database = connect() - cursor = database.cursor() - cursor.execute( - f"SELECT moderation_id FROM `moderation_{guild_id}` ORDER BY moderation_id DESC LIMIT 1" - ) - result = cursor.fetchone() - return (result[0] + 1) if result else 1 - - async def log(interaction: Interaction, moderation_id: int, resolved: bool = False) -> None: """This function sends a message to the guild's configured logging channel when an infraction takes place.""" from ..models.moderation import Moderation @@ -134,7 +120,7 @@ async def log(interaction: Interaction, moderation_id: int, resolved: bool = Fal logging_channel = interaction.guild.get_channel(logging_channel_id) try: - moderation = Moderation.from_sql(interaction.client, moderation_id, interaction.guild_id) + moderation = Moderation.find_by_id(interaction.client, moderation_id, interaction.guild_id) embed = await log_factory( interaction=interaction, moderation=moderation, resolved=resolved ) @@ -159,7 +145,7 @@ async def send_evidenceformat(interaction: Interaction, moderation_id: int) -> N if send_evidence_bool is False: return - moderation = Moderation.from_sql(interaction.client, moderation_id, interaction.guild.id) + moderation = Moderation.find_by_id(interaction.client, moderation_id, interaction.guild.id) content = await evidenceformat_factory(moderation=moderation) await interaction.followup.send(content=content, ephemeral=True) -- 2.45.3 From 1c6d2456ed844c1c48e3d910649f09486e0089b7 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 00:04:46 -0400 Subject: [PATCH 146/376] misc(aurora): changed `aurora.utilities.utils.get_bool_emoji` to use `match/case` instead of `if/else` --- aurora/utilities/utils.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 96eea2b..f2adae0 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -152,11 +152,13 @@ async def send_evidenceformat(interaction: Interaction, moderation_id: int) -> N def get_bool_emoji(value: Optional[bool]) -> str: """Returns a unicode emoji based on a boolean value.""" - if value is True: - return "\N{WHITE HEAVY CHECK MARK}" - if value is False: - return "\N{NO ENTRY SIGN}" - return "\N{BLACK QUESTION MARK ORNAMENT}\N{VARIATION SELECTOR-16}" + match value: + case True: + return "\N{WHITE HEAVY CHECK MARK}" + case False: + return "\N{NO ENTRY SIGN}" + case _: + return "\N{BLACK QUESTION MARK ORNAMENT}\N{VARIATION SELECTOR-16}" def get_pagesize_str(value: Union[int, None]) -> str: -- 2.45.3 From cb420d2fc40af42049409153ca6cc96226dc625c Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 11:52:34 -0400 Subject: [PATCH 147/376] fix(aurora): pylint/ruff fix --- aurora/aurora.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 37da97c..1efb03c 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -20,7 +20,6 @@ from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning -from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning from .importers.aurora import ImportAuroraView from .importers.galacticbot import ImportGalacticBotView -- 2.45.3 From a10af37f143528420c67c99d89e3eb6757bae05e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 12:23:12 -0400 Subject: [PATCH 148/376] feat(aurora): add support for `OFFSET` in `Moderation.get_latest()` --- aurora/models/moderation.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 5462ba3..bb36a90 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -229,9 +229,9 @@ class Moderation(AuroraGuildModel): return () @classmethod - def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: - params = [] - query = f"SELECT * FROM moderation_{guild_id} ORDER BY moderation_id DESC" + def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, offset: int = 0, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + params = [offset] + query = f"SELECT * FROM moderation_{guild_id} ORDER BY moderation_id DESC OFFSET ?" if limit: query += " LIMIT ?" params.append(limit) @@ -239,7 +239,7 @@ class Moderation(AuroraGuildModel): query += f" WHERE moderation_type IN ({', '.join(['?' for _ in types])})" params.extend(types) query += ";" - return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=tuple(params) if limit else (), cursor=cursor) + return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=tuple(params) if params else (), cursor=cursor) @classmethod def get_next_case_number(cls, bot: Red, guild_id: int, cursor: Cursor | None = None) -> int: -- 2.45.3 From 38180f5ccdb986a147a29708198cd7479ee4f12d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 12:29:24 -0400 Subject: [PATCH 149/376] fix(aurora): fixed an sql operation error --- aurora/models/moderation.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index bb36a90..53ad512 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -230,14 +230,14 @@ class Moderation(AuroraGuildModel): @classmethod def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, offset: int = 0, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: - params = [offset] - query = f"SELECT * FROM moderation_{guild_id} ORDER BY moderation_id DESC OFFSET ?" - if limit: - query += " LIMIT ?" - params.append(limit) + params = [] + query = f"SELECT * FROM moderation_{guild_id} ORDER BY moderation_id DESC" if types: query += f" WHERE moderation_type IN ({', '.join(['?' for _ in types])})" params.extend(types) + if limit: + query += " LIMIT ? OFFSET ?" + params.extend((limit, offset)) query += ";" return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=tuple(params) if params else (), cursor=cursor) -- 2.45.3 From 21fa3d9eb09b0aca889c2ca8d1de7d87610f0c54 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 12:44:58 -0400 Subject: [PATCH 150/376] feat(aurora): added an `__int__` dunder method to the moderation model --- aurora/models/moderation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 53ad512..3111eb2 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -66,6 +66,9 @@ class Moderation(AuroraGuildModel): def __str__(self) -> str: return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}" + def __int__(self) -> int: + return self.moderation_id + async def resolve(self, resolved_by: int, reason: str) -> None: if self.resolved: raise ValueError("Case is already resolved!") -- 2.45.3 From 8ac735dafebfd2fd84e9383478953e3194b7c4fe Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 14:20:01 -0400 Subject: [PATCH 151/376] misc(aurora): change the JSONEncoder subclass to use match/case instead of if statements --- aurora/utilities/json.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index 80f1259..5dbd4eb 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -1,5 +1,6 @@ import json from datetime import datetime, timedelta +from typing import Any from redbot.core.bot import Red @@ -7,16 +8,18 @@ from ..models.base import AuroraBaseModel class JSONEncoder(json.JSONEncoder): - def default(self, o): - if isinstance(o, datetime): - return int(o.timestamp()) - if isinstance(o, timedelta): - return str(o) - if isinstance(o, AuroraBaseModel): - return o.dump() - if isinstance(o, Red): - return None - return super().default(o) + def default(self, o) -> Any: + match o: + case datetime(): + return int(o.timestamp()) + case timedelta(): + return str(o) + case AuroraBaseModel(): + return o.dump() + case Red(): + return None + case _: + return super().default(o) # This is a wrapper around the json module's dumps function that uses our custom JSONEncoder class -- 2.45.3 From 0089625ef371a9810aa18a5762aad6d2adceee6b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 14:56:51 -0400 Subject: [PATCH 152/376] fix(aurora): add a debug statement --- aurora/models/moderation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 3111eb2..89ba6f9 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -166,6 +166,7 @@ class Moderation(AuroraGuildModel): @classmethod def from_result(cls, bot: Red, result: Iterable, guild_id: int) -> "Moderation": if result[7] is not None: + logger.debug(result[7]) hours, minutes, seconds = map(int, result[7].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) else: -- 2.45.3 From 5151f653174f4aad4f3a307022edfec538d20a8b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 14:59:57 -0400 Subject: [PATCH 153/376] fix(aurora): added more to the debugging statement --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 89ba6f9..ff73aa0 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -166,7 +166,7 @@ class Moderation(AuroraGuildModel): @classmethod def from_result(cls, bot: Red, result: Iterable, guild_id: int) -> "Moderation": if result[7] is not None: - logger.debug(result[7]) + logger.debug("%s | %s", result[7], type(result[7])) hours, minutes, seconds = map(int, result[7].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) else: -- 2.45.3 From 0a207b66e4c79c5a2f6e7e20820e3355f0d1eba1 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 15:22:50 -0400 Subject: [PATCH 154/376] fix(aurora): fixed an error with timedelta formatting --- aurora/models/moderation.py | 3 ++- aurora/utilities/utils.py | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index ff73aa0..363b163 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -10,6 +10,7 @@ from discord import NotFound from redbot.core.bot import Red from ..utilities.logger import logger +from ..utilities.utils import timedelta_to_string from .base import AuroraGuildModel from .change import Change from .partials import PartialChannel, PartialRole, PartialUser @@ -348,7 +349,7 @@ class Moderation(AuroraGuildModel): "target_id": target_id, "moderator_id": moderator_id, "role_id": role_id, - "duration": str(duration) if duration else None, + "duration": timedelta_to_string(duration) if duration else None, "end_timestamp": end_timestamp.timestamp() if end_timestamp else None, "reason": reason, "resolved": resolved, diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index f2adae0..1e6bdd6 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -194,6 +194,12 @@ def timedelta_from_relativedelta(relativedelta: rd) -> timedelta: then = now - relativedelta return now - then +def timedelta_to_string(timedelta: timedelta) -> str: + """Converts a timedelta object to a string.""" + hours, remainder = divmod(timedelta.seconds, 3600) + minutes, seconds = divmod(remainder, 60) + return f"{hours}:{minutes}:{seconds}s" + def get_footer_image(coginstance: commands.Cog) -> File: """Returns the footer image for the embeds.""" image_path = data_manager.bundled_data_path(coginstance) / "arrow.png" -- 2.45.3 From 166421b6bacc5fca73837ccb99c66ffeb8a80ab6 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 15:23:45 -0400 Subject: [PATCH 155/376] fix(aurora): removed a character causing a valueerror --- aurora/utilities/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 1e6bdd6..bd130d4 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -198,7 +198,7 @@ def timedelta_to_string(timedelta: timedelta) -> str: """Converts a timedelta object to a string.""" hours, remainder = divmod(timedelta.seconds, 3600) minutes, seconds = divmod(remainder, 60) - return f"{hours}:{minutes}:{seconds}s" + return f"{hours}:{minutes}:{seconds}" def get_footer_image(coginstance: commands.Cog) -> File: """Returns the footer image for the embeds.""" -- 2.45.3 From 5d53eec2f19c3b1b122bc1936bbac8e2337f388c Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 15:32:59 -0400 Subject: [PATCH 156/376] fix(aurora): fixed a valueerror in the `Change.from_dict()` method --- aurora/models/change.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index 0c7148a..0d0337f 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -53,10 +53,14 @@ class Change(AuroraBaseModel): else: timestamp = data["timestamp"] + try: + data["user_id"] = int(data["user_id"]) + except ValueError: + data["user_id"] = 0 + data.update({ "timestamp": timestamp, "end_timestamp": end_timestamp, - "duration": duration, - "user_id": int(data["user_id"]) + "duration": duration }) return cls(bot=bot, **data) -- 2.45.3 From 3168c42787d7d7374092aef22542aa5e4df03532 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 15:36:38 -0400 Subject: [PATCH 157/376] fix(aurora): fixed a pydantic ValidationError --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 363b163..0d67e9c 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -323,7 +323,7 @@ class Moderation(AuroraGuildModel): if reason == "NULL": reason = None - if resolved_by == "NULL": + if resolved_by == "NULL" or resolved_by == '?': resolved_by = None if resolved_reason == "NULL": -- 2.45.3 From 7a664ce9c3c2912882160001bc36a7a944a2b8e1 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 15:37:58 -0400 Subject: [PATCH 158/376] fix(aurora): make `Change.reason` optional --- aurora/models/change.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index 0d0337f..e219ed7 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -12,8 +12,8 @@ from .partials import PartialUser class Change(AuroraBaseModel): type: Literal["ORIGINAL", "RESOLVE", "EDIT"] timestamp: datetime - reason: str user_id: int + reason: Optional[str] = "No reason provided" duration: Optional[timedelta] = None end_timestamp: Optional[datetime] = None -- 2.45.3 From fdb96539c38d8e6736370cf566921bdb00b9c1a8 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 15:39:16 -0400 Subject: [PATCH 159/376] fix(aurora): removed a useless debug statement --- aurora/models/moderation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 0d67e9c..0f1a467 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -167,7 +167,6 @@ class Moderation(AuroraGuildModel): @classmethod def from_result(cls, bot: Red, result: Iterable, guild_id: int) -> "Moderation": if result[7] is not None: - logger.debug("%s | %s", result[7], type(result[7])) hours, minutes, seconds = map(int, result[7].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) else: -- 2.45.3 From ff66006b8a41bf741cf5fc77902176b422dfafd2 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 15:43:15 -0400 Subject: [PATCH 160/376] misc(aurora): add more logging --- aurora/models/change.py | 4 ++-- aurora/models/moderation.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index e219ed7..d516f56 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -29,10 +29,10 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Change": - logger.trace("Creating Change from dict (%s): %s", type(data), data) + logger.verbose("Creating Change from dict (%s): %s", type(data), data) if isinstance(data, str): data = json.loads(data) - logger.trace("Change data was a string, converted to dict: %s", data) + logger.verbose("Change data was a string, converted to dict: %s", data) if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): hours, minutes, seconds = map(int, data["duration"].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 0f1a467..bf0dba2 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -162,6 +162,7 @@ class Moderation(AuroraGuildModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Moderation": + logger.verbose("Creating Moderation from dict (%s): %s", type(data), data) return cls(bot=bot, **data) @classmethod @@ -208,6 +209,8 @@ class Moderation(AuroraGuildModel): @classmethod def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: from ..utilities.database import connect + logger.trace("Executing query: %s", query) + logger.trace("With parameters: %s", parameters) if not parameters: parameters = () if not cursor: -- 2.45.3 From 720e100a209a591137299106690f73fa5b4a4313 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 15:52:23 -0400 Subject: [PATCH 161/376] fix(aurora): removed some logging statements --- aurora/models/change.py | 3 --- aurora/models/moderation.py | 1 - 2 files changed, 4 deletions(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index d516f56..cece847 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -4,7 +4,6 @@ from typing import Literal, Optional from redbot.core.bot import Red -from ..utilities.logger import logger from .base import AuroraBaseModel from .partials import PartialUser @@ -29,10 +28,8 @@ class Change(AuroraBaseModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Change": - logger.verbose("Creating Change from dict (%s): %s", type(data), data) if isinstance(data, str): data = json.loads(data) - logger.verbose("Change data was a string, converted to dict: %s", data) if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): hours, minutes, seconds = map(int, data["duration"].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index bf0dba2..1b43ee8 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -162,7 +162,6 @@ class Moderation(AuroraGuildModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Moderation": - logger.verbose("Creating Moderation from dict (%s): %s", type(data), data) return cls(bot=bot, **data) @classmethod -- 2.45.3 From b252343dc0c65a39a6e4eefd0824d1d5f57b208c Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 16:35:18 -0400 Subject: [PATCH 162/376] misc(aurora): allow `Moderation.log()` to skip returning the class object --- aurora/importers/aurora.py | 1 + aurora/models/moderation.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index c184c1c..fd26518 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -114,6 +114,7 @@ class ImportAuroraView(ui.View): changes=changes, metadata=metadata, database=database, + return_obj=False ) await interaction.edit_original_response(content="Import complete.") diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 1b43ee8..73f7bf0 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -298,7 +298,8 @@ class Moderation(AuroraGuildModel): expired: bool | None = None, changes: list | None = None, metadata: dict | None = None, - ) -> "Moderation": + return_obj: bool = True, + ) -> "Moderation" | None: from ..utilities.database import connect from ..utilities.json import dumps if not timestamp: @@ -390,4 +391,5 @@ class Moderation(AuroraGuildModel): case["metadata"], ) - return cls.find_by_id(bot=bot, moderation_id=moderation_id, guild_id=guild_id) + if return_obj: + return cls.find_by_id(bot=bot, moderation_id=moderation_id, guild_id=guild_id) -- 2.45.3 From 3fdc54b7cbb2db0497b21169202e50281e7172e0 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 16:37:28 -0400 Subject: [PATCH 163/376] fix(aurora): get_next_case_number now only retrieves the first entry in the sql database (using `LIMIT 1`) --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 73f7bf0..5a26637 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -249,7 +249,7 @@ class Moderation(AuroraGuildModel): @classmethod def get_next_case_number(cls, bot: Red, guild_id: int, cursor: Cursor | None = None) -> int: - result = cls.get_latest(bot=bot, guild_id=guild_id, cursor=cursor) + result = cls.get_latest(bot=bot, guild_id=guild_id, cursor=cursor, limit=1) return (result[0].moderation_id + 1) if result else 1 @classmethod -- 2.45.3 From 3d2dabae08a6a1df6738defe9d44817da82d67d6 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 16:50:33 -0400 Subject: [PATCH 164/376] fix(aurora): fixed a typeerror --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 5a26637..c5ff023 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -299,7 +299,7 @@ class Moderation(AuroraGuildModel): changes: list | None = None, metadata: dict | None = None, return_obj: bool = True, - ) -> "Moderation" | None: + ) -> Union["Moderation", None]: from ..utilities.database import connect from ..utilities.json import dumps if not timestamp: -- 2.45.3 From ff3431011382c4596b58e0c358c5bce7cc2a97d0 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 16:52:19 -0400 Subject: [PATCH 165/376] fix(aurora): fixed a valueerror --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index c5ff023..28b4d73 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -166,7 +166,7 @@ class Moderation(AuroraGuildModel): @classmethod def from_result(cls, bot: Red, result: Iterable, guild_id: int) -> "Moderation": - if result[7] is not None: + if result[7] is not None and result[7] != "NULL": hours, minutes, seconds = map(int, result[7].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) else: -- 2.45.3 From ce48c1e8890900219c4e2d802c80ac0d0c94ab5c Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 16:55:29 -0400 Subject: [PATCH 166/376] fix(aurora): fixed a valueerror --- aurora/models/change.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index cece847..d3fdd99 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -30,7 +30,7 @@ class Change(AuroraBaseModel): def from_dict(cls, bot: Red, data: dict) -> "Change": if isinstance(data, str): data = json.loads(data) - if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta): + if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta) and not data["duration"] == "NULL": hours, minutes, seconds = map(int, data["duration"].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) elif "duration" in data and isinstance(data["duration"], timedelta): -- 2.45.3 From 74d122a2e759efd2aa30703de54c33a7a188d07e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 23:31:36 -0400 Subject: [PATCH 167/376] fix(aurora): catch importer errors instead of letting the entire import process die --- aurora/importers/aurora.py | 43 ++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index fd26518..ced2566 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -96,26 +96,29 @@ class ImportAuroraView(ui.View): else: duration = None - Moderation.log( - bot=interaction.client, - guild_id=self.ctx.guild.id, - moderator_id=case["moderator_id"], - moderation_type=case["moderation_type"], - target_type=case["target_type"], - target_id=case["target_id"], - role_id=case["role_id"], - duration=duration, - reason=case["reason"], - timestamp=case["timestamp"], - resolved=case["resolved"], - resolved_by=case["resolved_by"], - resolved_reason=case["resolve_reason"], - expired=case["expired"], - changes=changes, - metadata=metadata, - database=database, - return_obj=False - ) + try: + Moderation.log( + bot=interaction.client, + guild_id=self.ctx.guild.id, + moderator_id=case["moderator_id"], + moderation_type=case["moderation_type"], + target_type=case["target_type"], + target_id=case["target_id"], + role_id=case["role_id"], + duration=duration, + reason=case["reason"], + timestamp=case["timestamp"], + resolved=case["resolved"], + resolved_by=case["resolved_by"], + resolved_reason=case["resolve_reason"], + expired=case["expired"], + changes=changes, + metadata=metadata, + database=database, + return_obj=False + ) + except Exception as e: + failed_cases.append(str(case["moderation_id"]) + f": {e}") await interaction.edit_original_response(content="Import complete.") if failed_cases: -- 2.45.3 From 78630dc317a6819bb6a55d3c7b7cdbc1b9fc2568 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 23:31:52 -0400 Subject: [PATCH 168/376] feat(aurora): added timedelta_from_string() function --- aurora/importers/aurora.py | 5 ++--- aurora/utilities/utils.py | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index ced2566..462a7bd 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -1,6 +1,5 @@ # pylint: disable=duplicate-code import json -from datetime import timedelta from time import time from typing import Dict @@ -10,6 +9,7 @@ from redbot.core.utils.chat_formatting import box, warning from ..models.moderation import Moderation from ..utilities.database import connect, create_guild_table +from ..utilities.utils import timedelta_from_string class ImportAuroraView(ui.View): @@ -91,8 +91,7 @@ class ImportAuroraView(ui.View): metadata.update({"imported_timestamp": int(time())}) if case["duration"] != "NULL" and case["duration"] is not None: - hours, minutes, seconds = map(int, case["duration"].split(":")) - duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) + duration = timedelta_from_string(case["duration"]) else: duration = None diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index bd130d4..834035d 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -194,6 +194,13 @@ def timedelta_from_relativedelta(relativedelta: rd) -> timedelta: then = now - relativedelta return now - then +def timedelta_from_string(string: str) -> timedelta: + """Converts a string to a timedelta object.""" + from .logger import logger + hours, minutes, seconds = map(int, string.split(":")) + logger.debug("%s | hours: %s, minutes: %s, seconds: %s", string, hours, minutes, seconds) + return timedelta(hours=hours, minutes=minutes, seconds=seconds) + def timedelta_to_string(timedelta: timedelta) -> str: """Converts a timedelta object to a string.""" hours, remainder = divmod(timedelta.seconds, 3600) -- 2.45.3 From 8591649465a272f05b6cf937c6248669defcb1a9 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 23:43:53 -0400 Subject: [PATCH 169/376] fix(aurora): fixed `aurora.utilities.utils.timedelta_from_string` not including days in its calculations --- aurora/utilities/utils.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 834035d..93e4fc1 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -196,16 +196,15 @@ def timedelta_from_relativedelta(relativedelta: rd) -> timedelta: def timedelta_from_string(string: str) -> timedelta: """Converts a string to a timedelta object.""" - from .logger import logger hours, minutes, seconds = map(int, string.split(":")) - logger.debug("%s | hours: %s, minutes: %s, seconds: %s", string, hours, minutes, seconds) return timedelta(hours=hours, minutes=minutes, seconds=seconds) def timedelta_to_string(timedelta: timedelta) -> str: """Converts a timedelta object to a string.""" + days = timedelta.days * 24 hours, remainder = divmod(timedelta.seconds, 3600) minutes, seconds = divmod(remainder, 60) - return f"{hours}:{minutes}:{seconds}" + return f"{days + hours}:{minutes:02}:{seconds:02}" def get_footer_image(coginstance: commands.Cog) -> File: """Returns the footer image for the embeds.""" -- 2.45.3 From 0d64e3f6520f101c7c25380f40245ddc5032b3b7 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 23:52:35 -0400 Subject: [PATCH 170/376] misc(aurora): convert `Change.from_dict()` to use `utils.timedelta_from_string()` --- aurora/models/change.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index d3fdd99..22ac222 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -4,6 +4,7 @@ from typing import Literal, Optional from redbot.core.bot import Red +from ..utilities.utils import timedelta_from_string from .base import AuroraBaseModel from .partials import PartialUser @@ -31,8 +32,7 @@ class Change(AuroraBaseModel): if isinstance(data, str): data = json.loads(data) if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta) and not data["duration"] == "NULL": - hours, minutes, seconds = map(int, data["duration"].split(':')) - duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) + duration = timedelta_from_string(data["duration"]) elif "duration" in data and isinstance(data["duration"], timedelta): duration = data["duration"] else: -- 2.45.3 From 027144f35d3d4e6571ed3c16a2e0464e634124b6 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 4 Jun 2024 23:55:55 -0400 Subject: [PATCH 171/376] fix(aurora): pylint fixes --- aurora/importers/aurora.py | 2 +- aurora/models/moderation.py | 5 +++-- aurora/utilities/utils.py | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 462a7bd..87091bd 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -116,7 +116,7 @@ class ImportAuroraView(ui.View): database=database, return_obj=False ) - except Exception as e: + except Exception as e: # pylint: disable=broad-exception-caught failed_cases.append(str(case["moderation_id"]) + f": {e}") await interaction.edit_original_response(content="Import complete.") diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 28b4d73..f527fff 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -299,7 +299,7 @@ class Moderation(AuroraGuildModel): changes: list | None = None, metadata: dict | None = None, return_obj: bool = True, - ) -> Union["Moderation", None]: + ) -> Union["Moderation", int]: from ..utilities.database import connect from ..utilities.json import dumps if not timestamp: @@ -325,7 +325,7 @@ class Moderation(AuroraGuildModel): if reason == "NULL": reason = None - if resolved_by == "NULL" or resolved_by == '?': + if resolved_by in ["NULL", "?"]: resolved_by = None if resolved_reason == "NULL": @@ -393,3 +393,4 @@ class Moderation(AuroraGuildModel): if return_obj: return cls.find_by_id(bot=bot, moderation_id=moderation_id, guild_id=guild_id) + return moderation_id diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 93e4fc1..ea39d65 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -199,10 +199,10 @@ def timedelta_from_string(string: str) -> timedelta: hours, minutes, seconds = map(int, string.split(":")) return timedelta(hours=hours, minutes=minutes, seconds=seconds) -def timedelta_to_string(timedelta: timedelta) -> str: +def timedelta_to_string(td: timedelta) -> str: """Converts a timedelta object to a string.""" - days = timedelta.days * 24 - hours, remainder = divmod(timedelta.seconds, 3600) + days = td.days * 24 + hours, remainder = divmod(td.seconds, 3600) minutes, seconds = divmod(remainder, 60) return f"{days + hours}:{minutes:02}:{seconds:02}" -- 2.45.3 From 5cbf4e7e47b3d01716a4329b83daef87cd983df2 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 00:14:43 -0400 Subject: [PATCH 172/376] feat(aurora): migrated to aiosqlite --- aurora/aurora.py | 102 ++++++++++++++++---------------- aurora/importers/aurora.py | 14 ++--- aurora/importers/galacticbot.py | 12 ++-- aurora/info.json | 2 +- aurora/models/moderation.py | 61 ++++++++++--------- aurora/utilities/database.py | 27 ++++----- aurora/utilities/utils.py | 4 +- poetry.lock | 20 ++++++- pyproject.toml | 1 + 9 files changed, 127 insertions(+), 116 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 1efb03c..0b4463a 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -7,11 +7,11 @@ import json import os -import sqlite3 import time from datetime import datetime, timedelta, timezone from math import ceil +import aiosqlite import discord from discord import Object from discord.ext import tasks @@ -50,21 +50,21 @@ class Aurora(commands.Cog): if requester == "discord_deleted_user": await config.user_from_id(user_id).clear() - database = connect() - cursor = database.cursor() + database = await connect() + cursor = await database.cursor() - cursor.execute("SHOW TABLES;") + await cursor.execute("SHOW TABLES;") tables = [table[0] for table in cursor.fetchall()] condition = "target_id = %s OR moderator_id = %s;" for table in tables: delete_query = f"DELETE FROM {table[0]} WHERE {condition}" - cursor.execute(delete_query, (user_id, user_id)) + await cursor.execute(delete_query, (user_id, user_id)) - database.commit() - cursor.close() - database.close() + await database.commit() + await cursor.close() + await database.close() if requester == "owner": await config.user_from_id(user_id).clear() if requester == "user": @@ -121,15 +121,13 @@ class Aurora(commands.Cog): async def addrole_on_member_join(self, member: discord.Member): """This method automatically adds roles to users when they join the server.""" if not await self.bot.cog_disabled_in_guild(self, member.guild): - query = f"""SELECT moderation_id, role_id, reason FROM moderation_{member.guild.id} WHERE target_id = ? AND moderation_type = 'ADDROLE' AND expired = 0 AND resolved = 0;""" - database = connect() - cursor = database.cursor() - cursor.execute(query, (member.id,)) - results = cursor.fetchall() - for result in results: - role = member.guild.get_role(result[1]) - reason = result[2] - await member.add_roles(role, reason=f"Role automatically added on member rejoin for: {reason} (Case #{result[0]:,})") + async with connect() as database: + query = f"""SELECT moderation_id, role_id, reason FROM moderation_{member.guild.id} WHERE target_id = ? AND moderation_type = 'ADDROLE' AND expired = 0 AND resolved = 0;""" + async with database.execute(query, (member.id,)) as cursor: + async for row in cursor: + role = member.guild.get_role(row[1]) + reason = row[2] + await member.add_roles(role, reason=f"Role automatically added on member rejoin for: {reason} (Case #{row[0]:,})") @commands.Cog.listener("on_audit_log_entry_create") async def autologger(self, entry: discord.AuditLogEntry): @@ -175,7 +173,7 @@ class Aurora(commands.Cog): else: return - Moderation.log( + await Moderation.log( self.bot, entry.guild.id, entry.user.id, @@ -233,7 +231,7 @@ class Aurora(commands.Cog): except discord.errors.HTTPException: pass - moderation = Moderation.log( + moderation = await Moderation.log( interaction.client, interaction.guild.id, interaction.user.id, @@ -292,7 +290,7 @@ class Aurora(commands.Cog): except discord.errors.HTTPException: pass - moderation = Moderation.log( + moderation = await Moderation.log( interaction.client, interaction.guild.id, interaction.user.id, @@ -398,7 +396,7 @@ class Aurora(commands.Cog): content=f"{target.mention} has been given the {role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" ) - moderation = Moderation.log( + moderation = await Moderation.log( interaction.client, interaction.guild.id, interaction.user.id, @@ -504,7 +502,7 @@ class Aurora(commands.Cog): content=f"{target.mention} has had the {role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" ) - moderation = Moderation.log( + moderation = await Moderation.log( interaction.client, interaction.guild.id, interaction.user.id, @@ -592,7 +590,7 @@ class Aurora(commands.Cog): except discord.errors.HTTPException: pass - moderation = Moderation.log( + moderation = await Moderation.log( interaction.client, interaction.guild.id, interaction.user.id, @@ -728,7 +726,7 @@ class Aurora(commands.Cog): await target.kick(reason=f"Kicked by {interaction.user.id} for: {reason}") - moderation = Moderation.log( + moderation = await Moderation.log( interaction.client, interaction.guild.id, interaction.user.id, @@ -836,7 +834,7 @@ class Aurora(commands.Cog): delete_message_seconds=delete_messages_seconds, ) - moderation = Moderation.log( + moderation = await Moderation.log( interaction.client, interaction.guild.id, interaction.user.id, @@ -880,7 +878,7 @@ class Aurora(commands.Cog): delete_message_seconds=delete_messages_seconds, ) - moderation = Moderation.log( + moderation = await Moderation.log( interaction.client, interaction.guild.id, interaction.user.id, @@ -957,7 +955,7 @@ class Aurora(commands.Cog): except discord.errors.HTTPException: pass - moderation = Moderation.log( + moderation = await Moderation.log( interaction.client, interaction.guild.id, interaction.user.id, @@ -1001,7 +999,7 @@ class Aurora(commands.Cog): await channel.edit(slowmode_delay=interval) await interaction.response.send_message(f"Slowmode in {channel.mention} has been set to {interval} seconds!\n**Reason** - `{reason}`") - moderation = Moderation.log( + moderation = await Moderation.log( interaction.client, interaction.guild.id, interaction.user.id, @@ -1089,7 +1087,7 @@ class Aurora(commands.Cog): ) return - database = connect() + database = await connect() if export: try: @@ -1099,7 +1097,7 @@ class Aurora(commands.Cog): + f"moderation_{interaction.guild.id}.json" ) - cases = Moderation.get_latest(bot=interaction.client, guild_id=interaction.guild.id) + cases = await Moderation.get_latest(bot=interaction.client, guild_id=interaction.guild.id) with open(filename, "w", encoding="utf-8") as f: dump(obj=cases, fp=f, indent=2) @@ -1120,15 +1118,15 @@ class Aurora(commands.Cog): + box(e, "py"), ephemeral=ephemeral, ) - database.close() + await database.close() return if target: - moderations = Moderation.find_by_target(interaction.client, interaction.guild.id, target.id) + moderations = await Moderation.find_by_target(interaction.client, interaction.guild.id, target.id) elif moderator: - moderations = Moderation.find_by_moderator(interaction.client, interaction.guild.id, moderator.id) + moderations = await Moderation.find_by_moderator(interaction.client, interaction.guild.id, moderator.id) else: - moderations = Moderation.get_latest(interaction.client, interaction.guild.id) + moderations = await Moderation.get_latest(interaction.client, interaction.guild.id) case_quantity = len(moderations) page_quantity = ceil(case_quantity / pagesize) @@ -1214,7 +1212,7 @@ class Aurora(commands.Cog): return try: - moderation = Moderation.find_by_id(interaction.client, case, interaction.guild.id) + moderation = await Moderation.find_by_id(interaction.client, case, interaction.guild.id) except ValueError: await interaction.response.send_message( content=error(f"Case #{case:,} does not exist!"), ephemeral=True @@ -1298,7 +1296,7 @@ class Aurora(commands.Cog): ) try: - mod = Moderation.find_by_id(interaction.client, case, interaction.guild.id) + mod = await Moderation.find_by_id(interaction.client, case, interaction.guild.id) except ValueError: await interaction.response.send_message( content=error(f"Case #{case:,} does not exist!"), ephemeral=True @@ -1391,7 +1389,7 @@ class Aurora(commands.Cog): return try: - moderation = Moderation.find_by_id(interaction.client, case, interaction.guild.id) + moderation = await Moderation.find_by_id(interaction.client, case, interaction.guild.id) old_moderation = moderation except ValueError: await interaction.response.send_message( @@ -1469,7 +1467,7 @@ class Aurora(commands.Cog): "end_timestamp": moderation.end_timestamp, })) - moderation.update() + await moderation.update() embed = await case_factory(interaction=interaction, moderation=moderation) await interaction.response.send_message( @@ -1485,8 +1483,8 @@ class Aurora(commands.Cog): async def handle_expiry(self): await self.bot.wait_until_red_ready() current_time = time.time() - database = connect() - cursor = database.cursor() + database = await connect() + cursor = await database.cursor() global_unban_num = 0 global_addrole_num = 0 global_removerole_num = 0 @@ -1499,9 +1497,9 @@ class Aurora(commands.Cog): tempban_query = f"SELECT target_id, moderation_id FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'TEMPBAN' AND expired = 0" try: - cursor.execute(tempban_query, (time.time(),)) + await cursor.execute(tempban_query, (time.time(),)) result = cursor.fetchall() - except sqlite3.OperationalError: + except aiosqlite.OperationalError: continue target_ids = [row[0] for row in result] @@ -1558,9 +1556,9 @@ class Aurora(commands.Cog): removerole_num = 0 addrole_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL AND end_timestamp <= ? AND moderation_type = 'ADDROLE' AND expired = 0" try: - cursor.execute(addrole_query, (time.time(),)) - result = cursor.fetchall() - except sqlite3.OperationalError: + await cursor.execute(addrole_query, (time.time(),)) + result = await cursor.fetchall() + except aiosqlite.OperationalError: continue target_ids = [row[0] for row in result] moderation_ids = [row[1] for row in result] @@ -1593,9 +1591,9 @@ class Aurora(commands.Cog): addrole_num = 0 removerole_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'REMOVEROLE' AND expired = 0" try: - cursor.execute(removerole_query, (time.time(),)) - result = cursor.fetchall() - except sqlite3.OperationalError: + await cursor.execute(removerole_query, (time.time(),)) + result = await cursor.fetchall() + except aiosqlite.OperationalError: continue target_ids = [row[0] for row in result] moderation_ids = [row[1] for row in result] @@ -1621,7 +1619,7 @@ class Aurora(commands.Cog): continue expiry_query = f"UPDATE `moderation_{guild.id}` SET expired = 1 WHERE (end_timestamp IS NOT NULL AND end_timestamp <= ? AND expired = 0) OR (expired = 0 AND resolved = 1);" - cursor.execute(expiry_query, (time.time(),)) + await cursor.execute(expiry_query, (time.time(),)) per_guild_completion_time = (time.time() - time_per_guild) * 1000 logger.debug( @@ -1637,9 +1635,9 @@ class Aurora(commands.Cog): global_addrole_num = global_addrole_num + addrole_num global_removerole_num = global_removerole_num + removerole_num - database.commit() - cursor.close() - database.close() + await database.commit() + await cursor.close() + await database.close() completion_time = (time.time() - current_time) * 1000 logger.debug( diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 87091bd..f154dab 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -27,14 +27,10 @@ class ImportAuroraView(ui.View): "Deleting original table...", ephemeral=True ) - database = connect() - cursor = database.cursor() - - query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};" - cursor.execute(query) - - cursor.close() - database.commit() + async with connect() as database: + query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};" + database.execute(query) + database.commit() await interaction.edit_original_response(content="Creating new table...") @@ -96,7 +92,7 @@ class ImportAuroraView(ui.View): duration = None try: - Moderation.log( + await Moderation.log( bot=interaction.client, guild_id=self.ctx.guild.id, moderator_id=case["moderator_id"], diff --git a/aurora/importers/galacticbot.py b/aurora/importers/galacticbot.py index a7c2d27..453cac0 100644 --- a/aurora/importers/galacticbot.py +++ b/aurora/importers/galacticbot.py @@ -26,14 +26,14 @@ class ImportGalacticBotView(ui.View): "Deleting original table...", ephemeral=True ) - database = connect() - cursor = database.cursor() + database = await connect() + cursor = await database.cursor() query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};" - cursor.execute(query) + await cursor.execute(query) - cursor.close() - database.commit() + await cursor.close() + await database.commit() await interaction.edit_original_response(content="Creating new table...") @@ -124,7 +124,7 @@ class ImportGalacticBotView(ui.View): else: reason = None - Moderation.log( + await Moderation.log( self.ctx.guild.id, case["executor"], case["type"], diff --git a/aurora/info.json b/aurora/info.json index d232f7e..34b74c9 100644 --- a/aurora/info.json +++ b/aurora/info.json @@ -9,7 +9,7 @@ "disabled": false, "min_bot_version": "3.5.0", "min_python_version": [3, 10, 0], - "requirements": ["pydantic"], + "requirements": ["pydantic", "aiosqlite"], "tags": [ "mod", "moderate", diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index f527fff..31912d1 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -1,11 +1,11 @@ import json import sqlite3 from datetime import datetime, timedelta -from sqlite3 import Cursor from time import time from typing import Dict, Iterable, List, Optional, Tuple, Union import discord +from aiosqlite import Cursor from discord import NotFound from redbot.core.bot import Red @@ -115,15 +115,15 @@ class Moderation(AuroraGuildModel): "user_id": resolved_by, })) - self.update() + await self.update() - def update(self) -> None: + async def update(self) -> None: from ..utilities.database import connect from ..utilities.json import dumps query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" - with connect() as database: - database.execute(query, ( + async with connect() as database: + await database.execute(query, ( self.timestamp.timestamp(), self.moderation_type, self.target_type, @@ -206,7 +206,7 @@ class Moderation(AuroraGuildModel): return cls.from_dict(bot=bot, data=case) @classmethod - def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: from ..utilities.database import connect logger.trace("Executing query: %s", query) logger.trace("With parameters: %s", parameters) @@ -214,16 +214,16 @@ class Moderation(AuroraGuildModel): parameters = () if not cursor: no_cursor = True - database = connect() - cursor = database.cursor() + database = await connect() + cursor = await database.cursor() else: no_cursor = False - cursor.execute(query, parameters) - results = cursor.fetchall() + await cursor.execute(query, parameters) + results = await cursor.fetchall() if no_cursor: - cursor.close() - database.close() + await cursor.close() + await database.close() if results: cases = [] @@ -235,7 +235,7 @@ class Moderation(AuroraGuildModel): return () @classmethod - def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, offset: int = 0, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, offset: int = 0, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: params = [] query = f"SELECT * FROM moderation_{guild_id} ORDER BY moderation_id DESC" if types: @@ -245,41 +245,41 @@ class Moderation(AuroraGuildModel): query += " LIMIT ? OFFSET ?" params.extend((limit, offset)) query += ";" - return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=tuple(params) if params else (), cursor=cursor) + return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=tuple(params) if params else (), cursor=cursor) @classmethod - def get_next_case_number(cls, bot: Red, guild_id: int, cursor: Cursor | None = None) -> int: - result = cls.get_latest(bot=bot, guild_id=guild_id, cursor=cursor, limit=1) + async def get_next_case_number(cls, bot: Red, guild_id: int, cursor: Cursor | None = None) -> int: + result = await cls.get_latest(bot=bot, guild_id=guild_id, cursor=cursor, limit=1) return (result[0].moderation_id + 1) if result else 1 @classmethod - def find_by_id(cls, bot: Red, moderation_id: int, guild_id: int, cursor: Cursor | None = None) -> "Moderation": + async def find_by_id(cls, bot: Red, moderation_id: int, guild_id: int, cursor: Cursor | None = None) -> "Moderation": query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;" - case = cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderation_id,), cursor=cursor) + case = await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderation_id,), cursor=cursor) if case: return case[0] raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") @classmethod - def find_by_target(cls, bot: Red, guild_id: int, target: int, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def find_by_target(cls, bot: Red, guild_id: int, target: int, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE target_id = ?" if types: query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" query += " ORDER BY moderation_id DESC;" - return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(target, *types) if types else (target,), cursor=cursor) + return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(target, *types) if types else (target,), cursor=cursor) @classmethod - def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE moderator_id = ?" if types: query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" query += " ORDER BY moderation_id DESC;" - return cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderator, *types) if types else (moderator,), cursor=cursor) + return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderator, *types) if types else (moderator,), cursor=cursor) @classmethod - def log( + async def log( cls, bot: Red, guild_id: int, @@ -335,13 +335,12 @@ class Moderation(AuroraGuildModel): role_id = None if not database: - database = connect() + database = await connect() close_db = True else: close_db = False - cursor = database.cursor() - moderation_id = cls.get_next_case_number(bot=bot, guild_id=guild_id, cursor=cursor) + moderation_id = cls.get_next_case_number(bot=bot, guild_id=guild_id) case = { "moderation_id": moderation_id, @@ -363,12 +362,12 @@ class Moderation(AuroraGuildModel): } sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - cursor.execute(sql, tuple(case.values())) + await database.execute(sql, tuple(case.values())) - cursor.close() - database.commit() + await database.close() + await database.commit() if close_db: - database.close() + await database.close() logger.debug( "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", @@ -392,5 +391,5 @@ class Moderation(AuroraGuildModel): ) if return_obj: - return cls.find_by_id(bot=bot, moderation_id=moderation_id, guild_id=guild_id) + return await cls.find_by_id(bot=bot, moderation_id=moderation_id, guild_id=guild_id) return moderation_id diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index 588ad35..3894bce 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -1,22 +1,22 @@ # pylint: disable=cyclic-import import json -import sqlite3 +import aiosqlite from discord import Guild from redbot.core import data_manager from .logger import logger -def connect() -> sqlite3.Connection: +async def connect() -> aiosqlite.Connection: """Connects to the SQLite database, and returns a connection object.""" try: - connection = sqlite3.connect( + connection = await aiosqlite.connect( database=data_manager.cog_data_path(raw_name="Aurora") / "aurora.db" ) return connection - except sqlite3.OperationalError as e: + except aiosqlite.OperationalError as e: logger.error("Unable to access the SQLite database!\nError:\n%s", e.msg) raise ConnectionRefusedError( f"Unable to access the SQLite Database!\n{e.msg}" @@ -24,14 +24,13 @@ def connect() -> sqlite3.Connection: async def create_guild_table(guild: Guild): - database = connect() - cursor = database.cursor() + database = await connect() try: - cursor.execute(f"SELECT * FROM `moderation_{guild.id}`") + await database.execute(f"SELECT * FROM `moderation_{guild.id}`") logger.debug("SQLite Table exists for server %s (%s)", guild.name, guild.id) - except sqlite3.OperationalError: + except aiosqlite.OperationalError: query = f""" CREATE TABLE `moderation_{guild.id}` ( moderation_id INTEGER PRIMARY KEY, @@ -52,16 +51,16 @@ async def create_guild_table(guild: Guild): metadata JSON NOT NULL ) """ - cursor.execute(query) + await database.execute(query) index_query_1 = f"CREATE INDEX IF NOT EXISTS idx_target_id ON moderation_{guild.id}(target_id);" - cursor.execute(index_query_1) + await database.execute(index_query_1) index_query_2 = f"CREATE INDEX IF NOT EXISTS idx_moderator_id ON moderation_{guild.id}(moderator_id);" - cursor.execute(index_query_2) + await database.execute(index_query_2) index_query_3 = f"CREATE INDEX IF NOT EXISTS idx_moderation_id ON moderation_{guild.id}(moderation_id);" - cursor.execute(index_query_3) + await database.execute(index_query_3) insert_query = f""" INSERT INTO `moderation_{guild.id}` @@ -86,9 +85,9 @@ async def create_guild_table(guild: Guild): json.dumps([]), json.dumps({}), ) - cursor.execute(insert_query, insert_values) + await database.execute(insert_query, insert_values) - database.commit() + await database.commit() logger.debug( "SQLite Table (moderation_%s) created for %s (%s)", diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index ea39d65..49346dc 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -120,7 +120,7 @@ async def log(interaction: Interaction, moderation_id: int, resolved: bool = Fal logging_channel = interaction.guild.get_channel(logging_channel_id) try: - moderation = Moderation.find_by_id(interaction.client, moderation_id, interaction.guild_id) + moderation = await Moderation.find_by_id(interaction.client, moderation_id, interaction.guild_id) embed = await log_factory( interaction=interaction, moderation=moderation, resolved=resolved ) @@ -145,7 +145,7 @@ async def send_evidenceformat(interaction: Interaction, moderation_id: int) -> N if send_evidence_bool is False: return - moderation = Moderation.find_by_id(interaction.client, moderation_id, interaction.guild.id) + moderation = await Moderation.find_by_id(interaction.client, moderation_id, interaction.guild.id) content = await evidenceformat_factory(moderation=moderation) await interaction.followup.send(content=content, ephemeral=True) diff --git a/poetry.lock b/poetry.lock index 96437ae..be5a40b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -123,6 +123,24 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "aiosqlite" +version = "0.20.0" +description = "asyncio bridge to the standard sqlite3 module" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aiosqlite-0.20.0-py3-none-any.whl", hash = "sha256:36a1deaca0cac40ebe32aac9977a6e2bbc7f5189f23f4a54d5908986729e5bd6"}, + {file = "aiosqlite-0.20.0.tar.gz", hash = "sha256:6d35c8c256637f4672f843c31021464090805bf925385ac39473fb16eaaca3d7"}, +] + +[package.dependencies] +typing_extensions = ">=4.0" + +[package.extras] +dev = ["attribution (==1.7.0)", "black (==24.2.0)", "coverage[toml] (==7.4.1)", "flake8 (==7.0.0)", "flake8-bugbear (==24.2.6)", "flit (==3.9.0)", "mypy (==1.8.0)", "ufmt (==2.3.0)", "usort (==1.0.8.post1)"] +docs = ["sphinx (==7.2.6)", "sphinx-mdinclude (==0.5.3)"] + [[package]] name = "annotated-types" version = "0.7.0" @@ -2655,4 +2673,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "3f732c0b0b0eb2a31fb9484c7cf699cd3c26474d6779528102af4c509a48351e" +content-hash = "22b824824f73dc3dc1a9a0a01060371ee1f6414e5bef39cb7455d21121988b47" diff --git a/pyproject.toml b/pyproject.toml index a2f2034..644cbdf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,6 +18,7 @@ pydantic = "^2.7.1" colorthief = "^0.2.1" beautifulsoup4 = "^4.12.3" markdownify = "^0.12.1" +aiosqlite = "^0.20.0" [tool.poetry.group.dev] optional = true -- 2.45.3 From eebddd6e89647ef05941fa9857c27bd6221d9f11 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 00:25:19 -0400 Subject: [PATCH 173/376] fix(aurora): override `aiosqlite`'s logging level to warning --- aurora/aurora.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/aurora/aurora.py b/aurora/aurora.py index 0b4463a..fed5034 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -6,6 +6,7 @@ # |_____/ \___|\__,_|___/ \_/\_/ |_|_| |_| |_|_| |_| |_|\___|_| import json +import logging as py_logging import os import time from datetime import datetime, timedelta, timezone @@ -81,6 +82,12 @@ class Aurora(commands.Cog): self.bot = bot register_config(config) self.handle_expiry.start() + # If we don't override aiosqlite's logging level, it will spam the console with dozens of debug messages per query. + # This is unnecessary because Aurora already logs all of its SQL queries (or at least, most of them), + # and the information that aiosqlite logs is not useful to the bot owner. + # This is a bad solution though as it overrides it for any other cogs that are using aiosqlite too. + # If there's a better solution that you're aware of, please let me know in Discord or in a CoastalCommits issue. + py_logging.getLogger('aiosqlite').setLevel(py_logging.WARNING) def format_help_for_context(self, ctx: commands.Context) -> str: pre_processed = super().format_help_for_context(ctx) or "" -- 2.45.3 From 56a2f96a2d6be218db8d04d99906cad2f322399e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 00:36:12 -0400 Subject: [PATCH 174/376] feat(aurora): made database.connect() into an async context manager --- aurora/aurora.py | 2 +- aurora/importers/aurora.py | 2 +- aurora/utilities/database.py | 11 +++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index fed5034..2332d4a 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -77,7 +77,7 @@ class Aurora(commands.Cog): "Invalid requester passed to red_delete_data_for_user: %s", requester ) - def __init__(self, bot: Red): + def __init__(self, bot: Red) -> None: super().__init__() self.bot = bot register_config(config) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index f154dab..b2367a6 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -27,7 +27,7 @@ class ImportAuroraView(ui.View): "Deleting original table...", ephemeral=True ) - async with connect() as database: + async with await connect() as database: query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};" database.execute(query) database.commit() diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index 3894bce..7d50d77 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -1,5 +1,7 @@ # pylint: disable=cyclic-import import json +from contextlib import asynccontextmanager +from typing import Any, AsyncGenerator import aiosqlite from discord import Guild @@ -8,13 +10,14 @@ from redbot.core import data_manager from .logger import logger -async def connect() -> aiosqlite.Connection: +@asynccontextmanager +async def connect() -> AsyncGenerator[aiosqlite.Connection, Any, None]: """Connects to the SQLite database, and returns a connection object.""" try: connection = await aiosqlite.connect( database=data_manager.cog_data_path(raw_name="Aurora") / "aurora.db" ) - return connection + yield connection except aiosqlite.OperationalError as e: logger.error("Unable to access the SQLite database!\nError:\n%s", e.msg) @@ -22,6 +25,10 @@ async def connect() -> aiosqlite.Connection: f"Unable to access the SQLite Database!\n{e.msg}" ) from e + finally: + if connection: + await connection.close() + async def create_guild_table(guild: Guild): database = await connect() -- 2.45.3 From 3383e84221fb8c462b6f2d090cbc0363c6251ebc Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 00:39:56 -0400 Subject: [PATCH 175/376] fix(aurora): fixed some issues with aiosqlite --- aurora/aurora.py | 14 ++++++------- aurora/importers/aurora.py | 9 +++++---- aurora/models/moderation.py | 38 +++++++++++++++++++----------------- aurora/utilities/database.py | 11 ++--------- 4 files changed, 34 insertions(+), 38 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 2332d4a..3cac57d 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -128,13 +128,13 @@ class Aurora(commands.Cog): async def addrole_on_member_join(self, member: discord.Member): """This method automatically adds roles to users when they join the server.""" if not await self.bot.cog_disabled_in_guild(self, member.guild): - async with connect() as database: - query = f"""SELECT moderation_id, role_id, reason FROM moderation_{member.guild.id} WHERE target_id = ? AND moderation_type = 'ADDROLE' AND expired = 0 AND resolved = 0;""" - async with database.execute(query, (member.id,)) as cursor: - async for row in cursor: - role = member.guild.get_role(row[1]) - reason = row[2] - await member.add_roles(role, reason=f"Role automatically added on member rejoin for: {reason} (Case #{row[0]:,})") + database = await connect() + query = f"""SELECT moderation_id, role_id, reason FROM moderation_{member.guild.id} WHERE target_id = ? AND moderation_type = 'ADDROLE' AND expired = 0 AND resolved = 0;""" + async with database.execute(query, (member.id,)) as cursor: + async for row in cursor: + role = member.guild.get_role(row[1]) + reason = row[2] + await member.add_roles(role, reason=f"Role automatically added on member rejoin for: {reason} (Case #{row[0]:,})") @commands.Cog.listener("on_audit_log_entry_create") async def autologger(self, entry: discord.AuditLogEntry): diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index b2367a6..686797f 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -27,10 +27,11 @@ class ImportAuroraView(ui.View): "Deleting original table...", ephemeral=True ) - async with await connect() as database: - query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};" - database.execute(query) - database.commit() + database = await connect() + query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};" + database.execute(query) + database.commit() + database.close() await interaction.edit_original_response(content="Creating new table...") diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 31912d1..412e195 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -122,24 +122,26 @@ class Moderation(AuroraGuildModel): from ..utilities.json import dumps query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" - async with connect() as database: - await database.execute(query, ( - self.timestamp.timestamp(), - self.moderation_type, - self.target_type, - self.moderator_id, - self.role_id, - str(self.duration) if self.duration else None, - self.end_timestamp.timestamp() if self.end_timestamp else None, - self.reason, - self.resolved, - self.resolved_by, - self.resolve_reason, - self.expired, - dumps(self.changes), - dumps(self.metadata), - self.moderation_id, - )) + database = await connect() + await database.execute(query, ( + self.timestamp.timestamp(), + self.moderation_type, + self.target_type, + self.moderator_id, + self.role_id, + str(self.duration) if self.duration else None, + self.end_timestamp.timestamp() if self.end_timestamp else None, + self.reason, + self.resolved, + self.resolved_by, + self.resolve_reason, + self.expired, + dumps(self.changes), + dumps(self.metadata), + self.moderation_id, + )) + await database.commit() + await database.close() logger.debug("Row updated in moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", self.moderation_id, diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index 7d50d77..3894bce 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -1,7 +1,5 @@ # pylint: disable=cyclic-import import json -from contextlib import asynccontextmanager -from typing import Any, AsyncGenerator import aiosqlite from discord import Guild @@ -10,14 +8,13 @@ from redbot.core import data_manager from .logger import logger -@asynccontextmanager -async def connect() -> AsyncGenerator[aiosqlite.Connection, Any, None]: +async def connect() -> aiosqlite.Connection: """Connects to the SQLite database, and returns a connection object.""" try: connection = await aiosqlite.connect( database=data_manager.cog_data_path(raw_name="Aurora") / "aurora.db" ) - yield connection + return connection except aiosqlite.OperationalError as e: logger.error("Unable to access the SQLite database!\nError:\n%s", e.msg) @@ -25,10 +22,6 @@ async def connect() -> AsyncGenerator[aiosqlite.Connection, Any, None]: f"Unable to access the SQLite Database!\n{e.msg}" ) from e - finally: - if connection: - await connection.close() - async def create_guild_table(guild: Guild): database = await connect() -- 2.45.3 From fe5823b637913c725acd27279d4ceccb41a07fcc Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 00:41:41 -0400 Subject: [PATCH 176/376] fix(aurora): awaited a coroutine --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 412e195..004959d 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -342,7 +342,7 @@ class Moderation(AuroraGuildModel): else: close_db = False - moderation_id = cls.get_next_case_number(bot=bot, guild_id=guild_id) + moderation_id = await cls.get_next_case_number(bot=bot, guild_id=guild_id) case = { "moderation_id": moderation_id, -- 2.45.3 From d1b5346396e2d09627b8f8b9c35bcdd1d302de50 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 00:51:13 -0400 Subject: [PATCH 177/376] fix(aurora): fixed failed_cases in the aurora importer --- aurora/importers/aurora.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 686797f..7810c4d 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -1,14 +1,16 @@ # pylint: disable=duplicate-code import json +import os from time import time from typing import Dict -from discord import ButtonStyle, Interaction, Message, ui -from redbot.core import commands -from redbot.core.utils.chat_formatting import box, warning +from discord import ButtonStyle, File, Interaction, Message, ui +from redbot.core import commands, data_manager +from redbot.core.utils.chat_formatting import warning from ..models.moderation import Moderation from ..utilities.database import connect, create_guild_table +from ..utilities.json import dump from ..utilities.utils import timedelta_from_string @@ -118,12 +120,26 @@ class ImportAuroraView(ui.View): await interaction.edit_original_response(content="Import complete.") if failed_cases: + filename = ( + str(data_manager.cog_data_path(cog_instance=self)) + + str(os.sep) + + f"failed_cases_{interaction.guild.id}.json" + ) + + with open(filename, "w", encoding="utf-8") as f: + dump(obj=failed_cases, fp=f, indent=2) + await interaction.edit_original_response( content="Import complete.\n" - + warning("Failed to import the following cases:\n") - + box(failed_cases) + + warning("Failed to import the following cases:\n"), + attachments=[File( + filename, f"failed_cases_{interaction.guild.id}.json" + ) + ] ) + os.remove(filename) + @ui.button(label="No", style=ButtonStyle.danger) async def import_button_n( self, interaction: Interaction, button: ui.Button -- 2.45.3 From 67e3abf5cec07f0cc415b06ebb58b820bfd0f18a Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 00:54:05 -0400 Subject: [PATCH 178/376] fix(aurora): use interaction.channel.send instead --- aurora/importers/aurora.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 7810c4d..468eb25 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -129,13 +129,12 @@ class ImportAuroraView(ui.View): with open(filename, "w", encoding="utf-8") as f: dump(obj=failed_cases, fp=f, indent=2) - await interaction.edit_original_response( + await interaction.channel.send( content="Import complete.\n" + warning("Failed to import the following cases:\n"), - attachments=[File( + file=File( filename, f"failed_cases_{interaction.guild.id}.json" ) - ] ) os.remove(filename) -- 2.45.3 From 3247e6fb8277299f321c8715998e494e878f12f8 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 00:59:33 -0400 Subject: [PATCH 179/376] fix(aurora): lmao i'm dumb --- aurora/importers/aurora.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 468eb25..b7edc71 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -33,7 +33,6 @@ class ImportAuroraView(ui.View): query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};" database.execute(query) database.commit() - database.close() await interaction.edit_original_response(content="Creating new table...") @@ -118,6 +117,9 @@ class ImportAuroraView(ui.View): except Exception as e: # pylint: disable=broad-exception-caught failed_cases.append(str(case["moderation_id"]) + f": {e}") + await database.commit() + await database.close() + await interaction.edit_original_response(content="Import complete.") if failed_cases: filename = ( -- 2.45.3 From ca4510d3a594d7964c683f731db5cb4aa219efa9 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:01:17 -0400 Subject: [PATCH 180/376] =?UTF-8?q?fix(aurora):=20why=20was=20I=20CLOSING?= =?UTF-8?q?=20THE=20CONNECTION=20THERE=20=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aurora/models/moderation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 004959d..73c4647 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -366,7 +366,6 @@ class Moderation(AuroraGuildModel): sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" await database.execute(sql, tuple(case.values())) - await database.close() await database.commit() if close_db: await database.close() -- 2.45.3 From d629f1a5a27377a7d79dd8c56c8685be3afdbf1e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:02:09 -0400 Subject: [PATCH 181/376] fix(aurora): awaited two coroutines --- aurora/importers/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index b7edc71..9bc98ae 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -31,8 +31,8 @@ class ImportAuroraView(ui.View): database = await connect() query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};" - database.execute(query) - database.commit() + await database.execute(query) + await database.commit() await interaction.edit_original_response(content="Creating new table...") -- 2.45.3 From 76572e2281d90b015a8e3d665ab116457b19b6c8 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:05:11 -0400 Subject: [PATCH 182/376] fix(aurora): awaited a coroutine --- aurora/utilities/database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index 3894bce..1cb40e5 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -96,4 +96,4 @@ async def create_guild_table(guild: Guild): guild.id, ) - database.close() + await database.close() -- 2.45.3 From df465e5ba67029c73e9202531a2a1cac217fd5c9 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:11:18 -0400 Subject: [PATCH 183/376] fix(aurora): awaited another coroutine --- aurora/utilities/factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 491f8c3..b6fadb7 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -91,7 +91,7 @@ async def message_factory( embed.set_author(name=guild.name) embed.set_footer( - text=f"Case #{Moderation.get_next_case_number(bot=bot, guild_id=guild.id):,}", + text=f"Case #{await Moderation.get_next_case_number(bot=bot, guild_id=guild.id):,}", icon_url="attachment://arrow.png", ) -- 2.45.3 From d07e5ed804270c5d343a4d7e084e2d915643ac26 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:12:49 -0400 Subject: [PATCH 184/376] misc(aurora): changing around some logging levels --- aurora/models/moderation.py | 2 +- aurora/utilities/database.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 73c4647..2972747 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -370,7 +370,7 @@ class Moderation(AuroraGuildModel): if close_db: await database.close() - logger.debug( + logger.verbose( "Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", guild_id, case["moderation_id"], diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index 1cb40e5..a1d1808 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -28,7 +28,7 @@ async def create_guild_table(guild: Guild): try: await database.execute(f"SELECT * FROM `moderation_{guild.id}`") - logger.debug("SQLite Table exists for server %s (%s)", guild.name, guild.id) + logger.verbose("SQLite Table exists for server %s (%s)", guild.name, guild.id) except aiosqlite.OperationalError: query = f""" -- 2.45.3 From 42f7f9f69b07a3486523f972ea22f41017bcaa45 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:29:47 -0400 Subject: [PATCH 185/376] feat(aurora): migrated `Aurora.handle_expiry()` to use `Moderation.execute()` instead of opening its own connections --- aurora/aurora.py | 81 ++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 48 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 3cac57d..6cbfff5 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1490,8 +1490,6 @@ class Aurora(commands.Cog): async def handle_expiry(self): await self.bot.wait_until_red_ready() current_time = time.time() - database = await connect() - cursor = await database.cursor() global_unban_num = 0 global_addrole_num = 0 global_removerole_num = 0 @@ -1501,20 +1499,21 @@ class Aurora(commands.Cog): if not await self.bot.cog_disabled_in_guild(self, guild): time_per_guild = time.time() - tempban_query = f"SELECT target_id, moderation_id FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'TEMPBAN' AND expired = 0" + tempban_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'TEMPBAN' AND expired = 0" try: - await cursor.execute(tempban_query, (time.time(),)) - result = cursor.fetchall() + tempbans = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=tempban_query, parameters=(time.time(),)) except aiosqlite.OperationalError: continue - target_ids = [row[0] for row in result] - moderation_ids = [row[1] for row in result] - unban_num = 0 - for target_id, moderation_id in zip(target_ids, moderation_ids): - user: discord.User = await self.bot.fetch_user(target_id) + for moderation in tempbans: + user = self.bot.get_user(moderation.target_id) + if user is None: + try: + user = self.bot.fetch_user(moderation.target_id) + except discord.errors.NotFound: + continue name = ( f"{user.name}#{user.discriminator}" if user.discriminator != "0" @@ -1522,14 +1521,14 @@ class Aurora(commands.Cog): ) try: await guild.unban( - user, reason=f"Automatic unban from case #{moderation_id}" + user, reason=f"Automatic unban from case #{moderation.id}" ) embed = await message_factory( bot=self.bot, color=await self.bot.get_embed_color(guild.channels[0]), guild=guild, - reason=f"Automatic unban from case #{moderation_id}", + reason=f"Automatic unban from case #{moderation.id}", moderation_type="unbanned", ) @@ -1538,14 +1537,14 @@ class Aurora(commands.Cog): except discord.errors.HTTPException: pass - logger.debug( + logger.trace( "Unbanned %s (%s) from %s (%s)", name, user.id, guild.name, guild.id, ) - unban_num = unban_num + 1 + unban_num += 1 except ( discord.errors.NotFound, discord.errors.Forbidden, @@ -1561,26 +1560,23 @@ class Aurora(commands.Cog): ) removerole_num = 0 - addrole_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL AND end_timestamp <= ? AND moderation_type = 'ADDROLE' AND expired = 0" - try: - await cursor.execute(addrole_query, (time.time(),)) - result = await cursor.fetchall() - except aiosqlite.OperationalError: - continue - target_ids = [row[0] for row in result] - moderation_ids = [row[1] for row in result] - role_ids = [row[2] for row in result] + addrole_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL AND end_timestamp <= ? AND moderation_type = 'ADDROLE' AND expired = 0" + addroles = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=addrole_query, parameters=(time.time(),)) - for target_id, moderation_id, role_id in zip( - target_ids, moderation_ids, role_ids - ): + for moderation in addroles: try: - member = await guild.fetch_member(target_id) + member = await guild.fetch_member(moderation.target_id) await member.remove_roles( - Object(role_id), reason=f"Automatic role removal from case #{moderation_id}" + Object(moderation.role_id), reason=f"Automatic role removal from case #{moderation.id}" ) + logger.trace( + "Removed role %s from %s (%s)", + moderation.role_id, + member.name, + member.id, + ) removerole_num = removerole_num + 1 except ( discord.errors.NotFound, @@ -1589,44 +1585,36 @@ class Aurora(commands.Cog): ) as e: logger.error( "Removing the role %s from user %s failed due to: \n%s", - role_id, - target_id, + moderation.role_id, + moderation.target_id, e, ) continue addrole_num = 0 removerole_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'REMOVEROLE' AND expired = 0" - try: - await cursor.execute(removerole_query, (time.time(),)) - result = await cursor.fetchall() - except aiosqlite.OperationalError: - continue - target_ids = [row[0] for row in result] - moderation_ids = [row[1] for row in result] - role_ids = [row[2] for row in result] + removeroles = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=removerole_query, parameters=(time.time(),)) - for target_id, moderation_id, role_id in zip( - target_ids, moderation_ids, role_ids - ): + for moderation in removeroles: try: - member = await guild.fetch_member(target_id) + member = await guild.fetch_member(moderation.target_id) await member.add_roles( - Object(role_id), reason=f"Automatic role addition from case #{moderation_id}" + Object(moderation.role_id), reason=f"Automatic role addition from case #{moderation.id}" ) + logger.trace("Added role %s to %s (%s)", moderation.role_id, member.name, member.id) addrole_num = addrole_num + 1 except ( discord.errors.NotFound, discord.errors.Forbidden, discord.errors.HTTPException, ) as e: - logger.error("Adding the role %s to user %s failed due to: \n%s", role_id, target_id, e) + logger.error("Adding the role %s to user %s failed due to: \n%s", moderation.role_id, moderation.target_id, e) continue expiry_query = f"UPDATE `moderation_{guild.id}` SET expired = 1 WHERE (end_timestamp IS NOT NULL AND end_timestamp <= ? AND expired = 0) OR (expired = 0 AND resolved = 1);" - await cursor.execute(expiry_query, (time.time(),)) + await Moderation.execute(bot=self.bot, guild_id=guild.id, query=expiry_query, parameters=(time.time(),)) per_guild_completion_time = (time.time() - time_per_guild) * 1000 logger.debug( @@ -1642,9 +1630,6 @@ class Aurora(commands.Cog): global_addrole_num = global_addrole_num + addrole_num global_removerole_num = global_removerole_num + removerole_num - await database.commit() - await cursor.close() - await database.close() completion_time = (time.time() - current_time) * 1000 logger.debug( -- 2.45.3 From e9889173199efa2548bffabeb6db17feb9996e73 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:31:40 -0400 Subject: [PATCH 186/376] feat(aurora): added a return_obj parameter to `Moderation.execute()` --- aurora/aurora.py | 2 +- aurora/models/moderation.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 6cbfff5..3d7f683 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1614,7 +1614,7 @@ class Aurora(commands.Cog): continue expiry_query = f"UPDATE `moderation_{guild.id}` SET expired = 1 WHERE (end_timestamp IS NOT NULL AND end_timestamp <= ? AND expired = 0) OR (expired = 0 AND resolved = 1);" - await Moderation.execute(bot=self.bot, guild_id=guild.id, query=expiry_query, parameters=(time.time(),)) + await Moderation.execute(bot=self.bot, guild_id=guild.id, query=expiry_query, parameters=(time.time(),), return_obj=False) per_guild_completion_time = (time.time() - time_per_guild) * 1000 logger.debug( diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 2972747..8887dd5 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -208,7 +208,7 @@ class Moderation(AuroraGuildModel): return cls.from_dict(bot=bot, data=case) @classmethod - async def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None, cursor: Cursor | None = None, return_obj: bool = True) -> Tuple["Moderation"]: from ..utilities.database import connect logger.trace("Executing query: %s", query) logger.trace("With parameters: %s", parameters) @@ -227,7 +227,7 @@ class Moderation(AuroraGuildModel): await cursor.close() await database.close() - if results: + if results and return_obj: cases = [] for result in results: case = cls.from_result(bot=bot, result=result, guild_id=guild_id) -- 2.45.3 From afac2749785e2b59cb007a6be0f3bb0e7fbb48ea Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:36:45 -0400 Subject: [PATCH 187/376] fix(aurora): removed a useless try/except block --- aurora/aurora.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 3d7f683..f8f8605 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -12,7 +12,6 @@ import time from datetime import datetime, timedelta, timezone from math import ceil -import aiosqlite import discord from discord import Object from discord.ext import tasks @@ -1500,11 +1499,7 @@ class Aurora(commands.Cog): time_per_guild = time.time() tempban_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'TEMPBAN' AND expired = 0" - - try: - tempbans = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=tempban_query, parameters=(time.time(),)) - except aiosqlite.OperationalError: - continue + tempbans = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=tempban_query, parameters=(time.time(),)) unban_num = 0 for moderation in tempbans: @@ -1592,7 +1587,7 @@ class Aurora(commands.Cog): continue addrole_num = 0 - removerole_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'REMOVEROLE' AND expired = 0" + removerole_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'REMOVEROLE' AND expired = 0" removeroles = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=removerole_query, parameters=(time.time(),)) for moderation in removeroles: -- 2.45.3 From e9a64e5a39acbf4d5d3fc9512dca35209bb4b394 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:37:41 -0400 Subject: [PATCH 188/376] fix(aurora): fixed an sql syntax error --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index f8f8605..d2db152 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1498,7 +1498,7 @@ class Aurora(commands.Cog): if not await self.bot.cog_disabled_in_guild(self, guild): time_per_guild = time.time() - tempban_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'TEMPBAN' AND expired = 0" + tempban_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL AND end_timestamp <= ? AND moderation_type = 'TEMPBAN' AND expired = 0" tempbans = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=tempban_query, parameters=(time.time(),)) unban_num = 0 -- 2.45.3 From 9622e037c9ff1bf77f1b7dfc3c3b4eb4078da0ce Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:38:27 -0400 Subject: [PATCH 189/376] fix(aurora): fixed another sql syntax error --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index d2db152..df25b1f 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1587,7 +1587,7 @@ class Aurora(commands.Cog): continue addrole_num = 0 - removerole_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL 0 AND end_timestamp <= ? AND moderation_type = 'REMOVEROLE' AND expired = 0" + removerole_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL AND end_timestamp <= ? AND moderation_type = 'REMOVEROLE' AND expired = 0" removeroles = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=removerole_query, parameters=(time.time(),)) for moderation in removeroles: -- 2.45.3 From 5cb61ecd65734e3083a2f25e51d9abadfcb77e6e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 01:39:34 -0400 Subject: [PATCH 190/376] fix(aurora): awaited a coroutine --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index df25b1f..521cf5b 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1506,7 +1506,7 @@ class Aurora(commands.Cog): user = self.bot.get_user(moderation.target_id) if user is None: try: - user = self.bot.fetch_user(moderation.target_id) + user = await self.bot.fetch_user(moderation.target_id) except discord.errors.NotFound: continue name = ( -- 2.45.3 From f6a42b97d9a79940f1e0c992a192fcb8c3968d3a Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 5 Jun 2024 23:13:23 -0400 Subject: [PATCH 191/376] misc(aurora): various model changes --- aurora/models/base.py | 11 +++++++---- aurora/models/moderation.py | 20 ++++++++++++-------- aurora/models/partials.py | 21 +++++++++------------ 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/aurora/models/base.py b/aurora/models/base.py index e6005ee..7cf8ab1 100644 --- a/aurora/models/base.py +++ b/aurora/models/base.py @@ -1,5 +1,6 @@ -from typing import Any +from typing import Any, Optional +from discord import Guild from pydantic import BaseModel, ConfigDict from redbot.core.bot import Red @@ -17,12 +18,14 @@ class AuroraBaseModel(BaseModel): return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) class AuroraGuildModel(AuroraBaseModel): - """Subclass of AuroraBaseModel that includes a guild_id attribute, and a modified to_json() method to match.""" + """Subclass of AuroraBaseModel that includes a guild_id attribute and a guild attribute, and a modified to_json() method to match.""" + model_config = ConfigDict(ignored_types=(Red, Guild), arbitrary_types_allowed=True) guild_id: int + guild: Optional[Guild] = None def dump(self) -> dict: - return self.model_dump(exclude={"bot", "guild_id"}) + return self.model_dump(exclude={"bot", "guild_id", "guild"}) def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs): from ..utilities.json import dump, dumps # pylint: disable=cyclic-import - return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot", "guild_id"}), indent=indent, **kwargs) + return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.dump(), indent=indent, **kwargs) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 8887dd5..9cc534c 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -52,7 +52,7 @@ class Moderation(AuroraGuildModel): async def get_target(self) -> Union["PartialUser", "PartialChannel"]: if self.target_type == "USER": return await PartialUser.from_id(self.bot, self.target_id) - return await PartialChannel.from_id(self.bot, self.target_id) + return await PartialChannel.from_id(self.bot, self.target_id, self.guild) async def get_resolved_by(self) -> Optional["PartialUser"]: if self.resolved_by: @@ -61,7 +61,7 @@ class Moderation(AuroraGuildModel): async def get_role(self) -> Optional["PartialRole"]: if self.role_id: - return await PartialRole.from_id(self.bot, self.guild_id, self.role_id) + return await PartialRole.from_id(self.bot, self.guild, self.role_id) return None def __str__(self) -> str: @@ -118,12 +118,10 @@ class Moderation(AuroraGuildModel): await self.update() async def update(self) -> None: - from ..utilities.database import connect from ..utilities.json import dumps query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;" - database = await connect() - await database.execute(query, ( + await self.execute(query, ( self.timestamp.timestamp(), self.moderation_type, self.target_type, @@ -140,10 +138,8 @@ class Moderation(AuroraGuildModel): dumps(self.metadata), self.moderation_id, )) - await database.commit() - await database.close() - logger.debug("Row updated in moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", + logger.verbose("Row updated in moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s", self.moderation_id, self.guild_id, self.timestamp.timestamp(), @@ -164,6 +160,14 @@ class Moderation(AuroraGuildModel): @classmethod def from_dict(cls, bot: Red, data: dict) -> "Moderation": + if data.get("guild_id"): + try: + guild: discord.Guild = bot.get_guild(data["guild_id"]) + if not guild: + guild = bot.fetch_guild(data["guild_id"]) + except (discord.Forbidden, discord.HTTPException): + guild = None + data.update({"guild": guild}) return cls(bot=bot, **data) @classmethod diff --git a/aurora/models/partials.py b/aurora/models/partials.py index 48f4030..68b0261 100644 --- a/aurora/models/partials.py +++ b/aurora/models/partials.py @@ -1,4 +1,4 @@ -from discord import Forbidden, HTTPException, InvalidData, NotFound +from discord import ChannelType, Forbidden, Guild, HTTPException, InvalidData, NotFound from redbot.core.bot import Red from .base import AuroraBaseModel, AuroraGuildModel @@ -31,6 +31,7 @@ class PartialUser(AuroraBaseModel): class PartialChannel(AuroraGuildModel): id: int name: str + type: ChannelType @property def mention(self): @@ -42,17 +43,17 @@ class PartialChannel(AuroraGuildModel): return self.mention @classmethod - async def from_id(cls, bot: Red, channel_id: int) -> "PartialChannel": + async def from_id(cls, bot: Red, channel_id: int, guild: Guild) -> "PartialChannel": channel = bot.get_channel(channel_id) if not channel: try: channel = await bot.fetch_channel(channel_id) - return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, name=channel.name) + return cls(bot=bot, guild_id=channel.guild.id, guild=guild, id=channel.id, name=channel.name, type=channel.type) except (NotFound, InvalidData, HTTPException, Forbidden) as e: if e == Forbidden: return cls(bot=bot, guild_id=0, id=channel_id, name="Forbidden Channel") - return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel") - return cls(bot=bot, guild_id=channel.guild.id, id=channel.id, name=channel.name) + return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel", type=ChannelType.text) + return cls(bot=bot, guild_id=channel.guild.id, guild=guild, id=channel.id, name=channel.name, type=channel.type) class PartialRole(AuroraGuildModel): id: int @@ -68,12 +69,8 @@ class PartialRole(AuroraGuildModel): return self.mention @classmethod - async def from_id(cls, bot: Red, guild_id: int, role_id: int) -> "PartialRole": - try: - guild = await bot.fetch_guild(guild_id, with_counts=False) - except (Forbidden, HTTPException): - return cls(bot=bot, guild_id=guild_id, id=role_id, name="Forbidden Role") + async def from_id(cls, bot: Red, guild: Guild, role_id: int) -> "PartialRole": role = guild.get_role(role_id) if not role: - return cls(bot=bot, guild_id=guild_id, id=role_id, name="Deleted Role") - return cls(bot=bot, guild_id=guild_id, id=role.id, name=role.name) + return cls(bot=bot, guild_id=guild.id, id=role_id, name="Deleted Role") + return cls(bot=bot, guild_id=guild.id, id=role.id, name=role.name) -- 2.45.3 From 0bcbcd6c0cd45cf40fd1027b643b11612f7d0fb1 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 8 Jun 2024 20:12:22 -0400 Subject: [PATCH 192/376] feat(aurora): bunch of changes --- aurora/aurora.py | 52 ++++++++--------- aurora/importers/aurora.py | 11 +--- aurora/importers/galacticbot.py | 5 +- aurora/models/moderation.py | 35 ++++++++---- aurora/utilities/database.py | 99 --------------------------------- aurora/utilities/utils.py | 69 +++++++++++++++++++++++ 6 files changed, 122 insertions(+), 149 deletions(-) delete mode 100644 aurora/utilities/database.py diff --git a/aurora/aurora.py b/aurora/aurora.py index 521cf5b..85d81d6 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -19,7 +19,7 @@ from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.commands.converter import parse_relativedelta, parse_timedelta -from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import bold, box, error, humanize_list, humanize_timedelta, warning from .importers.aurora import ImportAuroraView from .importers.galacticbot import ImportGalacticBotView @@ -30,11 +30,10 @@ from .menus.overrides import Overrides from .models.change import Change from .models.moderation import Moderation from .utilities.config import config, register_config -from .utilities.database import connect, create_guild_table from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from .utilities.json import dump from .utilities.logger import logger -from .utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from .utilities.utils import check_moddable, check_permissions, create_guild_table, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta class Aurora(commands.Cog): @@ -43,28 +42,22 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["SeaswimmerTheFsh"] - __version__ = "2.2.0" + __version__ = "2.3.0" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): if requester == "discord_deleted_user": await config.user_from_id(user_id).clear() - database = await connect() - cursor = await database.cursor() - - await cursor.execute("SHOW TABLES;") - tables = [table[0] for table in cursor.fetchall()] + results = await Moderation.execute(query="SHOW TABLES;", return_obj=False) + tables = [table[0] for table in results] condition = "target_id = %s OR moderator_id = %s;" for table in tables: delete_query = f"DELETE FROM {table[0]} WHERE {condition}" - await cursor.execute(delete_query, (user_id, user_id)) + await Moderation.execute(query=delete_query, parameters=(user_id, user_id), return_obj=False) - await database.commit() - await cursor.close() - await database.close() if requester == "owner": await config.user_from_id(user_id).clear() if requester == "user": @@ -86,16 +79,16 @@ class Aurora(commands.Cog): # and the information that aiosqlite logs is not useful to the bot owner. # This is a bad solution though as it overrides it for any other cogs that are using aiosqlite too. # If there's a better solution that you're aware of, please let me know in Discord or in a CoastalCommits issue. - py_logging.getLogger('aiosqlite').setLevel(py_logging.WARNING) + py_logging.getLogger('aiosqlite').setLevel(py_logging.INFO) def format_help_for_context(self, ctx: commands.Context) -> str: pre_processed = super().format_help_for_context(ctx) or "" n = "\n" if "\n\n" not in pre_processed else "" text = [ f"{pre_processed}{n}", - f"Cog Version: **{self.__version__}**", - f"Author: {humanize_list(self.__author__)}", - f"Documentation: {self.__documentation__}", + f"{bold('Cog Version:')} {self.__version__}", + f"{bold('Author:')} {humanize_list(self.__author__)}", + f"{bold('Documentation:')} {self.__documentation__}", ] return "\n".join(text) @@ -127,13 +120,12 @@ class Aurora(commands.Cog): async def addrole_on_member_join(self, member: discord.Member): """This method automatically adds roles to users when they join the server.""" if not await self.bot.cog_disabled_in_guild(self, member.guild): - database = await connect() query = f"""SELECT moderation_id, role_id, reason FROM moderation_{member.guild.id} WHERE target_id = ? AND moderation_type = 'ADDROLE' AND expired = 0 AND resolved = 0;""" - async with database.execute(query, (member.id,)) as cursor: - async for row in cursor: - role = member.guild.get_role(row[1]) - reason = row[2] - await member.add_roles(role, reason=f"Role automatically added on member rejoin for: {reason} (Case #{row[0]:,})") + results = Moderation.execute(query, (member.id,)) + for row in results: + role = member.guild.get_role(row[1]) + reason = row[2] + await member.add_roles(role, reason=f"Role automatically added on member rejoin for: {reason} (Case #{row[0]:,})") @commands.Cog.listener("on_audit_log_entry_create") async def autologger(self, entry: discord.AuditLogEntry): @@ -1093,7 +1085,7 @@ class Aurora(commands.Cog): ) return - database = await connect() + database = await Moderation.connect() if export: try: @@ -1268,7 +1260,7 @@ class Aurora(commands.Cog): ephemeral: bool | None = None, evidenceformat: bool = False, changes: bool = False, - export: Choice[str] | None = None, + raw: Choice[str] | None = None, ): """Check the details of a specific case. @@ -1278,9 +1270,11 @@ class Aurora(commands.Cog): What case are you looking up? ephemeral: bool Hide the command response + evidenceformat: bool + Display the evidence format of the case changes: bool List the changes made to the case - export: bool + raw: bool Export the case to a JSON file or codeblock""" permissions = check_permissions( interaction.client.user, ["embed_links"], interaction @@ -1309,8 +1303,8 @@ class Aurora(commands.Cog): ) return - if export: - if export.value == "file" or len(mod.to_json(2)) > 1800: + if raw: + if raw.value == "file" or len(mod.to_json(2)) > 1800: filename = ( str(data_manager.cog_data_path(cog_instance=self)) + str(os.sep) @@ -1319,7 +1313,7 @@ class Aurora(commands.Cog): with open(filename, "w", encoding="utf-8") as f: mod.to_json(2, f) - if export.value == "codeblock": + if raw.value == "codeblock": content = f"Case #{case:,} exported.\n" + warning( "Case was too large to export as codeblock, so it has been uploaded as a `.json` file." ) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 9bc98ae..2500993 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -9,9 +9,8 @@ from redbot.core import commands, data_manager from redbot.core.utils.chat_formatting import warning from ..models.moderation import Moderation -from ..utilities.database import connect, create_guild_table from ..utilities.json import dump -from ..utilities.utils import timedelta_from_string +from ..utilities.utils import create_guild_table, timedelta_from_string class ImportAuroraView(ui.View): @@ -29,10 +28,8 @@ class ImportAuroraView(ui.View): "Deleting original table...", ephemeral=True ) - database = await connect() query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};" - await database.execute(query) - await database.commit() + await Moderation.execute(query=query, return_obj=False) await interaction.edit_original_response(content="Creating new table...") @@ -111,15 +108,11 @@ class ImportAuroraView(ui.View): expired=case["expired"], changes=changes, metadata=metadata, - database=database, return_obj=False ) except Exception as e: # pylint: disable=broad-exception-caught failed_cases.append(str(case["moderation_id"]) + f": {e}") - await database.commit() - await database.close() - await interaction.edit_original_response(content="Import complete.") if failed_cases: filename = ( diff --git a/aurora/importers/galacticbot.py b/aurora/importers/galacticbot.py index 453cac0..2fbc62d 100644 --- a/aurora/importers/galacticbot.py +++ b/aurora/importers/galacticbot.py @@ -8,13 +8,14 @@ from redbot.core import commands from redbot.core.utils.chat_formatting import box, warning from ..models.moderation import Change, Moderation -from ..utilities.database import connect, create_guild_table +from ..utilities.database import create_guild_table class ImportGalacticBotView(ui.View): def __init__(self, timeout, ctx, message): super().__init__() self.ctx: commands.Context = ctx + self.timeout = timeout self.message: Message = message @ui.button(label="Yes", style=ButtonStyle.success) @@ -26,7 +27,7 @@ class ImportGalacticBotView(ui.View): "Deleting original table...", ephemeral=True ) - database = await connect() + database = await Moderation.connect() cursor = await database.cursor() query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};" diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 9cc534c..afd9c8e 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -5,8 +5,10 @@ from time import time from typing import Dict, Iterable, List, Optional, Tuple, Union import discord -from aiosqlite import Cursor +from aiosqlite import Connection, Cursor, OperationalError, Row +from aiosqlite import connect as aiosqlite_connect from discord import NotFound +from redbot.core import data_manager from redbot.core.bot import Red from ..utilities.logger import logger @@ -211,34 +213,48 @@ class Moderation(AuroraGuildModel): } return cls.from_dict(bot=bot, data=case) + @staticmethod + async def connect() -> Connection: + """Connects to the SQLite database, and returns a connection object.""" + try: + connection = await aiosqlite_connect( + database=data_manager.cog_data_path(raw_name="Aurora") / "aurora.db" + ) + return connection + + except OperationalError as e: + logger.error("Unable to access the SQLite database!\nError:\n%s", e.msg) + raise ConnectionRefusedError( + f"Unable to access the SQLite Database!\n{e.msg}" + ) from e + @classmethod - async def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None, cursor: Cursor | None = None, return_obj: bool = True) -> Tuple["Moderation"]: - from ..utilities.database import connect - logger.trace("Executing query: %s", query) - logger.trace("With parameters: %s", parameters) + async def execute(cls, query: str, parameters: tuple | None = None, bot: Red | None = None, guild_id: int | None = None, cursor: Cursor | None = None, return_obj: bool = True) -> Union[Tuple["Moderation"], Iterable[Row]]: + logger.trace("Executing query: \"%s\" with parameters \"%s\"", query, parameters) if not parameters: parameters = () if not cursor: no_cursor = True - database = await connect() + database = await cls.connect() cursor = await database.cursor() else: no_cursor = False await cursor.execute(query, parameters) results = await cursor.fetchall() + await database.commit() if no_cursor: await cursor.close() await database.close() - if results and return_obj: + if results and return_obj and bot and guild_id: cases = [] for result in results: case = cls.from_result(bot=bot, result=result, guild_id=guild_id) if case.moderation_id != 0: cases.append(case) return tuple(cases) - return () + return results @classmethod async def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, offset: int = 0, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: @@ -306,7 +322,6 @@ class Moderation(AuroraGuildModel): metadata: dict | None = None, return_obj: bool = True, ) -> Union["Moderation", int]: - from ..utilities.database import connect from ..utilities.json import dumps if not timestamp: timestamp = datetime.fromtimestamp(time()) @@ -341,7 +356,7 @@ class Moderation(AuroraGuildModel): role_id = None if not database: - database = await connect() + database = await cls.connect() close_db = True else: close_db = False diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py deleted file mode 100644 index a1d1808..0000000 --- a/aurora/utilities/database.py +++ /dev/null @@ -1,99 +0,0 @@ -# pylint: disable=cyclic-import -import json - -import aiosqlite -from discord import Guild -from redbot.core import data_manager - -from .logger import logger - - -async def connect() -> aiosqlite.Connection: - """Connects to the SQLite database, and returns a connection object.""" - try: - connection = await aiosqlite.connect( - database=data_manager.cog_data_path(raw_name="Aurora") / "aurora.db" - ) - return connection - - except aiosqlite.OperationalError as e: - logger.error("Unable to access the SQLite database!\nError:\n%s", e.msg) - raise ConnectionRefusedError( - f"Unable to access the SQLite Database!\n{e.msg}" - ) from e - - -async def create_guild_table(guild: Guild): - database = await connect() - - try: - await database.execute(f"SELECT * FROM `moderation_{guild.id}`") - logger.verbose("SQLite Table exists for server %s (%s)", guild.name, guild.id) - - except aiosqlite.OperationalError: - query = f""" - CREATE TABLE `moderation_{guild.id}` ( - moderation_id INTEGER PRIMARY KEY, - timestamp INTEGER NOT NULL, - moderation_type TEXT NOT NULL, - target_type TEXT NOT NULL, - target_id INTEGER NOT NULL, - moderator_id INTEGER NOT NULL, - role_id INTEGER, - duration TEXT, - end_timestamp INTEGER, - reason TEXT, - resolved INTEGER NOT NULL, - resolved_by TEXT, - resolve_reason TEXT, - expired INTEGER NOT NULL, - changes JSON NOT NULL, - metadata JSON NOT NULL - ) - """ - await database.execute(query) - - index_query_1 = f"CREATE INDEX IF NOT EXISTS idx_target_id ON moderation_{guild.id}(target_id);" - await database.execute(index_query_1) - - index_query_2 = f"CREATE INDEX IF NOT EXISTS idx_moderator_id ON moderation_{guild.id}(moderator_id);" - await database.execute(index_query_2) - - index_query_3 = f"CREATE INDEX IF NOT EXISTS idx_moderation_id ON moderation_{guild.id}(moderation_id);" - await database.execute(index_query_3) - - insert_query = f""" - INSERT INTO `moderation_{guild.id}` - (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """ - insert_values = ( - 0, - 0, - "NULL", - "NULL", - 0, - 0, - None, - None, - None, - None, - 0, - None, - None, - 0, - json.dumps([]), - json.dumps({}), - ) - await database.execute(insert_query, insert_values) - - await database.commit() - - logger.debug( - "SQLite Table (moderation_%s) created for %s (%s)", - guild.id, - guild.name, - guild.id, - ) - - await database.close() diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 49346dc..c898e60 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -2,6 +2,7 @@ from datetime import datetime, timedelta from typing import Optional, Tuple, Union +import aiosqlite from dateutil.relativedelta import relativedelta as rd from discord import File, Guild, Interaction, Member, SelectOption, TextChannel, User from discord.errors import Forbidden @@ -9,6 +10,8 @@ from redbot.core import commands, data_manager from redbot.core.utils.chat_formatting import error from ..utilities.config import config +from ..utilities.json import dumps +from ..utilities.logger import logger def check_permissions( @@ -210,3 +213,69 @@ def get_footer_image(coginstance: commands.Cog) -> File: """Returns the footer image for the embeds.""" image_path = data_manager.bundled_data_path(coginstance) / "arrow.png" return File(image_path, filename="arrow.png", description="arrow") + +async def create_guild_table(guild: Guild) -> None: + from ..models.moderation import Moderation + + try: + await Moderation.execute(f"SELECT * FROM `moderation_{guild.id}`", return_obj=False) + logger.trace("SQLite Table exists for server %s (%s)", guild.name, guild.id) + + except aiosqlite.OperationalError: + query = f""" + CREATE TABLE `moderation_{guild.id}` ( + moderation_id INTEGER PRIMARY KEY, + timestamp INTEGER NOT NULL, + moderation_type TEXT NOT NULL, + target_type TEXT NOT NULL, + target_id INTEGER NOT NULL, + moderator_id INTEGER NOT NULL, + role_id INTEGER, + duration TEXT, + end_timestamp INTEGER, + reason TEXT, + resolved INTEGER NOT NULL, + resolved_by TEXT, + resolve_reason TEXT, + expired INTEGER NOT NULL, + changes JSON NOT NULL, + metadata JSON NOT NULL + ) + """ + await Moderation.execute(query=query, return_obj=False) + + index_query_1 = f"CREATE INDEX IF NOT EXISTS idx_target_id ON moderation_{guild.id}(target_id);" + await Moderation.execute(query=index_query_1, return_obj=False) + + index_query_2 = f"CREATE INDEX IF NOT EXISTS idx_moderator_id ON moderation_{guild.id}(moderator_id);" + await Moderation.execute(query=index_query_2, return_obj=False) + + index_query_3 = f"CREATE INDEX IF NOT EXISTS idx_moderation_id ON moderation_{guild.id}(moderation_id);" + await Moderation.execute(query=index_query_3, return_obj=False) + + insert_query = f""" + INSERT INTO `moderation_{guild.id}` + (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """ + insert_values = ( + 0, + 0, + "NULL", + "NULL", + 0, + 0, + None, + None, + None, + None, + 0, + None, + None, + 0, + dumps([]), + dumps({}), + ) + await Moderation.execute(query=insert_query, parameters=insert_values, return_obj=False) + + logger.trace("SQLite Table created for server %s (%s)", guild.name, guild.id) -- 2.45.3 From 60d4afc6f372c5b2dd8ceb45ffec2a49c4517681 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 11 Jun 2024 03:11:45 -0400 Subject: [PATCH 193/376] fix(aurora): fixed `AuroraBaseModel.to_json()` not using `AuroraBaseModel.dump()` --- aurora/models/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/base.py b/aurora/models/base.py index 7cf8ab1..7f91e34 100644 --- a/aurora/models/base.py +++ b/aurora/models/base.py @@ -15,7 +15,7 @@ class AuroraBaseModel(BaseModel): def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs): from ..utilities.json import dump, dumps # pylint: disable=cyclic-import - return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.model_dump(exclude={"bot"}), indent=indent, **kwargs) + return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.dump(), indent=indent, **kwargs) class AuroraGuildModel(AuroraBaseModel): """Subclass of AuroraBaseModel that includes a guild_id attribute and a guild attribute, and a modified to_json() method to match.""" -- 2.45.3 From 87942213a55d9a7c7c2baf38fd0608f5123a6ea4 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 11 Jun 2024 03:17:38 -0400 Subject: [PATCH 194/376] fix(aurora): typehints --- aurora/models/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/base.py b/aurora/models/base.py index 7f91e34..d3bc075 100644 --- a/aurora/models/base.py +++ b/aurora/models/base.py @@ -13,7 +13,7 @@ class AuroraBaseModel(BaseModel): def dump(self) -> dict: return self.model_dump(exclude={"bot"}) - def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs): + def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs) -> str: from ..utilities.json import dump, dumps # pylint: disable=cyclic-import return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.dump(), indent=indent, **kwargs) @@ -26,6 +26,6 @@ class AuroraGuildModel(AuroraBaseModel): def dump(self) -> dict: return self.model_dump(exclude={"bot", "guild_id", "guild"}) - def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs): + def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs) -> str: from ..utilities.json import dump, dumps # pylint: disable=cyclic-import return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.dump(), indent=indent, **kwargs) -- 2.45.3 From 987fc0dbf83f1d737ee09acb69bed14b5427d550 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sun, 30 Jun 2024 04:56:42 -0400 Subject: [PATCH 195/376] feat(aurora): add scoped export functionality to aurora's `/history` command --- aurora/aurora.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 85d81d6..a6c581c 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1085,47 +1085,45 @@ class Aurora(commands.Cog): ) return - database = await Moderation.connect() + if target: + filename = "moderation_target_" + str(target.id) + "_" + str(interaction.guild.id) + ".json" + moderations = await Moderation.find_by_target(interaction.client, interaction.guild.id, target.id) + elif moderator: + filename = "moderation_moderator_" + str(moderator.id) + "_" + str(interaction.guild.id) + ".json" + moderations = await Moderation.find_by_moderator(interaction.client, interaction.guild.id, moderator.id) + else: + filename = "moderation_" + str(interaction.guild.id) + ".json" + moderations = await Moderation.get_latest(interaction.client, interaction.guild.id) if export: try: - filename = ( + filepath = ( str(data_manager.cog_data_path(cog_instance=self)) + str(os.sep) - + f"moderation_{interaction.guild.id}.json" + + filename ) - cases = await Moderation.get_latest(bot=interaction.client, guild_id=interaction.guild.id) - with open(filename, "w", encoding="utf-8") as f: - dump(obj=cases, fp=f, indent=2) + dump(obj=moderations, fp=f, indent=2) await interaction.followup.send( file=discord.File( - filename, f"moderation_{interaction.guild.id}.json" + fp=filepath, filename=filename ), ephemeral=ephemeral, ) - os.remove(filename) + os.remove(filepath) except json.JSONDecodeError as e: await interaction.followup.send( content=error( "An error occured while exporting the moderation history.\nError:\n" ) - + box(e, "py"), + + box(text=e, lang="py"), ephemeral=ephemeral, ) - await database.close() return - if target: - moderations = await Moderation.find_by_target(interaction.client, interaction.guild.id, target.id) - elif moderator: - moderations = await Moderation.find_by_moderator(interaction.client, interaction.guild.id, moderator.id) - else: - moderations = await Moderation.get_latest(interaction.client, interaction.guild.id) - case_quantity = len(moderations) page_quantity = ceil(case_quantity / pagesize) start_index = (page - 1) * pagesize -- 2.45.3 From c28b089edb2da15ef26a4400b4a84ea12f0224be Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sun, 30 Jun 2024 05:02:32 -0400 Subject: [PATCH 196/376] fix(aurora): fixed an issue with the `/case` command preventing the cog from loading --- aurora/aurora.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index a6c581c..adecdf7 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1042,7 +1042,7 @@ class Aurora(commands.Cog): inline: bool Display infractions in a grid arrangement (does not look very good) export: bool - Exports the server's entire moderation history to a JSON file""" + Exports the server's moderation history to a JSON file""" if ephemeral is None: ephemeral = ( await config.user(interaction.user).history_ephemeral() @@ -1246,9 +1246,9 @@ class Aurora(commands.Cog): @app_commands.command(name="case") @app_commands.choices( - export=[ - Choice(name="Export as File", value="file"), + raw=[ Choice(name="Export as Codeblock", value="codeblock"), + Choice(name="Export as File", value="file"), ] ) async def case( -- 2.45.3 From 3b102debac38a7ee0c06c02d6ef0c7d25bd40a71 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sun, 30 Jun 2024 05:04:21 -0400 Subject: [PATCH 197/376] fix(aurora): fixed a `PermissionError` --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index adecdf7..7977bbe 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1103,7 +1103,7 @@ class Aurora(commands.Cog): + filename ) - with open(filename, "w", encoding="utf-8") as f: + with open(filepath, "w", encoding="utf-8") as f: dump(obj=moderations, fp=f, indent=2) await interaction.followup.send( -- 2.45.3 From 2aadf5134d5a73987f463726c2e8244e3c621a8e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 5 Jul 2024 19:03:44 -0400 Subject: [PATCH 198/376] fix(aurora): use f-strings --- aurora/aurora.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 7977bbe..92d9faf 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1086,13 +1086,13 @@ class Aurora(commands.Cog): return if target: - filename = "moderation_target_" + str(target.id) + "_" + str(interaction.guild.id) + ".json" + filename = f"moderation_target_{str(target.id)}_{str(interaction.guild.id)}.json" moderations = await Moderation.find_by_target(interaction.client, interaction.guild.id, target.id) elif moderator: - filename = "moderation_moderator_" + str(moderator.id) + "_" + str(interaction.guild.id) + ".json" + filename = f"moderation_moderator_{str(moderator.id)}_{str(interaction.guild.id)}.json" moderations = await Moderation.find_by_moderator(interaction.client, interaction.guild.id, moderator.id) else: - filename = "moderation_" + str(interaction.guild.id) + ".json" + filename = f"moderation_{str(interaction.guild.id)}.json" moderations = await Moderation.get_latest(interaction.client, interaction.guild.id) if export: -- 2.45.3 From fcecfe8e88f82807c87d31c3dc54e415afd9e025 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 5 Jul 2024 19:14:03 -0400 Subject: [PATCH 199/376] fix(aurora): fixed an issue in the galacticbot importer --- aurora/importers/galacticbot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/importers/galacticbot.py b/aurora/importers/galacticbot.py index 2fbc62d..0fd1cfc 100644 --- a/aurora/importers/galacticbot.py +++ b/aurora/importers/galacticbot.py @@ -8,7 +8,7 @@ from redbot.core import commands from redbot.core.utils.chat_formatting import box, warning from ..models.moderation import Change, Moderation -from ..utilities.database import create_guild_table +from ..utilities.utils import create_guild_table class ImportGalacticBotView(ui.View): -- 2.45.3 From 9f068bba6fb48d46959ac8a03c4f7046445ba06d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 11:30:37 -0400 Subject: [PATCH 200/376] feat(aurora): starting on the updated moderation type system --- aurora/aurora.py | 134 ++++-------------------- aurora/info.json | 2 +- aurora/models/moderation_types.py | 164 ++++++++++++++++++++++++++++++ aurora/models/type.py | 18 ++++ aurora/utilities/factory.py | 61 ++++++----- aurora/utilities/moderate.py | 41 ++++++++ aurora/utilities/registry.py | 3 + aurora/utilities/utils.py | 50 ++++----- poetry.lock | 19 +++- pyproject.toml | 1 + 10 files changed, 321 insertions(+), 172 deletions(-) create mode 100644 aurora/models/moderation_types.py create mode 100644 aurora/models/type.py create mode 100644 aurora/utilities/moderate.py create mode 100644 aurora/utilities/registry.py diff --git a/aurora/aurora.py b/aurora/aurora.py index 92d9faf..6b970bb 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -29,11 +29,14 @@ from .menus.immune import Immune from .menus.overrides import Overrides from .models.change import Change from .models.moderation import Moderation +from .models.moderation_types import Ban, Tempban from .utilities.config import config, register_config from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from .utilities.json import dump from .utilities.logger import logger -from .utilities.utils import check_moddable, check_permissions, create_guild_table, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from .utilities.moderate import moderate +from .utilities.registry import type_registry +from .utilities.utils import check_moddable, check_permissions, create_guild_table, get_footer_image, log, send_evidenceformat class Aurora(commands.Cog): @@ -42,7 +45,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["SeaswimmerTheFsh"] - __version__ = "2.3.0" + __version__ = "2.4.0" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -72,6 +75,7 @@ class Aurora(commands.Cog): def __init__(self, bot: Red) -> None: super().__init__() self.bot = bot + self.type_registry = type_registry register_config(config) self.handle_expiry.start() # If we don't override aiosqlite's logging level, it will spam the console with dozens of debug messages per query. @@ -775,124 +779,28 @@ class Aurora(commands.Cog): How many days of messages to delete? silent: bool Should the user be messaged?""" - if not await check_moddable(target, interaction, ["ban_members"]): - return - - if delete_messages is None: - delete_messages_seconds = 0 - else: - delete_messages_seconds = delete_messages.value - - try: - await interaction.guild.fetch_ban(target) - await interaction.response.send_message( - content=error(f"{target.mention} is already banned!"), ephemeral=True - ) - return - except discord.errors.NotFound: - pass - if duration: - parsed_time = parse_relativedelta(duration) - if parsed_time is None: - await interaction.response.send_message( - content=error("Please provide a valid duration!"), ephemeral=True - ) - return - try: - parsed_time = timedelta_from_relativedelta(parsed_time) - except ValueError: - await interaction.response.send_message( - content=error("Please provide a valid duration!"), ephemeral=True - ) - return - - await interaction.response.send_message( - content=f"{target.mention} has been banned for {humanize_timedelta(timedelta=parsed_time)}!\n**Reason** - `{reason}`" - ) - - try: - embed = await message_factory( - bot=interaction.client, - color=await self.bot.get_embed_color(interaction.channel), - guild=interaction.guild, - moderator=interaction.user, - reason=reason, - moderation_type="tempbanned", - response=await interaction.original_response(), - duration=parsed_time, - ) - await target.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - await interaction.guild.ban( + await moderate( + interaction, target, - reason=f"Tempbanned by {interaction.user.id} for: {reason} (Duration: {parsed_time})", - delete_message_seconds=delete_messages_seconds, + silent, + ["ban_members"], + Tempban, + reason=reason, + duration=duration, + delete_messages=delete_messages, ) - - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "TEMPBAN", - "USER", - target.id, - None, - parsed_time, - reason, - ) - await interaction.edit_original_response( - content=f"{target.mention} has been banned for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation.id}`)\n**Reason** - `{reason}`" - ) - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) else: - await interaction.response.send_message( - content=f"{target.mention} has been banned!\n**Reason** - `{reason}`" - ) - - if silent is None: - silent = not await config.guild(interaction.guild).dm_users() - if silent is False: - try: - embed = await message_factory( - bot=interaction.client, - color=await self.bot.get_embed_color(interaction.channel), - guild=interaction.guild, - moderator=interaction.user, - reason=reason, - moderation_type="banned", - response=await interaction.original_response(), - ) - await target.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - await interaction.guild.ban( + await moderate( + interaction, target, - reason=f"Banned by {interaction.user.id} for: {reason}", - delete_message_seconds=delete_messages_seconds, + silent, + ["ban_members"], + Ban, + reason=reason, + delete_messages=delete_messages, ) - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "BAN", - "USER", - target.id, - 0, - "NULL", - reason, - ) - await interaction.edit_original_response( - content=f"{target.mention} has been banned! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" - ) - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) - @app_commands.command(name="unban") async def unban( self, diff --git a/aurora/info.json b/aurora/info.json index 34b74c9..092b491 100644 --- a/aurora/info.json +++ b/aurora/info.json @@ -9,7 +9,7 @@ "disabled": false, "min_bot_version": "3.5.0", "min_python_version": [3, 10, 0], - "requirements": ["pydantic", "aiosqlite"], + "requirements": ["pydantic", "aiosqlite", "class-registry"], "tags": [ "mod", "moderate", diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py new file mode 100644 index 0000000..066236f --- /dev/null +++ b/aurora/models/moderation_types.py @@ -0,0 +1,164 @@ + +from discord import File, Guild, Member, User +from discord.errors import HTTPException, NotFound +from redbot.core import app_commands, commands +from redbot.core.bot import Red +from redbot.core.commands.converter import parse_relativedelta +from redbot.core.utils.chat_formatting import bold, error, humanize_timedelta, inline + +from ..utilities.factory import message_factory +from ..utilities.registry import type_registry +from ..utilities.utils import get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta +from .moderation import Moderation +from .type import Type + + +def get_icon(bot: Red) -> File: + cog = bot.get_cog("Aurora") + if cog: + return get_footer_image(cog) + raise ValueError("Aurora cog not found. How was this managed?") + +@type_registry.register(key="ban") +class Ban(Type): + def __init__(self) -> None: + self.type="ban" + self.verb="banned" + + @classmethod + async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Ban': + """Ban a user.""" + bot = ctx.bot + try: + await ctx.guild.fetch_ban(target) + await ctx.send(content=error(f"{target.mention} is already banned!"), ephemeral=True) + except NotFound: + pass + + if delete_messages is None: + delete_messages_seconds = 0 + else: + delete_messages_seconds = delete_messages.value + + response_message = await ctx.send(f"{target.mention} has been {cls.verb}!\n{bold('Reason:')} {inline(reason)}") + + if silent is True: + try: + embed = await message_factory( + bot, + await bot.get_embed_color(ctx.channel), + ctx.guild, + reason, + cls.type, + ctx.author, + None, + response_message + ) + await target.send(embed=embed, file=get_icon(bot)) + except HTTPException: + pass + + await ctx.guild.ban(target, reason=f"Banned by {ctx.author.id} for: {reason}", delete_message_seconds=delete_messages_seconds) + moderation = await Moderation.log( + bot, + ctx.guild.id, + ctx.author.id, + cls.type, + 'USER', + target.id, + None, + None, + reason + ) + await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") + await log(ctx, moderation.id) + await send_evidenceformat(ctx, moderation.id) + return cls + + @classmethod + async def resolve_handler(cls, bot: Red, guild: Guild, target: Member, reason: str): + try: + await guild.fetch_ban(user=target) + except NotFound: + return + await guild.unban(user=target, reason=reason) + + try: + embed = await message_factory( + bot, + await bot.get_embed_color(guild.channels[0]), + guild, + reason, + 'unban', + None, + None, + None + ) + await target.send(embed=embed, file=get_icon(bot)) + except HTTPException: + pass + +@type_registry.register(key="tempban") +class Tempban(Ban): + def __init__(self) -> None: + super().__init__() + self.type="tempban" + self.verb="tempbanned" + + @classmethod + async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, duration: str, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Ban': + """Ban a user.""" + bot = ctx.bot + try: + await ctx.guild.fetch_ban(target) + await ctx.send(content=error(f"{target.mention} is already banned!"), ephemeral=True) + except NotFound: + pass + + if delete_messages is None: + delete_messages_seconds = 0 + else: + delete_messages_seconds = delete_messages.value + + parsed_time = parse_relativedelta(duration) + if not parsed_time: + await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) + try: + parsed_time = timedelta_from_relativedelta(parsed_time) + except ValueError: + await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) + + response_message = await ctx.send(f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}") + + if silent is True: + try: + embed = await message_factory( + bot, + await bot.get_embed_color(ctx.channel), + ctx.guild, + reason, + cls.type, + ctx.author, + parsed_time, + response_message + ) + await target.send(embed=embed, file=get_icon(bot)) + except HTTPException: + pass + + await ctx.guild.ban(target, reason=f"Tempbanned by {ctx.author.id} for: {reason} (Duration: {parsed_time})", delete_message_seconds=delete_messages_seconds) + moderation = await Moderation.log( + bot, + ctx.guild.id, + ctx.author.id, + cls.type, + 'USER', + target.id, + None, + parsed_time, + reason + ) + await response_message.edit(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") + await log(ctx, moderation.id) + await send_evidenceformat(ctx, moderation.id) + return cls diff --git a/aurora/models/type.py b/aurora/models/type.py new file mode 100644 index 0000000..87689ec --- /dev/null +++ b/aurora/models/type.py @@ -0,0 +1,18 @@ + +from discord import Member, User +from redbot.core import commands + + +class Type(object): + def __init__(self) -> None: + self.type = None + self.verb = None + self.embed_desc = "been" + + def __str__(self) -> str: + return self.type + + @classmethod + async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, **kwargs) -> 'Type': # pylint: disable=unused-argument + """This method should be overridden by any child classes, but should retain the same starting keyword arguments.""" + raise NotImplementedError diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index b6fadb7..8c538a4 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -2,13 +2,14 @@ from datetime import datetime, timedelta from typing import Union -from discord import Color, Embed, Guild, Interaction, InteractionMessage, Member, Role, User +from discord import Color, Embed, Guild, Interaction, Member, Message, Role, User from redbot.core import commands from redbot.core.bot import Red from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning from ..models.moderation import Moderation from ..models.partials import PartialUser +from ..models.type import Type from .config import config from .utils import get_bool_emoji, get_pagesize_str @@ -18,10 +19,10 @@ async def message_factory( color: Color, guild: Guild, reason: str, - moderation_type: str, + moderation_type: Type, moderator: Union[Member, User] | None = None, duration: timedelta | None = None, - response: InteractionMessage | None = None, + response: Message | None = None, role: Role | None = None, ) -> Embed: """This function creates a message from set parameters, meant for contacting the moderated user. @@ -31,49 +32,47 @@ async def message_factory( color (Color): The color of the embed. guild (Guild): The guild the moderation occurred in. reason (str): The reason for the moderation. - moderation_type (str): The type of moderation. + moderation_type (Type): The type of moderation. moderator (Union[Member, User], optional): The moderator who performed the moderation. Defaults to None. duration (timedelta, optional): The duration of the moderation. Defaults to None. - response (InteractionMessage, optional): The response message. Defaults to None. + response (Message, optional): The response message. Defaults to None. role (Role, optional): The role that was added or removed. Defaults to None. Returns: embed: The message embed. """ - if response is not None and moderation_type not in [ - "kicked", - "banned", - "tempbanned", - "unbanned", + if response is not None and moderation_type.type not in [ + "kick", + "ban", + "tempban", + "unban", ]: guild_name = f"[{guild.name}]({response.jump_url})" else: guild_name = guild.name - title = moderation_type - - if moderation_type in ["tempbanned", "muted"] and duration: + if duration: embed_duration = f" for {humanize_timedelta(timedelta=duration)}" else: embed_duration = "" - if moderation_type == "note": - embed_desc = "received a" - elif moderation_type == "addrole": - embed_desc = f"received the {role.name} role" - title = "Role Added" - moderation_type = "" - elif moderation_type == "removerole": - embed_desc = f"lost the {role.name} role" - title = "Role Removed" - moderation_type = "" - else: - embed_desc = "been" + # if moderation_type.type == "note": + # embed_desc = "received a" + # elif moderation_type.type == "addrole": + # embed_desc = f"received the {role.name} role" + # title = "Role Added" + # verb = "" + # elif moderation_type.type == "removerole": + # embed_desc = f"lost the {role.name} role" + # title = "Role Removed" + # verb = "" + # else: + # embed_desc = "been" embed = Embed( - title=str.title(title), - description=f"You have {embed_desc} {moderation_type}{embed_duration} in {guild_name}.", + title=str.title(moderation_type.type), + description=f"You have {moderation_type.embed_desc} {moderation_type.verb}{embed_duration} in {guild_name}.", color=color, timestamp=datetime.now(), ) @@ -99,12 +98,12 @@ async def message_factory( async def log_factory( - interaction: Interaction, moderation: Moderation, resolved: bool = False + ctx: commands.Context, moderation: Moderation, resolved: bool = False ) -> Embed: """This function creates a log embed from set parameters, meant for moderation logging. Args: - interaction (discord.Interaction): The interaction object. + ctx (commands.Context): The ctx object. moderation (aurora.models.Moderation): The moderation object. resolved (bool, optional): Whether the case is resolved or not. Defaults to False. """ @@ -113,7 +112,7 @@ async def log_factory( if resolved: embed = Embed( title=f"📕 Case #{moderation.id:,} Resolved", - color=await interaction.client.get_embed_color(interaction.channel), + color=await ctx.bot.get_embed_color(ctx.channel), ) resolved_by = await moderation.get_resolved_by() @@ -145,7 +144,7 @@ async def log_factory( else: embed = Embed( title=f"📕 Case #{moderation.id:,}", - color=await interaction.client.get_embed_color(interaction.channel), + color=await ctx.bot.get_embed_color(ctx.channel), ) embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " diff --git a/aurora/utilities/moderate.py b/aurora/utilities/moderate.py new file mode 100644 index 0000000..7ae98cc --- /dev/null +++ b/aurora/utilities/moderate.py @@ -0,0 +1,41 @@ +from typing import List, Union + +import discord +from redbot.core import app_commands, commands + +from ..models.moderation_types import Type +from .config import config +from .registry import type_registry +from .utils import check_moddable + + +async def moderate(ctx: Union[commands.Context, discord.Interaction], target: discord.Member, silent: bool | None, permissions: List[str], moderation_type: Type | str, **kwargs) -> None | Type: + """This function is used to moderate users. + It checks if the target can be moderated, then calls the handler method of the moderation type specified. + + Args: + bot (Red): The bot instance. + ctx (Union[commands.Context, discord.Interaction]): The context of the command. If this is a `discord.Interaction` object, it will be converted to a `commands.Context` object. Additionally, if the interaction orignated from a context menu, the `ctx.author` attribute will be overriden to `interaction.user`. + target (discord.Member): The target user to moderate. + silent (bool | None): Whether to send the moderation action to the target. + permissions (List[str]): The permissions required to moderate the target. + moderation_type (Type): The moderation type (handler) to use. See `aurora.models.moderation_types` for some examples. + **kwargs: The keyword arguments to pass to the handler method. + """ + if not await check_moddable(target, ctx, permissions): + return + if silent is None: + silent = not await config.guild(ctx.guild).dm_users() + if isinstance(moderation_type, str): + moderation_type = type_registry[str.lower(moderation_type)] + if isinstance(ctx, discord.Interaction): + interaction = ctx + ctx = await commands.Context.from_interaction(interaction) + if isinstance(interaction.command, app_commands.ContextMenu): + ctx.author = interaction.user + return await moderation_type.handler( + ctx, + target, + silent, + **kwargs + ) diff --git a/aurora/utilities/registry.py b/aurora/utilities/registry.py new file mode 100644 index 0000000..7aca3c1 --- /dev/null +++ b/aurora/utilities/registry.py @@ -0,0 +1,3 @@ +from class_registry import ClassRegistry + +type_registry = ClassRegistry() diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index c898e60..0686c02 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -17,7 +17,7 @@ from ..utilities.logger import logger def check_permissions( user: User, permissions: Tuple[str], - ctx: Union[commands.Context, Interaction] | None = None, + ctx: commands.Context | Interaction | None = None, guild: Guild | None = None, ) -> Union[bool, str]: """Checks if a user has a specific permission (or a list of permissions) in a channel.""" @@ -43,12 +43,12 @@ def check_permissions( async def check_moddable( - target: Union[User, Member, TextChannel], interaction: Interaction, permissions: Tuple[str] + target: Union[User, Member, TextChannel], ctx: commands.Context, permissions: Tuple[str] ) -> bool: """Checks if a moderator can moderate a target.""" is_channel = isinstance(target, TextChannel) - if check_permissions(interaction.client.user, permissions, guild=interaction.guild): - await interaction.response.send_message( + if check_permissions(ctx.bot.user, permissions, guild=ctx.guild): + await ctx.send( error( f"I do not have the `{permissions}` permission, required for this action." ), @@ -56,9 +56,9 @@ async def check_moddable( ) return False - if await config.guild(interaction.guild).use_discord_permissions() is True: - if check_permissions(interaction.user, permissions, guild=interaction.guild): - await interaction.response.send_message( + if await config.guild(ctx.guild).use_discord_permissions() is True: + if check_permissions(ctx.author, permissions, guild=ctx.guild): + await ctx.send( error( f"You do not have the `{permissions}` permission, required for this action." ), @@ -66,21 +66,21 @@ async def check_moddable( ) return False - if interaction.user.id == target.id: - await interaction.response.send_message( + if ctx.author.id == target.id: + await ctx.send( content="You cannot moderate yourself!", ephemeral=True ) return False if not is_channel and target.bot: - await interaction.response.send_message( + await ctx.send( content="You cannot moderate bots!", ephemeral=True ) return False if isinstance(target, Member): - if interaction.user.top_role <= target.top_role and await config.guild(interaction.guild).respect_hierarchy() is True: - await interaction.response.send_message( + if ctx.author.top_role <= target.top_role and await config.guild(ctx.guild).respect_hierarchy() is True: + await ctx.send( content=error( "You cannot moderate members with a higher role than you!" ), @@ -89,10 +89,10 @@ async def check_moddable( return False if ( - interaction.guild.get_member(interaction.client.user.id).top_role + ctx.guild.get_member(ctx.bot.user.id).top_role <= target.top_role ): - await interaction.response.send_message( + await ctx.send( content=error( "You cannot moderate members with a role higher than the bot!" ), @@ -104,7 +104,7 @@ async def check_moddable( for role in target.roles: if role.id in immune_roles: - await interaction.response.send_message( + await ctx.send( content=error("You cannot moderate members with an immune role!"), ephemeral=True, ) @@ -113,19 +113,19 @@ async def check_moddable( return True -async def log(interaction: Interaction, moderation_id: int, resolved: bool = False) -> None: +async def log(ctx: commands.Context, moderation_id: int, resolved: bool = False) -> None: """This function sends a message to the guild's configured logging channel when an infraction takes place.""" from ..models.moderation import Moderation from .factory import log_factory - logging_channel_id = await config.guild(interaction.guild).log_channel() + logging_channel_id = await config.guild(ctx.guild).log_channel() if logging_channel_id != " ": - logging_channel = interaction.guild.get_channel(logging_channel_id) + logging_channel = ctx.guild.get_channel(logging_channel_id) try: - moderation = await Moderation.find_by_id(interaction.client, moderation_id, interaction.guild_id) + moderation = await Moderation.find_by_id(ctx.bot, moderation_id, ctx.guild_id) embed = await log_factory( - interaction=interaction, moderation=moderation, resolved=resolved + ctx=ctx, moderation=moderation, resolved=resolved ) try: await logging_channel.send(embed=embed) @@ -135,22 +135,22 @@ async def log(interaction: Interaction, moderation_id: int, resolved: bool = Fal return -async def send_evidenceformat(interaction: Interaction, moderation_id: int) -> None: +async def send_evidenceformat(ctx: commands.Context, moderation_id: int) -> None: """This function sends an ephemeral message to the moderator who took the moderation action, with a pre-made codeblock for use in the mod-evidence channel.""" from ..models.moderation import Moderation from .factory import evidenceformat_factory send_evidence_bool = ( - await config.user(interaction.user).auto_evidenceformat() - or await config.guild(interaction.guild).auto_evidenceformat() + await config.user(ctx.author).auto_evidenceformat() + or await config.guild(guild=ctx.guild).auto_evidenceformat() or False ) if send_evidence_bool is False: return - moderation = await Moderation.find_by_id(interaction.client, moderation_id, interaction.guild.id) + moderation = await Moderation.find_by_id(ctx.bot, moderation_id, ctx.guild.id) content = await evidenceformat_factory(moderation=moderation) - await interaction.followup.send(content=content, ephemeral=True) + await ctx.send(content=content, ephemeral=True) def get_bool_emoji(value: Optional[bool]) -> str: diff --git a/poetry.lock b/poetry.lock index be5a40b..4474ce9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiohttp" @@ -599,6 +599,20 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] +[[package]] +name = "class-registry" +version = "2.1.2" +description = "Factory+Registry pattern for Python classes." +optional = false +python-versions = "*" +files = [ + {file = "class-registry-2.1.2.tar.gz", hash = "sha256:678bdb0322566c07a4d8905140d364bd34a73baf46bf7580fc2e06fa994d4e7e"}, + {file = "class_registry-2.1.2-py2.py3-none-any.whl", hash = "sha256:cfb855514753e2edfe8d88b14a6e449820682fe0983efe61b83df28b688b3e5a"}, +] + +[package.dependencies] +six = "*" + [[package]] name = "click" version = "8.1.7" @@ -1199,6 +1213,7 @@ optional = false python-versions = ">=3.6" files = [ {file = "mkdocs-redirects-1.2.1.tar.gz", hash = "sha256:9420066d70e2a6bb357adf86e67023dcdca1857f97f07c7fe450f8f1fb42f861"}, + {file = "mkdocs_redirects-1.2.1-py3-none-any.whl", hash = "sha256:497089f9e0219e7389304cffefccdfa1cac5ff9509f2cb706f4c9b221726dffb"}, ] [package.dependencies] @@ -2673,4 +2688,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "22b824824f73dc3dc1a9a0a01060371ee1f6414e5bef39cb7455d21121988b47" +content-hash = "bf7dd1ef2ebf8aedeb3295201cf04b53e5cd04cca488fd1e7e0257cbe9597513" diff --git a/pyproject.toml b/pyproject.toml index 644cbdf..68f5ea3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,7 @@ colorthief = "^0.2.1" beautifulsoup4 = "^4.12.3" markdownify = "^0.12.1" aiosqlite = "^0.20.0" +class-registry = "^2.1.2" [tool.poetry.group.dev] optional = true -- 2.45.3 From aeec616be516eb1337ab155b8eef6f78827e9bd5 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 11:32:33 -0400 Subject: [PATCH 201/376] fix(aurora): assume that `ctx` is a `commands.Context` object before trying to use it in `moderate` --- aurora/utilities/moderate.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aurora/utilities/moderate.py b/aurora/utilities/moderate.py index 7ae98cc..b0f6ca1 100644 --- a/aurora/utilities/moderate.py +++ b/aurora/utilities/moderate.py @@ -22,10 +22,6 @@ async def moderate(ctx: Union[commands.Context, discord.Interaction], target: di moderation_type (Type): The moderation type (handler) to use. See `aurora.models.moderation_types` for some examples. **kwargs: The keyword arguments to pass to the handler method. """ - if not await check_moddable(target, ctx, permissions): - return - if silent is None: - silent = not await config.guild(ctx.guild).dm_users() if isinstance(moderation_type, str): moderation_type = type_registry[str.lower(moderation_type)] if isinstance(ctx, discord.Interaction): @@ -33,6 +29,10 @@ async def moderate(ctx: Union[commands.Context, discord.Interaction], target: di ctx = await commands.Context.from_interaction(interaction) if isinstance(interaction.command, app_commands.ContextMenu): ctx.author = interaction.user + if not await check_moddable(target, ctx, permissions): + return + if silent is None: + silent = not await config.guild(ctx.guild).dm_users() return await moderation_type.handler( ctx, target, -- 2.45.3 From f2a88cbf94336c2be6a699afee3b12facfe8f056 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 11:46:13 -0400 Subject: [PATCH 202/376] fix(aurora): fixed an AttributeError --- aurora/models/moderation_types.py | 21 +++++++++------------ aurora/models/type.py | 24 +++++++++++++++++++----- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 066236f..3921b2f 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -21,9 +21,8 @@ def get_icon(bot: Red) -> File: @type_registry.register(key="ban") class Ban(Type): - def __init__(self) -> None: - self.type="ban" - self.verb="banned" + moderation_type="ban" + verb="banned" @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Ban': @@ -49,7 +48,7 @@ class Ban(Type): await bot.get_embed_color(ctx.channel), ctx.guild, reason, - cls.type, + cls(), ctx.author, None, response_message @@ -63,7 +62,7 @@ class Ban(Type): bot, ctx.guild.id, ctx.author.id, - cls.type, + cls.moderation_type, 'USER', target.id, None, @@ -76,7 +75,7 @@ class Ban(Type): return cls @classmethod - async def resolve_handler(cls, bot: Red, guild: Guild, target: Member, reason: str): + async def resolve_handler(cls, bot: Red, guild: Guild, target: Member | User, reason: str | None = None) -> None: try: await guild.fetch_ban(user=target) except NotFound: @@ -100,10 +99,8 @@ class Ban(Type): @type_registry.register(key="tempban") class Tempban(Ban): - def __init__(self) -> None: - super().__init__() - self.type="tempban" - self.verb="tempbanned" + moderation_type="tempban" + verb="tempbanned" @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, duration: str, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Ban': @@ -137,7 +134,7 @@ class Tempban(Ban): await bot.get_embed_color(ctx.channel), ctx.guild, reason, - cls.type, + cls(), ctx.author, parsed_time, response_message @@ -151,7 +148,7 @@ class Tempban(Ban): bot, ctx.guild.id, ctx.author.id, - cls.type, + cls.moderation_type, 'USER', target.id, None, diff --git a/aurora/models/type.py b/aurora/models/type.py index 87689ec..cc7ec61 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -1,13 +1,15 @@ -from discord import Member, User +from typing import Any + +from discord import Guild, Member, User from redbot.core import commands +from redbot.core.bot import Red class Type(object): - def __init__(self) -> None: - self.type = None - self.verb = None - self.embed_desc = "been" + moderation_type = None + verb = None + embed_desc = "been" def __str__(self) -> str: return self.type @@ -16,3 +18,15 @@ class Type(object): async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, **kwargs) -> 'Type': # pylint: disable=unused-argument """This method should be overridden by any child classes, but should retain the same starting keyword arguments.""" raise NotImplementedError + + @classmethod + async def resolve_handler(cls, bot: Red, guild: Guild, target: Member | User, reason: str | None = None) -> Any: # pylint: disable=unused-argument + """This method should be overridden by any resolvable child classes, but should retain the same keyword arguments. + If your moderation type should not be resolvable, do not override this.""" + raise NotImplementedError + + @classmethod + async def expiry_handler(cls, bot: Red, guild: Guild, target: Member | User) -> Any: # pylint: disable=unused-argument + """This method should be overridden by any expirable child classes, but should retain the same keyword arguments. + If your moderation type should not expire, do not override this.""" + raise NotImplementedError -- 2.45.3 From fac00feeeffd048ea150900fde9ed8dc576c54ee Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 11:47:56 -0400 Subject: [PATCH 203/376] fix(aurora): fixed another AttributeError --- aurora/utilities/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 0686c02..1445537 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -123,7 +123,7 @@ async def log(ctx: commands.Context, moderation_id: int, resolved: bool = False) logging_channel = ctx.guild.get_channel(logging_channel_id) try: - moderation = await Moderation.find_by_id(ctx.bot, moderation_id, ctx.guild_id) + moderation = await Moderation.find_by_id(ctx.bot, moderation_id, ctx.guild.id) embed = await log_factory( ctx=ctx, moderation=moderation, resolved=resolved ) -- 2.45.3 From ee49d5b10c209e2ae1091a007a07ba0d4750f239 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 11:50:59 -0400 Subject: [PATCH 204/376] misc(aurora): make `target_type` lowercase --- aurora/models/moderation_types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 3921b2f..a6a4894 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -63,7 +63,7 @@ class Ban(Type): ctx.guild.id, ctx.author.id, cls.moderation_type, - 'USER', + 'user', target.id, None, None, @@ -149,7 +149,7 @@ class Tempban(Ban): ctx.guild.id, ctx.author.id, cls.moderation_type, - 'USER', + 'user', target.id, None, parsed_time, -- 2.45.3 From dd89bfaf34738feea7ba1aab73914ecda236db21 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 11:52:19 -0400 Subject: [PATCH 205/376] fix(aurora): checking against the wrong bool value for `silent` --- aurora/models/moderation_types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index a6a4894..3786843 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -41,7 +41,7 @@ class Ban(Type): response_message = await ctx.send(f"{target.mention} has been {cls.verb}!\n{bold('Reason:')} {inline(reason)}") - if silent is True: + if silent is False: try: embed = await message_factory( bot, @@ -127,7 +127,7 @@ class Tempban(Ban): response_message = await ctx.send(f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}") - if silent is True: + if silent is False: try: embed = await message_factory( bot, -- 2.45.3 From 88cc7b4a3f9fb43b16bad7dd74b4261c0423c577 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 11:53:39 -0400 Subject: [PATCH 206/376] fix(aurora): fixed another attributeerror --- aurora/utilities/factory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 8c538a4..760162b 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -42,7 +42,7 @@ async def message_factory( Returns: embed: The message embed. """ - if response is not None and moderation_type.type not in [ + if response is not None and moderation_type.moderation_type not in [ "kick", "ban", "tempban", @@ -71,7 +71,7 @@ async def message_factory( # embed_desc = "been" embed = Embed( - title=str.title(moderation_type.type), + title=str.title(moderation_type.moderation_type), description=f"You have {moderation_type.embed_desc} {moderation_type.verb}{embed_duration} in {guild_name}.", color=color, timestamp=datetime.now(), -- 2.45.3 From 127dd564f5a5be17cab6fd2135f5864735730343 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 11:55:05 -0400 Subject: [PATCH 207/376] fix(aurora): use the verb for message embed titles --- aurora/utilities/factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 760162b..9aa2372 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -71,7 +71,7 @@ async def message_factory( # embed_desc = "been" embed = Embed( - title=str.title(moderation_type.moderation_type), + title=str.title(moderation_type.verb), description=f"You have {moderation_type.embed_desc} {moderation_type.verb}{embed_duration} in {guild_name}.", color=color, timestamp=datetime.now(), -- 2.45.3 From 134e787c4287316d62daf12615d5b6b3b9b507b8 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 11:58:46 -0400 Subject: [PATCH 208/376] fix(aurora): fixed the `Moderation.get_target` method trying to get a channel object from a user id --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index afd9c8e..6550768 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -52,7 +52,7 @@ class Moderation(AuroraGuildModel): return await PartialUser.from_id(self.bot, self.moderator_id) async def get_target(self) -> Union["PartialUser", "PartialChannel"]: - if self.target_type == "USER": + if str.lower(self.target_type) == "user": return await PartialUser.from_id(self.bot, self.target_id) return await PartialChannel.from_id(self.bot, self.target_id, self.guild) -- 2.45.3 From 08512d0dadf3cda1e00900d3470509cd76f5fc20 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 12:03:49 -0400 Subject: [PATCH 209/376] feat(aurora): use the type_registry in the `Moderation` object --- aurora/models/moderation.py | 12 +++++++++--- aurora/utilities/json.py | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 6550768..f2c8045 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -12,16 +12,18 @@ from redbot.core import data_manager from redbot.core.bot import Red from ..utilities.logger import logger +from ..utilities.registry import type_registry from ..utilities.utils import timedelta_to_string from .base import AuroraGuildModel from .change import Change from .partials import PartialChannel, PartialRole, PartialUser +from .type import Type class Moderation(AuroraGuildModel): moderation_id: int timestamp: datetime - moderation_type: str + moderation_type: Type target_type: str target_id: int moderator_id: int @@ -125,7 +127,7 @@ class Moderation(AuroraGuildModel): await self.execute(query, ( self.timestamp.timestamp(), - self.moderation_type, + self.moderation_type.moderation_type, self.target_type, self.moderator_id, self.role_id, @@ -192,11 +194,15 @@ class Moderation(AuroraGuildModel): else: metadata = {} + moderation_type = str.lower(result[2]) + if moderation_type in type_registry: + moderation_type = type_registry[moderation_type] + case = { "moderation_id": int(result[0]), "guild_id": int(guild_id), "timestamp": datetime.fromtimestamp(result[1]), - "moderation_type": str(result[2]), + "moderation_type": moderation_type, "target_type": str(result[3]), "target_id": int(result[4]), "moderator_id": int(result[5]), diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index 5dbd4eb..eba9c43 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -5,6 +5,7 @@ from typing import Any from redbot.core.bot import Red from ..models.base import AuroraBaseModel +from ..models.type import Type class JSONEncoder(json.JSONEncoder): @@ -16,6 +17,8 @@ class JSONEncoder(json.JSONEncoder): return str(o) case AuroraBaseModel(): return o.dump() + case Type(): + return o.moderation_type case Red(): return None case _: -- 2.45.3 From b85932c33876ead7b742901c29c1da46fba185a9 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 12:15:39 -0400 Subject: [PATCH 210/376] feat(aurora): use resolve handlers --- aurora/models/moderation.py | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index f2c8045..0fc2c1b 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -7,7 +7,6 @@ from typing import Dict, Iterable, List, Optional, Tuple, Union import discord from aiosqlite import Connection, Cursor, OperationalError, Row from aiosqlite import connect as aiosqlite_connect -from discord import NotFound from redbot.core import data_manager from redbot.core.bot import Red @@ -82,26 +81,28 @@ class Moderation(AuroraGuildModel): self.resolved_by = resolved_by self.resolve_reason = reason - if self.type in ["UNMUTE", "UNBAN"]: - raise TypeError("Cannot resolve an unmute or unban case!") + await self.type.resolve_handler(self.bot, self.guild, await self.get_target(), reason) - if self.type == "MUTE": - try: - guild: discord.Guild = await self.bot.fetch_guild(self.guild_id) - member = await guild.fetch_member(self.target_id) + # if self.type in ["UNMUTE", "UNBAN"]: + # raise TypeError("Cannot resolve an unmute or unban case!") - await member.timeout( - None, reason=f"Case {self.moderation_id} resolved by {resolved_by}{' for '+ reason if reason else ''}" - ) - except NotFound: - pass + # if self.type == "MUTE": + # try: + # guild: discord.Guild = await self.bot.fetch_guild(self.guild_id) + # member = await guild.fetch_member(self.target_id) - if self.type in ["BAN", "TEMPBAN"]: - try: - guild: discord.Guild = await self.bot.fetch_guild(self.guild_id) - await guild.unban(await self.get_target(), reason=f"Case {self.moderation_id} resolved by {resolved_by}{' for '+ reason if reason else ''}") - except NotFound: - pass + # await member.timeout( + # None, reason=f"Case {self.moderation_id} resolved by {resolved_by}{' for '+ reason if reason else ''}" + # ) + # except NotFound: + # pass + + # if self.type in ["BAN", "TEMPBAN"]: + # try: + # guild: discord.Guild = await self.bot.fetch_guild(self.guild_id) + # await guild.unban(await self.get_target(), reason=f"Case {self.moderation_id} resolved by {resolved_by}{' for '+ reason if reason else ''}") + # except NotFound: + # pass if not self.changes: self.changes.append(Change.from_dict(self.bot, { -- 2.45.3 From 54ac77ceb938dd0ba24073a55df08eb5e53ffc72 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 12:16:15 -0400 Subject: [PATCH 211/376] fix(aurora): fix ``__str__()`` method of the `Type` class --- aurora/models/type.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/type.py b/aurora/models/type.py index cc7ec61..5471c6a 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -12,7 +12,7 @@ class Type(object): embed_desc = "been" def __str__(self) -> str: - return self.type + return self.moderation_type @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, **kwargs) -> 'Type': # pylint: disable=unused-argument -- 2.45.3 From bf945ec9f1ef3ab2a068daf0e1a6a57fa171a4f5 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 12:23:06 -0400 Subject: [PATCH 212/376] fix(aurora): fixed some stuff up --- aurora/models/moderation.py | 4 ++-- aurora/models/moderation_types.py | 10 ++++++---- aurora/models/type.py | 8 +++++--- aurora/utilities/factory.py | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 0fc2c1b..535f9a1 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -313,7 +313,7 @@ class Moderation(AuroraGuildModel): bot: Red, guild_id: int, moderator_id: int, - moderation_type: str, + moderation_type: Type, target_type: str, target_id: int, role_id: int | None = None, @@ -373,7 +373,7 @@ class Moderation(AuroraGuildModel): case = { "moderation_id": moderation_id, "timestamp": timestamp.timestamp(), - "moderation_type": moderation_type, + "moderation_type": moderation_type.key, "target_type": target_type, "target_id": target_id, "moderator_id": moderator_id, diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 3786843..5022698 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -21,7 +21,8 @@ def get_icon(bot: Red) -> File: @type_registry.register(key="ban") class Ban(Type): - moderation_type="ban" + key="ban" + string="ban" verb="banned" @classmethod @@ -62,7 +63,7 @@ class Ban(Type): bot, ctx.guild.id, ctx.author.id, - cls.moderation_type, + cls(), 'user', target.id, None, @@ -99,7 +100,8 @@ class Ban(Type): @type_registry.register(key="tempban") class Tempban(Ban): - moderation_type="tempban" + key="tempban" + string="tempban" verb="tempbanned" @classmethod @@ -148,7 +150,7 @@ class Tempban(Ban): bot, ctx.guild.id, ctx.author.id, - cls.moderation_type, + cls(), 'user', target.id, None, diff --git a/aurora/models/type.py b/aurora/models/type.py index 5471c6a..11a0eae 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -6,13 +6,15 @@ from redbot.core import commands from redbot.core.bot import Red +#@type_registry.register(key="type") class Type(object): - moderation_type = None - verb = None + key = "type" # this should ALWAYS be the same as the registry key, and should NEVER be localized + string = "type" + verb = "typed" embed_desc = "been" def __str__(self) -> str: - return self.moderation_type + return self.string @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, **kwargs) -> 'Type': # pylint: disable=unused-argument diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 9aa2372..92ed7d8 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -42,7 +42,7 @@ async def message_factory( Returns: embed: The message embed. """ - if response is not None and moderation_type.moderation_type not in [ + if response is not None and moderation_type.key not in [ "kick", "ban", "tempban", -- 2.45.3 From 0c628cf2a22ea095ebac3e2dc0c8203af04f8cb2 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 12:27:59 -0400 Subject: [PATCH 213/376] fix(aurora): fixed a TypeError --- aurora/models/moderation.py | 2 +- aurora/utilities/factory.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 535f9a1..c501398 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -42,7 +42,7 @@ class Moderation(AuroraGuildModel): return self.moderation_id @property - def type(self) -> str: + def type(self) -> Type: return self.moderation_type @property diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 92ed7d8..76c8d9b 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -116,7 +116,7 @@ async def log_factory( ) resolved_by = await moderation.get_resolved_by() - embed.description = f"**Type:** {str.title(moderation.moderation_type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " + embed.description = f"**Type:** {str.title(moderation.type.string)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " if moderation.duration is not None: duration_embed = ( @@ -146,7 +146,7 @@ async def log_factory( title=f"📕 Case #{moderation.id:,}", color=await ctx.bot.get_embed_color(ctx.channel), ) - embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " + embed.description = f"**Type:** {str.title(moderation.type.string)}\n**Target:** {target.name} ({target.id})\n**Moderator:** {moderator.name} ({moderator.id})\n**Timestamp:** | " if moderation.duration: embed.description = ( @@ -176,7 +176,7 @@ async def case_factory(interaction: Interaction, moderation: Moderation) -> Embe title=f"📕 Case #{moderation.id:,}", color=await interaction.client.get_embed_color(interaction.channel), ) - embed.description = f"**Type:** {str.title(moderation.type)}\n**Target:** `{target.name}` ({target.id})\n**Moderator:** `{moderator.name}` ({moderator.id})\n**Resolved:** {moderation.resolved}\n**Timestamp:** | " + embed.description = f"**Type:** {str.title(moderation.type.string)}\n**Target:** `{target.name}` ({target.id})\n**Moderator:** `{moderator.name}` ({moderator.id})\n**Resolved:** {moderation.resolved}\n**Timestamp:** | " if moderation.duration: duration_embed = ( @@ -284,7 +284,7 @@ async def evidenceformat_factory(moderation: Moderation) -> str: target = await moderation.get_target() moderator = await moderation.get_moderator() - content = f"Case: {moderation.id:,} ({str.title(moderation.type)})\nTarget: {target.name} ({target.id})\nModerator: {moderator.name} ({moderator.id})" + content = f"Case: {moderation.id:,} ({str.title(moderation.type.string)})\nTarget: {target.name} ({target.id})\nModerator: {moderator.name} ({moderator.id})" if moderation.duration is not None: content += f"\nDuration: {humanize_timedelta(timedelta=moderation.duration)}" -- 2.45.3 From a05e957dde6c72c67b739b9a0f95095319a90f02 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 12:29:43 -0400 Subject: [PATCH 214/376] fix(aurora): fixed a json encoder issue that was causing an attributeerror --- aurora/utilities/json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index eba9c43..3859bf4 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -18,7 +18,7 @@ class JSONEncoder(json.JSONEncoder): case AuroraBaseModel(): return o.dump() case Type(): - return o.moderation_type + return o.key case Red(): return None case _: -- 2.45.3 From 8f0425456c6aef415c63c5811cd2c54ea42b710c Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 13:03:59 -0400 Subject: [PATCH 215/376] feat(aurora): boilerplate for all currently added moderation types --- aurora/importers/aurora.py | 19 ++- aurora/models/moderation_types.py | 191 +++++++++++++++++++++++++++++- aurora/models/type.py | 8 +- aurora/utilities/moderate.py | 4 +- 4 files changed, 201 insertions(+), 21 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 2500993..0e1c7a9 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -9,7 +9,9 @@ from redbot.core import commands, data_manager from redbot.core.utils.chat_formatting import warning from ..models.moderation import Moderation +from ..models.type import Type from ..utilities.json import dump +from ..utilities.registry import type_registry from ..utilities.utils import create_guild_table, timedelta_from_string @@ -40,23 +42,18 @@ class ImportAuroraView(ui.View): file = await self.ctx.message.attachments[0].read() data: list[dict] = sorted(json.loads(file), key=lambda x: x["moderation_id"]) - user_mod_types = ["NOTE", "WARN", "ADDROLE", "REMOVEROLE", "MUTE", "UNMUTE", "KICK", "TEMPBAN", "BAN", "UNBAN"] - - channel_mod_types = ["SLOWMODE", "LOCKDOWN"] - failed_cases = [] for case in data: if case["moderation_id"] == 0: continue + moderation_type: Type = type_registry[str.lower(case["moderation_type"])] if "target_type" not in case or not case["target_type"]: - if case["moderation_type"] in user_mod_types: - case["target_type"] = "USER" - elif case["moderation_type"] in channel_mod_types: - case["target_type"] = "CHANNEL" + if moderation_type.channel: + case["target_type"] = "channel" else: - case["target_type"] = "USER" + case["target_type"] = "user" if "role_id" not in case or not case["role_id"]: case["role_id"] = None @@ -95,8 +92,8 @@ class ImportAuroraView(ui.View): bot=interaction.client, guild_id=self.ctx.guild.id, moderator_id=case["moderator_id"], - moderation_type=case["moderation_type"], - target_type=case["target_type"], + moderation_type=moderation_type.key, + target_type=case["target_type"].lower(), target_id=case["target_id"], role_id=case["role_id"], duration=duration, diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 5022698..db36dd0 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -1,5 +1,8 @@ -from discord import File, Guild, Member, User +from math import ceil + +from discord import File, Guild, Member, TextChannel, User +from discord.abc import Messageable from discord.errors import HTTPException, NotFound from redbot.core import app_commands, commands from redbot.core.bot import Red @@ -19,6 +22,86 @@ def get_icon(bot: Red) -> File: return get_footer_image(cog) raise ValueError("Aurora cog not found. How was this managed?") +@type_registry.register(key="note") +class Note(Type): + key="note" + string="note" + verb="noted" + +@type_registry.register(key="warn") +class Warn(Type): + key="warn" + string="warn" + verb="warned" + +@type_registry.register(key="addrole") +class AddRole(Type): + key="addrole" + string="addrole" + verb="added a role to" + +@type_registry.register(key="removerole") +class RemoveRole(Type): + key="removerole" + string="removerole" + verb="removed a role from" + +@type_registry.register(key="mute") +class Mute(Type): + key="mute" + string="mute" + verb="muted" + +@type_registry.register(key="unmute") +class Unmute(Type): + key="unmute" + string="unmute" + verb="unmuted" + +@type_registry.register(key="kick") +class Kick(Type): + key="kick" + string="kick" + verb="kicked" + + @classmethod + async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None) -> 'Kick': + """Kick a user.""" + bot = ctx.bot + response_message = await ctx.send(f"{target.mention} has been {cls.verb}!\n{bold('Reason:')} {inline(reason)}") + + if silent is False: + try: + embed = await message_factory( + bot, + await bot.get_embed_color(ctx.channel), + ctx.guild, + reason, + cls(), + ctx.author, + None, + response_message + ) + await target.send(embed=embed, file=get_icon(bot)) + except HTTPException: + pass + + await target.kick(reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}") + moderation = await Moderation.log( + bot, + ctx.guild.id, + ctx.author.id, + cls(), + 'user', + target.id, + None, + None, + reason + ) + await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") + await log(ctx, moderation.id) + await send_evidenceformat(ctx, moderation.id) + return cls @type_registry.register(key="ban") class Ban(Type): key="ban" @@ -31,7 +114,7 @@ class Ban(Type): bot = ctx.bot try: await ctx.guild.fetch_ban(target) - await ctx.send(content=error(f"{target.mention} is already banned!"), ephemeral=True) + await ctx.send(content=error(f"{target.mention} is already {cls.verb}!"), ephemeral=True) except NotFound: pass @@ -58,7 +141,7 @@ class Ban(Type): except HTTPException: pass - await ctx.guild.ban(target, reason=f"Banned by {ctx.author.id} for: {reason}", delete_message_seconds=delete_messages_seconds) + await ctx.guild.ban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}", delete_message_seconds=delete_messages_seconds) moderation = await Moderation.log( bot, ctx.guild.id, @@ -110,7 +193,7 @@ class Tempban(Ban): bot = ctx.bot try: await ctx.guild.fetch_ban(target) - await ctx.send(content=error(f"{target.mention} is already banned!"), ephemeral=True) + await ctx.send(content=error(f"{target.mention} is already {Ban.verb}!"), ephemeral=True) except NotFound: pass @@ -145,7 +228,7 @@ class Tempban(Ban): except HTTPException: pass - await ctx.guild.ban(target, reason=f"Tempbanned by {ctx.author.id} for: {reason} (Duration: {parsed_time})", delete_message_seconds=delete_messages_seconds) + await ctx.guild.ban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason} (Duration: {parsed_time})", delete_message_seconds=delete_messages_seconds) moderation = await Moderation.log( bot, ctx.guild.id, @@ -161,3 +244,101 @@ class Tempban(Ban): await log(ctx, moderation.id) await send_evidenceformat(ctx, moderation.id) return cls + +@type_registry.register(key="unban") +class Unban(Type): + key="unban" + string="unban" + verb="unbanned" + + @classmethod + async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None) -> 'Unban': + """Unban a user.""" + bot = ctx.bot + try: + await ctx.guild.fetch_ban(target) + except NotFound: + await ctx.send(content=error(f"{target.mention} is not {Ban.verb}!"), ephemeral=True) + return + + response_message = await ctx.send(f"{target.mention} has been {cls.verb}!\n{bold('Reason:')} {inline(reason)}") + + if silent is False: + try: + embed = await message_factory( + bot, + await bot.get_embed_color(ctx.channel), + ctx.guild, + reason, + cls(), + ctx.author, + None, + response_message + ) + await target.send(embed=embed, file=get_icon(bot)) + except HTTPException: + pass + + await ctx.guild.unban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}") + moderation = await Moderation.log( + bot, + ctx.guild.id, + ctx.author.id, + cls(), + 'user', + target.id, + None, + None, + reason + ) + await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") + await log(ctx, moderation.id) + await send_evidenceformat(ctx, moderation.id) + return cls + +@type_registry.register(key="slowmode") +class Slowmode(Type): + key="slowmode" + string="slowmode" + verb="set the slowmode in" + channel=True + + @classmethod + async def handler(cls, ctx: commands.Context, target: Messageable, silent: bool, duration: str, reason: str) -> 'Slowmode': # pylint: disable=unused-argument + """Set the slowmode in a channel.""" + bot = ctx.bot + parsed_time = parse_relativedelta(duration) + if not parsed_time: + await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) + try: + parsed_time = timedelta_from_relativedelta(parsed_time) + except ValueError: + await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) + + if ceil(parsed_time.total_seconds()) > 21600: + await ctx.send(content=error("The slowmode duration cannot exceed 6 hours!"), ephemeral=True) + return + + if isinstance(target, TextChannel): + await target.edit(slowmode_delay=ceil(parsed_time.total_seconds())) + moderation = await Moderation.log( + bot, + ctx.guild.id, + ctx.author.id, + cls(), + 'channel', + target.id, + None, + parsed_time, + None + ) + await ctx.send(f"{ctx.author.mention} has {cls.verb} {target.mention} to {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}") + await log(ctx, moderation.id) + return cls + +@type_registry.register(key="lockdown") +class Lockdown(Type): + key="lockdown" + string="lockdown" + verb="locked down" + channel=True diff --git a/aurora/models/type.py b/aurora/models/type.py index 11a0eae..92e734b 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -2,6 +2,7 @@ from typing import Any from discord import Guild, Member, User +from discord.abc import Messageable from redbot.core import commands from redbot.core.bot import Red @@ -12,23 +13,24 @@ class Type(object): string = "type" verb = "typed" embed_desc = "been" + channel = False # if this is True, the overridden handler methods should be typed with `discord.abc.Messageable` instead of `discord.Member | discord.User` def __str__(self) -> str: return self.string @classmethod - async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, **kwargs) -> 'Type': # pylint: disable=unused-argument + async def handler(cls, ctx: commands.Context, target: Member | User | Messageable, silent: bool, **kwargs) -> 'Type': # pylint: disable=unused-argument """This method should be overridden by any child classes, but should retain the same starting keyword arguments.""" raise NotImplementedError @classmethod - async def resolve_handler(cls, bot: Red, guild: Guild, target: Member | User, reason: str | None = None) -> Any: # pylint: disable=unused-argument + async def resolve_handler(cls, bot: Red, guild: Guild, target: Member | User | Messageable, reason: str | None = None, **kwargs) -> Any: # pylint: disable=unused-argument """This method should be overridden by any resolvable child classes, but should retain the same keyword arguments. If your moderation type should not be resolvable, do not override this.""" raise NotImplementedError @classmethod - async def expiry_handler(cls, bot: Red, guild: Guild, target: Member | User) -> Any: # pylint: disable=unused-argument + async def expiry_handler(cls, bot: Red, guild: Guild, target: Member | User | Messageable, **kwargs) -> Any: # pylint: disable=unused-argument """This method should be overridden by any expirable child classes, but should retain the same keyword arguments. If your moderation type should not expire, do not override this.""" raise NotImplementedError diff --git a/aurora/utilities/moderate.py b/aurora/utilities/moderate.py index b0f6ca1..05fc245 100644 --- a/aurora/utilities/moderate.py +++ b/aurora/utilities/moderate.py @@ -9,14 +9,14 @@ from .registry import type_registry from .utils import check_moddable -async def moderate(ctx: Union[commands.Context, discord.Interaction], target: discord.Member, silent: bool | None, permissions: List[str], moderation_type: Type | str, **kwargs) -> None | Type: +async def moderate(ctx: Union[commands.Context, discord.Interaction], target: discord.Member | discord.User | discord.abc.Messageable, silent: bool | None, permissions: List[str], moderation_type: Type | str, **kwargs) -> None | Type: """This function is used to moderate users. It checks if the target can be moderated, then calls the handler method of the moderation type specified. Args: bot (Red): The bot instance. ctx (Union[commands.Context, discord.Interaction]): The context of the command. If this is a `discord.Interaction` object, it will be converted to a `commands.Context` object. Additionally, if the interaction orignated from a context menu, the `ctx.author` attribute will be overriden to `interaction.user`. - target (discord.Member): The target user to moderate. + target (discord.Member, discord.User, discord.abc.Messageable): The target user or channel to moderate. silent (bool | None): Whether to send the moderation action to the target. permissions (List[str]): The permissions required to moderate the target. moderation_type (Type): The moderation type (handler) to use. See `aurora.models.moderation_types` for some examples. -- 2.45.3 From 37bae2eeb3ad94d900eb5d802553f54b07bc70a3 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 13:10:09 -0400 Subject: [PATCH 216/376] fix(aurora): add a softban type --- aurora/models/moderation_types.py | 57 +++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index db36dd0..c895ff0 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -245,6 +245,63 @@ class Tempban(Ban): await send_evidenceformat(ctx, moderation.id) return cls +@type_registry.register(key="softban") +class Softban(Type): + key="softban" + string="softban" + verb="softbanned" + + @classmethod + async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Softban': + """Softban a user.""" + bot = ctx.bot + try: + await ctx.guild.fetch_ban(target) + await ctx.send(content=error(f"{target.mention} is already {Ban.verb}!"), ephemeral=True) + except NotFound: + pass + + if delete_messages is None: + delete_messages_seconds = 0 + else: + delete_messages_seconds = delete_messages.value + + response_message = await ctx.send(f"{target.mention} has been {cls.verb}!\n{bold('Reason:')} {inline(reason)}") + + if silent is False: + try: + embed = await message_factory( + bot, + await bot.get_embed_color(ctx.channel), + ctx.guild, + reason, + cls(), + ctx.author, + None, + response_message + ) + await target.send(embed=embed, file=get_icon(bot)) + except HTTPException: + pass + + await ctx.guild.ban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}", delete_message_seconds=delete_messages_seconds) + await ctx.guild.unban(target, reason=f"Softban by {ctx.author.id} for: {reason}") + moderation = await Moderation.log( + bot, + ctx.guild.id, + ctx.author.id, + cls(), + 'user', + target.id, + None, + None, + reason + ) + await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") + await log(ctx, moderation.id) + await send_evidenceformat(ctx, moderation.id) + return cls + @type_registry.register(key="unban") class Unban(Type): key="unban" -- 2.45.3 From aae4370868b034f9bf26cecfaa631deed13f7c7c Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 13:10:47 -0400 Subject: [PATCH 217/376] misc(aurora): fixed an incorrect string --- aurora/models/moderation_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index c895ff0..f214a39 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -285,7 +285,7 @@ class Softban(Type): pass await ctx.guild.ban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}", delete_message_seconds=delete_messages_seconds) - await ctx.guild.unban(target, reason=f"Softban by {ctx.author.id} for: {reason}") + await ctx.guild.unban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}") moderation = await Moderation.log( bot, ctx.guild.id, -- 2.45.3 From 13874dd4f04a4365823da596fdc718f5c468ef49 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 13:12:47 -0400 Subject: [PATCH 218/376] fix(aurora): add a debug logging statement --- aurora/models/moderation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index c501398..db88998 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -198,6 +198,8 @@ class Moderation(AuroraGuildModel): moderation_type = str.lower(result[2]) if moderation_type in type_registry: moderation_type = type_registry[moderation_type] + else: + logger.error("Unknown moderation type in case %s: %s", result[0], result[2]) case = { "moderation_id": int(result[0]), -- 2.45.3 From 6d0d79c6c71c98ac7d676721334197d5fd737dd4 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 13:15:06 -0400 Subject: [PATCH 219/376] fix(aurora): properly skip over case 0 --- aurora/models/moderation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index db88998..1e3089d 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -259,9 +259,10 @@ class Moderation(AuroraGuildModel): if results and return_obj and bot and guild_id: cases = [] for result in results: + if result[0] == 0: + continue case = cls.from_result(bot=bot, result=result, guild_id=guild_id) - if case.moderation_id != 0: - cases.append(case) + cases.append(case) return tuple(cases) return results -- 2.45.3 From 9f747a77ca78cf92fc685661929957bfe9a03a55 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 13:16:53 -0400 Subject: [PATCH 220/376] fix(aurora): fixed a history call to `Moderation.type` that was causing a TypeError --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 6b970bb..e0bf488 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1058,7 +1058,7 @@ class Aurora(commands.Cog): }) moderator = memory_dict[str(mod.moderator_id)] - field_name = f"Case #{mod.id:,} ({str.title(mod.type)})" + field_name = f"Case #{mod.id:,} ({mod.type.string.title()})" field_value = f"**Target:** `{target.name}` ({target.id})\n**Moderator:** `{moderator.name}` ({moderator.id})" if len(str(mod.reason)) > 125: -- 2.45.3 From ec32e19b8b6ab0da3c2d9bfb493fefe69e66d473 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 13:24:44 -0400 Subject: [PATCH 221/376] fix(aurora): pass a Type instead of a string --- aurora/importers/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 0e1c7a9..087e264 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -48,7 +48,7 @@ class ImportAuroraView(ui.View): if case["moderation_id"] == 0: continue - moderation_type: Type = type_registry[str.lower(case["moderation_type"])] + moderation_type: Type = type_registry[case["moderation_type"].lower()] if "target_type" not in case or not case["target_type"]: if moderation_type.channel: case["target_type"] = "channel" @@ -92,7 +92,7 @@ class ImportAuroraView(ui.View): bot=interaction.client, guild_id=self.ctx.guild.id, moderator_id=case["moderator_id"], - moderation_type=moderation_type.key, + moderation_type=moderation_type, target_type=case["target_type"].lower(), target_id=case["target_id"], role_id=case["role_id"], -- 2.45.3 From 9faf1b027c5ead94a43540f0f127facf6408314d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 13:39:01 -0400 Subject: [PATCH 222/376] misc(aurora): typehints --- aurora/models/moderation_types.py | 204 +++++++++++++++--------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index f214a39..66ed9e8 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -73,14 +73,14 @@ class Kick(Type): if silent is False: try: embed = await message_factory( - bot, - await bot.get_embed_color(ctx.channel), - ctx.guild, - reason, - cls(), - ctx.author, - None, - response_message + bot=bot, + color=await bot.get_embed_color(ctx.channel), + guild=ctx.guild, + reason=reason, + moderation_type=cls(), + moderator=ctx.author, + duration=None, + response=response_message ) await target.send(embed=embed, file=get_icon(bot)) except HTTPException: @@ -88,15 +88,15 @@ class Kick(Type): await target.kick(reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}") moderation = await Moderation.log( - bot, - ctx.guild.id, - ctx.author.id, - cls(), - 'user', - target.id, - None, - None, - reason + bot=bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type='user', + target_id=target.id, + role_id=None, + duration=None, + reason=reason ) await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") await log(ctx, moderation.id) @@ -128,14 +128,14 @@ class Ban(Type): if silent is False: try: embed = await message_factory( - bot, - await bot.get_embed_color(ctx.channel), - ctx.guild, - reason, - cls(), - ctx.author, - None, - response_message + bot=bot, + color=await bot.get_embed_color(ctx.channel), + guild=ctx.guild, + reason=reason, + moderation_type=cls(), + moderator=ctx.author, + duration=None, + response=response_message ) await target.send(embed=embed, file=get_icon(bot)) except HTTPException: @@ -143,15 +143,15 @@ class Ban(Type): await ctx.guild.ban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}", delete_message_seconds=delete_messages_seconds) moderation = await Moderation.log( - bot, - ctx.guild.id, - ctx.author.id, - cls(), - 'user', - target.id, - None, - None, - reason + bot=bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type='user', + target_id=target.id, + role_id=None, + duration=None, + reason=reason ) await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") await log(ctx, moderation.id) @@ -168,14 +168,14 @@ class Ban(Type): try: embed = await message_factory( - bot, - await bot.get_embed_color(guild.channels[0]), - guild, - reason, - 'unban', - None, - None, - None + bot=bot, + color=await bot.get_embed_color(guild.channels[0]), + guild=guild, + reason=reason, + moderation_type=Unban(), + moderator=None, + duration=None, + response=None ) await target.send(embed=embed, file=get_icon(bot)) except HTTPException: @@ -215,14 +215,14 @@ class Tempban(Ban): if silent is False: try: embed = await message_factory( - bot, - await bot.get_embed_color(ctx.channel), - ctx.guild, - reason, - cls(), - ctx.author, - parsed_time, - response_message + bot=bot, + color=await bot.get_embed_color(ctx.channel), + guild=ctx.guild, + reason=reason, + moderation_type=cls(), + moderator=ctx.author, + duration=parsed_time, + response=response_message ) await target.send(embed=embed, file=get_icon(bot)) except HTTPException: @@ -230,15 +230,15 @@ class Tempban(Ban): await ctx.guild.ban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason} (Duration: {parsed_time})", delete_message_seconds=delete_messages_seconds) moderation = await Moderation.log( - bot, - ctx.guild.id, - ctx.author.id, - cls(), - 'user', - target.id, - None, - parsed_time, - reason + bot=bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type='user', + target_id=target.id, + role_id=None, + duration=parsed_time, + reason=reason ) await response_message.edit(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") await log(ctx, moderation.id) @@ -271,14 +271,14 @@ class Softban(Type): if silent is False: try: embed = await message_factory( - bot, - await bot.get_embed_color(ctx.channel), - ctx.guild, - reason, - cls(), - ctx.author, - None, - response_message + bot=bot, + color=await bot.get_embed_color(ctx.channel), + guild=ctx.guild, + reason=reason, + moderation_type=cls(), + moderator=ctx.author, + duration=None, + response=response_message ) await target.send(embed=embed, file=get_icon(bot)) except HTTPException: @@ -287,15 +287,15 @@ class Softban(Type): await ctx.guild.ban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}", delete_message_seconds=delete_messages_seconds) await ctx.guild.unban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}") moderation = await Moderation.log( - bot, - ctx.guild.id, - ctx.author.id, - cls(), - 'user', - target.id, - None, - None, - reason + bot=bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type='user', + target_id=target.id, + role_id=None, + duration=None, + reason=reason ) await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") await log(ctx, moderation.id) @@ -323,14 +323,14 @@ class Unban(Type): if silent is False: try: embed = await message_factory( - bot, - await bot.get_embed_color(ctx.channel), - ctx.guild, - reason, - cls(), - ctx.author, - None, - response_message + bot=bot, + color=await bot.get_embed_color(ctx.channel), + guild=ctx.guild, + reason=reason, + moderation_type=cls(), + moderator=ctx.author, + duration=None, + response=response_message ) await target.send(embed=embed, file=get_icon(bot)) except HTTPException: @@ -338,15 +338,15 @@ class Unban(Type): await ctx.guild.unban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}") moderation = await Moderation.log( - bot, - ctx.guild.id, - ctx.author.id, - cls(), - 'user', - target.id, - None, - None, - reason + bot=bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type='user', + target_id=target.id, + role_id=None, + duration=None, + reason=reason ) await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") await log(ctx, moderation.id) @@ -379,15 +379,15 @@ class Slowmode(Type): if isinstance(target, TextChannel): await target.edit(slowmode_delay=ceil(parsed_time.total_seconds())) moderation = await Moderation.log( - bot, - ctx.guild.id, - ctx.author.id, - cls(), - 'channel', - target.id, - None, - parsed_time, - None + bot=bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type='channel', + target_id=target.id, + role_id=None, + duration=parsed_time, + reason=None ) await ctx.send(f"{ctx.author.mention} has {cls.verb} {target.mention} to {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}") await log(ctx, moderation.id) -- 2.45.3 From 461fbf83eef32abfe988b864d83d9764573380a1 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 14:23:56 -0400 Subject: [PATCH 223/376] fix(aurora): use phx-class-registry instead of class-registry --- aurora/info.json | 2 +- poetry.lock | 32 +++++++++++++++++--------------- pyproject.toml | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/aurora/info.json b/aurora/info.json index 092b491..00d919d 100644 --- a/aurora/info.json +++ b/aurora/info.json @@ -9,7 +9,7 @@ "disabled": false, "min_bot_version": "3.5.0", "min_python_version": [3, 10, 0], - "requirements": ["pydantic", "aiosqlite", "class-registry"], + "requirements": ["pydantic", "aiosqlite", "phx-class-registry"], "tags": [ "mod", "moderate", diff --git a/poetry.lock b/poetry.lock index 4474ce9..373a6f5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -599,20 +599,6 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] -[[package]] -name = "class-registry" -version = "2.1.2" -description = "Factory+Registry pattern for Python classes." -optional = false -python-versions = "*" -files = [ - {file = "class-registry-2.1.2.tar.gz", hash = "sha256:678bdb0322566c07a4d8905140d364bd34a73baf46bf7580fc2e06fa994d4e7e"}, - {file = "class_registry-2.1.2-py2.py3-none-any.whl", hash = "sha256:cfb855514753e2edfe8d88b14a6e449820682fe0983efe61b83df28b688b3e5a"}, -] - -[package.dependencies] -six = "*" - [[package]] name = "click" version = "8.1.7" @@ -1502,6 +1488,22 @@ files = [ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] +[[package]] +name = "phx-class-registry" +version = "4.1.0" +description = "Factory+Registry pattern for Python classes" +optional = false +python-versions = ">=3.10" +files = [ + {file = "phx-class-registry-4.1.0.tar.gz", hash = "sha256:6a7fe8568f9000ad1f90c9a81c5cb65ec20ee3b89b2aaab7a67e14dbb67e11d1"}, + {file = "phx_class_registry-4.1.0-py3-none-any.whl", hash = "sha256:1cad15897473d5bcd2ed7640423e68b7fa20745e4e25c0457f5474afa50bc8bb"}, +] + +[package.extras] +build-system = ["build", "twine"] +docs-builder = ["sphinx", "sphinx-rtd-theme"] +test-runner = ["tox"] + [[package]] name = "pillow" version = "10.3.0" @@ -2688,4 +2690,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "bf7dd1ef2ebf8aedeb3295201cf04b53e5cd04cca488fd1e7e0257cbe9597513" +content-hash = "6d09969e0ad7adff5aa105915c5c9e0354b4b7aceb80b9c2b3fb800bb08f21d4" diff --git a/pyproject.toml b/pyproject.toml index 68f5ea3..39c6670 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ colorthief = "^0.2.1" beautifulsoup4 = "^4.12.3" markdownify = "^0.12.1" aiosqlite = "^0.20.0" -class-registry = "^2.1.2" +phx-class-registry = "^4.1.0" [tool.poetry.group.dev] optional = true -- 2.45.3 From 9d0f2e38879c95de6a3f1b65360f560a12d71e94 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 6 Jul 2024 18:58:04 -0400 Subject: [PATCH 224/376] misc(aurora): send evidenceformat to dms if `send_evidenceformat` is called outside of an Interaction context, as epheremal messages would be disabled in this case --- aurora/utilities/utils.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 1445537..467d66f 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -145,12 +145,13 @@ async def send_evidenceformat(ctx: commands.Context, moderation_id: int) -> None or await config.guild(guild=ctx.guild).auto_evidenceformat() or False ) - if send_evidence_bool is False: - return - - moderation = await Moderation.find_by_id(ctx.bot, moderation_id, ctx.guild.id) - content = await evidenceformat_factory(moderation=moderation) - await ctx.send(content=content, ephemeral=True) + if send_evidence_bool is True: + moderation = await Moderation.find_by_id(ctx.bot, moderation_id, ctx.guild.id) + content = await evidenceformat_factory(moderation=moderation) + if not ctx.interaction: + await ctx.author.send(content=content) + else: + await ctx.send(content=content, ephemeral=True) def get_bool_emoji(value: Optional[bool]) -> str: -- 2.45.3 From e2b0fc999a0d53c2e3afceb1a51e12ff40f7ca0a Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 15:22:24 -0400 Subject: [PATCH 225/376] feat(aurora): finishing up moderation handlers --- aurora/aurora.py | 736 +++++------------------------- aurora/importers/aurora.py | 3 +- aurora/models/__init__.py | 2 + aurora/models/moderation.py | 121 ++++- aurora/models/moderation_types.py | 723 +++++++++++++++++++++++++++-- aurora/models/type.py | 74 ++- aurora/utilities/factory.py | 50 +- aurora/utilities/moderate.py | 3 +- aurora/utilities/registry.py | 3 - 9 files changed, 995 insertions(+), 720 deletions(-) delete mode 100644 aurora/utilities/registry.py diff --git a/aurora/aurora.py b/aurora/aurora.py index e0bf488..1e7fb11 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -13,7 +13,6 @@ from datetime import datetime, timedelta, timezone from math import ceil import discord -from discord import Object from discord.ext import tasks from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice @@ -29,14 +28,13 @@ from .menus.immune import Immune from .menus.overrides import Overrides from .models.change import Change from .models.moderation import Moderation -from .models.moderation_types import Ban, Tempban +from .models.type import type_registry from .utilities.config import config, register_config -from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed +from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, overrides_embed from .utilities.json import dump from .utilities.logger import logger from .utilities.moderate import moderate -from .utilities.registry import type_registry -from .utilities.utils import check_moddable, check_permissions, create_guild_table, get_footer_image, log, send_evidenceformat +from .utilities.utils import check_permissions, create_guild_table, log class Aurora(commands.Cog): @@ -209,47 +207,15 @@ class Aurora(commands.Cog): Why are you noting this user? silent: bool Should the user be messaged?""" - if not await check_moddable(target, interaction, ["moderate_members"]): - return - - await interaction.response.send_message( - content=f"{target.mention} has recieved a note!\n**Reason** - `{reason}`" + await moderate( + ctx=interaction, + target=target, + silent=silent, + permissions=["moderate_members"], + moderation_type=type_registry['note'], + reason=reason, ) - if silent is None: - silent = not await config.guild(interaction.guild).dm_users() - if silent is False: - try: - embed = await message_factory( - bot=interaction.client, - color=await self.bot.get_embed_color(interaction.channel), - guild=interaction.guild, - moderator=interaction.user, - reason=reason, - moderation_type="note", - response=await interaction.original_response(), - ) - await target.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "NOTE", - "USER", - target.id, - None, - None, - reason, - ) - await interaction.edit_original_response( - content=f"{target.mention} has received a note! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" - ) - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) - @app_commands.command(name="warn") async def warn( self, @@ -268,47 +234,15 @@ class Aurora(commands.Cog): Why are you warning this user? silent: bool Should the user be messaged?""" - if not await check_moddable(target, interaction, ["moderate_members"]): - return - - await interaction.response.send_message( - content=f"{target.mention} has been warned!\n**Reason** - `{reason}`" + await moderate( + ctx=interaction, + target=target, + silent=silent, + permissions=["moderate_members"], + moderation_type=type_registry['warn'], + reason=reason, ) - if silent is None: - silent = not await config.guild(interaction.guild).dm_users() - if silent is False: - try: - embed = await message_factory( - bot=interaction.client, - color=await self.bot.get_embed_color(interaction.channel), - guild=interaction.guild, - moderator=interaction.user, - reason=reason, - moderation_type="warned", - response=await interaction.original_response(), - ) - await target.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "WARN", - "USER", - target.id, - None, - None, - reason, - ) - await interaction.edit_original_response( - content=f"{target.mention} has been warned! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" - ) - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) - @app_commands.command(name="addrole") async def addrole( self, @@ -333,87 +267,16 @@ class Aurora(commands.Cog): How long are you adding this role for? silent: bool Should the user be messaged?""" - addrole_whitelist = await config.guild(interaction.guild).addrole_whitelist() - - if not addrole_whitelist: - await interaction.response.send_message( - content=error("There are no whitelisted roles set for this server!"), - ephemeral=True, - ) - return - - if duration is not None: - parsed_time = parse_timedelta(duration) - if parsed_time is None: - await interaction.response.send_message( - content=error("Please provide a valid duration!"), ephemeral=True - ) - return - else: - parsed_time = None - - if role.id not in addrole_whitelist: - await interaction.response.send_message( - content=error("That role isn't whitelisted!"), ephemeral=True - ) - return - - if not await check_moddable( - target, interaction, ["moderate_members", "manage_roles"] - ): - return - - if role.id in [user_role.id for user_role in target.roles]: - await interaction.response.send_message( - content=error(f"{target.mention} already has this role!"), - ephemeral=True, - ) - return - - await interaction.response.defer() - if silent is None: - silent = not await config.guild(interaction.guild).dm_users() - if silent is False: - try: - embed = await message_factory( - bot=interaction.client, - color=await self.bot.get_embed_color(interaction.channel), - guild=interaction.guild, - moderator=interaction.user, - reason=reason, - moderation_type="addrole", - response=await interaction.original_response(), - duration=parsed_time, - role=role, - ) - await target.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - await target.add_roles( - role, - reason=f"Role added by {interaction.user.id}{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''} for: {reason}", + await moderate( + ctx=interaction, + target=target, + silent=silent, + permissions=["moderate_members", "manage_roles"], + moderation_type=type_registry['addrole'], + reason=reason, + role=role, + duration=duration ) - response: discord.WebhookMessage = await interaction.followup.send( - content=f"{target.mention} has been given the {role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" - ) - - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "ADDROLE", - "USER", - target.id, - role.id, - parsed_time, - reason, - ) - await response.edit( - content=f"{target.mention} has been given the {role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`", - ) - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="removerole") async def removerole( @@ -439,87 +302,16 @@ class Aurora(commands.Cog): How long are you removing this role for? silent: bool Should the user be messaged?""" - addrole_whitelist = await config.guild(interaction.guild).addrole_whitelist() - - if not addrole_whitelist: - await interaction.response.send_message( - content=error("There are no whitelisted roles set for this server!"), - ephemeral=True, - ) - return - - if duration is not None: - parsed_time = parse_timedelta(duration) - if parsed_time is None: - await interaction.response.send_message( - content=error("Please provide a valid duration!"), ephemeral=True - ) - return - else: - parsed_time = None - - if role.id not in addrole_whitelist: - await interaction.response.send_message( - content=error("That role isn't whitelisted!"), ephemeral=True - ) - return - - if not await check_moddable( - target, interaction, ["moderate_members", "manage_roles"] - ): - return - - if role.id not in [user_role.id for user_role in target.roles]: - await interaction.response.send_message( - content=error(f"{target.mention} does not have this role!"), - ephemeral=True, - ) - return - - await interaction.response.defer() - if silent is None: - silent = not await config.guild(interaction.guild).dm_users() - if silent is False: - try: - embed = await message_factory( - bot=interaction.client, - color=await self.bot.get_embed_color(interaction.channel), - guild=interaction.guild, - moderator=interaction.user, - reason=reason, - moderation_type="removerole", - response=await interaction.original_response(), - duration=parsed_time, - role=role, - ) - await target.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - await target.remove_roles( - role, - reason=f"Role removed by {interaction.user.id}{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''} for: {reason}", + await moderate( + ctx=interaction, + target=target, + silent=silent, + permissions=["moderate_members", "manage_roles"], + moderation_type=type_registry['removerole'], + reason=reason, + role=role, + duration=duration ) - response: discord.WebhookMessage = await interaction.followup.send( - content=f"{target.mention} has had the {role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" - ) - - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "REMOVEROLE", - "USER", - target.id, - role.id, - parsed_time, - reason, - ) - await response.edit( - content=f"{target.mention} has had the {role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`", - ) - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="mute") async def mute( @@ -542,73 +334,16 @@ class Aurora(commands.Cog): Why are you unbanning this user? silent: bool Should the user be messaged?""" - if not await check_moddable(target, interaction, ["moderate_members"]): - return - - if target.is_timed_out() is True: - await interaction.response.send_message( - error(f"{target.mention} is already muted!"), - allowed_mentions=discord.AllowedMentions(users=False), - ephemeral=True, - ) - return - - try: - parsed_time = parse_timedelta(duration, maximum=timedelta(days=28)) - if parsed_time is None: - await interaction.response.send_message( - error("Please provide a valid duration!"), ephemeral=True - ) - return - except commands.BadArgument: - await interaction.response.send_message( - error("Please provide a duration that is less than 28 days."), ephemeral=True - ) - return - - await target.timeout( - parsed_time, reason=f"Muted by {interaction.user.id} for: {reason}" + await moderate( + ctx=interaction, + target=target, + silent=silent, + permissions=["moderate_members"], + moderation_type=type_registry['mute'], + duration=duration, + reason=reason, ) - await interaction.response.send_message( - content=f"{target.mention} has been muted for {humanize_timedelta(timedelta=parsed_time)}!\n**Reason** - `{reason}`" - ) - - if silent is None: - silent = not await config.guild(interaction.guild).dm_users() - if silent is False: - try: - embed = await message_factory( - bot=interaction.client, - color=await self.bot.get_embed_color(interaction.channel), - guild=interaction.guild, - moderator=interaction.user, - reason=reason, - moderation_type="muted", - response=await interaction.original_response(), - duration=parsed_time, - ) - await target.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "MUTE", - "USER", - target.id, - None, - parsed_time, - reason, - ) - await interaction.edit_original_response( - content=f"{target.mention} has been muted for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" - ) - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) - @app_commands.command(name="unmute") async def unmute( self, @@ -627,63 +362,15 @@ class Aurora(commands.Cog): Why are you unmuting this user? silent: bool Should the user be messaged?""" - if not await check_moddable(target, interaction, ["moderate_members"]): - return - - if target.is_timed_out() is False: - await interaction.response.send_message( - error(f"{target.mention} is not muted!"), - allowed_mentions=discord.AllowedMentions(users=False), - ephemeral=True, - ) - return - - if reason: - await target.timeout( - None, reason=f"Unmuted by {interaction.user.id} for: {reason}" - ) - else: - await target.timeout(None, reason=f"Unbanned by {interaction.user.id}") - reason = "No reason given." - - await interaction.response.send_message( - content=f"{target.mention} has been unmuted!\n**Reason** - `{reason}`" + await moderate( + ctx=interaction, + target=target, + silent=silent, + permissions=["moderate_members"], + moderation_type=type_registry['unmute'], + reason=reason, ) - if silent is None: - silent = not await config.guild(interaction.guild).dm_users() - if silent is False: - try: - embed = await message_factory( - bot=interaction.client, - color=await self.bot.get_embed_color(interaction.channel), - guild=interaction.guild, - moderator=interaction.user, - reason=reason, - moderation_type="unmuted", - response=await interaction.original_response(), - ) - await target.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "UNMUTE", - "USER", - target.id, - None, - None, - reason, - ) - await interaction.edit_original_response( - content=f"{target.mention} has been unmuted! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" - ) - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) - @app_commands.command(name="kick") async def kick( self, @@ -702,49 +389,15 @@ class Aurora(commands.Cog): Why are you kicking this user? silent: bool Should the user be messaged?""" - if not await check_moddable(target, interaction, ["kick_members"]): - return - - await interaction.response.send_message( - content=f"{target.mention} has been kicked!\n**Reason** - `{reason}`" + await moderate( + ctx=interaction, + target=target, + silent=silent, + permissions=["kick_members"], + moderation_type=type_registry['kick'], + reason=reason, ) - if silent is None: - silent = not await config.guild(interaction.guild).dm_users() - if silent is False: - try: - embed = await message_factory( - bot=interaction.client, - color=await self.bot.get_embed_color(interaction.channel), - guild=interaction.guild, - moderator=interaction.user, - reason=reason, - moderation_type="kicked", - response=await interaction.original_response(), - ) - await target.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - await target.kick(reason=f"Kicked by {interaction.user.id} for: {reason}") - - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "KICK", - "USER", - target.id, - None, - None, - reason, - ) - await interaction.edit_original_response( - content=f"{target.mention} has been kicked! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" - ) - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) - @app_commands.command(name="ban") @app_commands.choices( delete_messages=[ @@ -781,22 +434,22 @@ class Aurora(commands.Cog): Should the user be messaged?""" if duration: await moderate( - interaction, - target, - silent, - ["ban_members"], - Tempban, + ctx=interaction, + target=target, + silent=silent, + permissions=["ban_members"], + moderation_type=type_registry['tempban'], reason=reason, duration=duration, delete_messages=delete_messages, ) else: await moderate( - interaction, - target, - silent, - ["ban_members"], - Ban, + ctx=interaction, + target=target, + silent=silent, + permissions=["ban_members"], + moderation_type=type_registry['ban'], reason=reason, delete_messages=delete_messages, ) @@ -819,65 +472,15 @@ class Aurora(commands.Cog): Why are you unbanning this user? silent: bool Should the user be messaged?""" - if not await check_moddable(target, interaction, ["ban_members"]): - return - - try: - await interaction.guild.fetch_ban(target) - except discord.errors.NotFound: - await interaction.response.send_message( - content=error(f"{target.mention} is not banned!"), ephemeral=True - ) - return - - if reason: - await interaction.guild.unban( - target, reason=f"Unbanned by {interaction.user.id} for: {reason}" - ) - else: - await interaction.guild.unban( - target, reason=f"Unbanned by {interaction.user.id}" - ) - reason = "No reason given." - - await interaction.response.send_message( - content=f"{target.mention} has been unbanned!\n**Reason** - `{reason}`" + await moderate( + ctx=interaction, + target=target, + silent=silent, + permissions=["ban_members"], + moderation_type=type_registry['unban'], + reason=reason, ) - if silent is None: - silent = not await config.guild(interaction.guild).dm_users() - if silent is False: - try: - embed = await message_factory( - bot=interaction.client, - color=await self.bot.get_embed_color(interaction.channel), - guild=interaction.guild, - moderator=interaction.user, - reason=reason, - moderation_type="unbanned", - response=await interaction.original_response(), - ) - await target.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "UNBAN", - "USER", - target.id, - None, - None, - reason, - ) - await interaction.edit_original_response( - content=f"{target.mention} has been unbanned! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" - ) - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) - @app_commands.command(name="slowmode") async def slowmode( self, @@ -899,27 +502,15 @@ class Aurora(commands.Cog): if channel is None: channel = interaction.channel - if not await check_moddable(channel, interaction, ["manage_channels"]): - return - - await channel.edit(slowmode_delay=interval) - await interaction.response.send_message(f"Slowmode in {channel.mention} has been set to {interval} seconds!\n**Reason** - `{reason}`") - - moderation = await Moderation.log( - interaction.client, - interaction.guild.id, - interaction.user.id, - "SLOWMODE", - "CHANNEL", - channel.id, - None, - None, - reason, - metadata={"interval": f"{interval} seconds"} + await moderate( + ctx=interaction, + target=channel, + silent=True, + permissions=["manage_channel"], + moderation_type=type_registry['slowmode'], + interval=interval, + reason=reason, ) - await interaction.edit_original_response(content=f"Slowmode in {channel.mention} has been set to {interval} seconds! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`") - await log(interaction, moderation.id) - await send_evidenceformat(interaction, moderation.id) @app_commands.command(name="history") async def history( @@ -1132,7 +723,7 @@ class Aurora(commands.Cog): return try: - await moderation.resolve(interaction.user.id, reason) + success, msg = await moderation.resolve(interaction.user.id, reason) except (ValueError, TypeError) as e: if e == ValueError: await interaction.response.send_message( @@ -1148,9 +739,10 @@ class Aurora(commands.Cog): moderation=moderation, ) await interaction.response.send_message( - content=f"✅ Moderation #{case:,} resolved!", embed=embed + content=f"✅ Moderation #{case:,} resolved!\n" + error(f"Resolve handler returned an error message: `{msg}`") if success is False else "", embed=embed ) - await log(interaction, case, resolved=True) + ctx = await self.bot.get_context(interaction, cls=commands.Context) + await log(ctx=ctx, moderation_id=case, resolved=True) @app_commands.command(name="case") @app_commands.choices( @@ -1320,27 +912,14 @@ class Aurora(commands.Cog): moderation.end_timestamp = moderation.timestamp + moderation.duration.total_seconds() - if moderation.type == "MUTE": - if ( - time.time() - moderation.unix_timestamp - ) + moderation.duration.total_seconds() > 2419200: - return await interaction.response.send_message( - error( - "Please provide a duration that is less than 28 days from the initial moderation." - ) - ) - - try: - member = await interaction.guild.fetch_member( - moderation.target_id - ) - - await member.timeout( - moderation.duration, - reason=f"Case #{case:,} edited by {interaction.user.id}", - ) - except discord.NotFound: - pass + try: + success = await moderation.type.duration_edit_handler(interaction=interaction.client, old_moderation=old_moderation, new_moderation=moderation) + except NotImplementedError: + return await interaction.response.send_message( + error("This case type does not support duration editing!"), ephemeral=True + ) + if not success: + return if reason: moderation.reason = reason @@ -1392,147 +971,64 @@ class Aurora(commands.Cog): global_unban_num = 0 global_addrole_num = 0 global_removerole_num = 0 + global_other_num = 0 guilds: list[discord.Guild] = self.bot.guilds for guild in guilds: if not await self.bot.cog_disabled_in_guild(self, guild): time_per_guild = time.time() - tempban_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL AND end_timestamp <= ? AND moderation_type = 'TEMPBAN' AND expired = 0" - tempbans = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=tempban_query, parameters=(time.time(),)) + query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL AND end_timestamp <= ? AND expired = 0" + moderations = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=query, parameters=(time.time(),)) unban_num = 0 - for moderation in tempbans: - user = self.bot.get_user(moderation.target_id) - if user is None: - try: - user = await self.bot.fetch_user(moderation.target_id) - except discord.errors.NotFound: - continue - name = ( - f"{user.name}#{user.discriminator}" - if user.discriminator != "0" - else user.name - ) - try: - await guild.unban( - user, reason=f"Automatic unban from case #{moderation.id}" - ) - - embed = await message_factory( - bot=self.bot, - color=await self.bot.get_embed_color(guild.channels[0]), - guild=guild, - reason=f"Automatic unban from case #{moderation.id}", - moderation_type="unbanned", - ) - - try: - await user.send(embed=embed, file=get_footer_image(self)) - except discord.errors.HTTPException: - pass - - logger.trace( - "Unbanned %s (%s) from %s (%s)", - name, - user.id, - guild.name, - guild.id, - ) - unban_num += 1 - except ( - discord.errors.NotFound, - discord.errors.Forbidden, - discord.errors.HTTPException, - ) as e: - logger.error( - "Failed to unban %s (%s) from %s (%s)\n%s", - name, - user.id, - guild.name, - guild.id, - e, - ) - removerole_num = 0 - addrole_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL AND end_timestamp <= ? AND moderation_type = 'ADDROLE' AND expired = 0" - addroles = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=addrole_query, parameters=(time.time(),)) - - for moderation in addroles: - try: - member = await guild.fetch_member(moderation.target_id) - - await member.remove_roles( - Object(moderation.role_id), reason=f"Automatic role removal from case #{moderation.id}" - ) - - logger.trace( - "Removed role %s from %s (%s)", - moderation.role_id, - member.name, - member.id, - ) - removerole_num = removerole_num + 1 - except ( - discord.errors.NotFound, - discord.errors.Forbidden, - discord.errors.HTTPException, - ) as e: - logger.error( - "Removing the role %s from user %s failed due to: \n%s", - moderation.role_id, - moderation.target_id, - e, - ) - continue - addrole_num = 0 - removerole_query = f"SELECT * FROM moderation_{guild.id} WHERE end_timestamp IS NOT NULL AND end_timestamp <= ? AND moderation_type = 'REMOVEROLE' AND expired = 0" - removeroles = await Moderation.execute(bot=self.bot, guild_id=guild.id, query=removerole_query, parameters=(time.time(),)) - - for moderation in removeroles: + other_num = 0 + for moderation in moderations: try: - member = await guild.fetch_member(moderation.target_id) - - await member.add_roles( - Object(moderation.role_id), reason=f"Automatic role addition from case #{moderation.id}" - ) - - logger.trace("Added role %s to %s (%s)", moderation.role_id, member.name, member.id) - addrole_num = addrole_num + 1 - except ( - discord.errors.NotFound, - discord.errors.Forbidden, - discord.errors.HTTPException, - ) as e: - logger.error("Adding the role %s to user %s failed due to: \n%s", moderation.role_id, moderation.target_id, e) + num = await moderation.type.expiry_handler(self.bot, guild, moderation) + except NotImplementedError: + logger.warning("Expiry handler not implemented for expirable moderation type %s", moderation.type.key) continue + match moderation.type.key: + case "tempban": + unban_num += num + case "addrole": + removerole_num += num + case "removerole": + addrole_num += num + case _: + other_num += num if isinstance(num, int) else 0 expiry_query = f"UPDATE `moderation_{guild.id}` SET expired = 1 WHERE (end_timestamp IS NOT NULL AND end_timestamp <= ? AND expired = 0) OR (expired = 0 AND resolved = 1);" await Moderation.execute(bot=self.bot, guild_id=guild.id, query=expiry_query, parameters=(time.time(),), return_obj=False) per_guild_completion_time = (time.time() - time_per_guild) * 1000 logger.debug( - "Completed expiry loop for %s (%s) in %sms with %s users unbanned, %s roles added, and %s roles removed", + "Completed expiry loop for %s (%s) in %sms with %s users unbanned, %s roles added, and %s roles removed (%s other cases expired)", guild.name, guild.id, f"{per_guild_completion_time:.6f}", unban_num, addrole_num, removerole_num, + other_num ) global_unban_num = global_unban_num + unban_num global_addrole_num = global_addrole_num + addrole_num global_removerole_num = global_removerole_num + removerole_num + global_other_num = global_other_num + other_num completion_time = (time.time() - current_time) * 1000 logger.debug( - "Completed expiry loop in %sms with %s users unbanned, %s roles added, and %s roles removed", + "Completed expiry loop in %sms with %s users unbanned, %s roles added, and %s roles removed (%s other cases expired)", f"{completion_time:.6f}", global_unban_num, global_addrole_num, global_removerole_num, + global_other_num ) ######################################################################################################################## diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 087e264..9bd4f4b 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -9,9 +9,8 @@ from redbot.core import commands, data_manager from redbot.core.utils.chat_formatting import warning from ..models.moderation import Moderation -from ..models.type import Type +from ..models.type import Type, type_registry from ..utilities.json import dump -from ..utilities.registry import type_registry from ..utilities.utils import create_guild_table, timedelta_from_string diff --git a/aurora/models/__init__.py b/aurora/models/__init__.py index e69de29..f15d56d 100644 --- a/aurora/models/__init__.py +++ b/aurora/models/__init__.py @@ -0,0 +1,2 @@ +from .moderation_types import * # noqa: F403 +# This just imports all the built-in moderation types so they can be registered, as they aren't imported anywhere else. diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 1e3089d..471d133 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -11,15 +11,64 @@ from redbot.core import data_manager from redbot.core.bot import Red from ..utilities.logger import logger -from ..utilities.registry import type_registry from ..utilities.utils import timedelta_to_string from .base import AuroraGuildModel from .change import Change from .partials import PartialChannel, PartialRole, PartialUser -from .type import Type +from .type import Type, type_registry class Moderation(AuroraGuildModel): + """This class represents a moderation case in the database. + + Attributes: + bot (Red): The bot instance. + guild (discord.Guild): The guild the case belongs to. + moderation_id (int): The ID of the moderation case. + timestamp (datetime): The timestamp of the case. + moderation_type (Type): The type of moderation case. + target_type (str): The type of target. Should be either `user` or `channel`. + target_id (int): The ID of the target. + moderator_id (int): The ID of the moderator who issued the case. + role_id (int): The ID of the role, if applicable. + duration (timedelta): The duration of the case, if applicable. + end_timestamp (datetime): The end timestamp of the case, if applicable. + reason (str): The reason for the case. + resolved (bool): Whether the case is resolved. + resolved_by (int): The ID of the user who resolved the case. + resolve_reason (str): The reason the case was resolved. + expired (bool): Whether the case is expired. + changes (List[Change]): A list of changes to the case. + metadata (Dict): A dictionary of metadata stored with the case. + + Properties: + id (int): The ID of the case. + type (Type): The type of the case. + unix_timestamp (int): The timestamp of the case as a Unix timestamp. + + Methods: + get_moderator: Gets the moderator who issued the case. + get_target: Gets the target of the case. + get_resolved_by: Gets the user who resolved the case. + get_role: Gets the role, if applicable. + resolve: Resolves the case. + update: Updates the case in the database. + + Class Methods: + from_dict: Creates a `Moderation` object from a dictionary. + from_result: Creates a `Moderation` object from a database result. + execute: Executes a query on the database. + get_latest: Gets the latest cases from the database. + get_next_case_number: Gets the next case number to use. + find_by_id: Finds a case by its ID. + find_by_target: Finds cases by the target. + find_by_moderator: Finds cases by the moderator. + log: Logs a moderation case in the database. + + Static Methods: + connect: Connects to the SQLite database. + """ + moderation_id: int timestamp: datetime moderation_type: Type @@ -53,7 +102,7 @@ class Moderation(AuroraGuildModel): return await PartialUser.from_id(self.bot, self.moderator_id) async def get_target(self) -> Union["PartialUser", "PartialChannel"]: - if str.lower(self.target_type) == "user": + if self.target_type.lower() == "user": return await PartialUser.from_id(self.bot, self.target_id) return await PartialChannel.from_id(self.bot, self.target_id, self.guild) @@ -73,7 +122,7 @@ class Moderation(AuroraGuildModel): def __int__(self) -> int: return self.moderation_id - async def resolve(self, resolved_by: int, reason: str) -> None: + async def resolve(self, resolved_by: int, reason: str) -> Tuple[bool, str]: if self.resolved: raise ValueError("Case is already resolved!") @@ -81,7 +130,7 @@ class Moderation(AuroraGuildModel): self.resolved_by = resolved_by self.resolve_reason = reason - await self.type.resolve_handler(self.bot, self.guild, await self.get_target(), reason) + success, msg = await self.type.resolve_handler(moderation=self, reason=reason) # if self.type in ["UNMUTE", "UNBAN"]: # raise TypeError("Cannot resolve an unmute or unban case!") @@ -121,6 +170,7 @@ class Moderation(AuroraGuildModel): })) await self.update() + return success, msg async def update(self) -> None: from ..utilities.json import dumps @@ -164,19 +214,19 @@ class Moderation(AuroraGuildModel): ) @classmethod - def from_dict(cls, bot: Red, data: dict) -> "Moderation": + async def from_dict(cls, bot: Red, data: dict) -> "Moderation": if data.get("guild_id"): try: - guild: discord.Guild = bot.get_guild(data["guild_id"]) + guild = bot.get_guild(data["guild_id"]) if not guild: - guild = bot.fetch_guild(data["guild_id"]) + guild = await bot.fetch_guild(data["guild_id"]) except (discord.Forbidden, discord.HTTPException): guild = None data.update({"guild": guild}) return cls(bot=bot, **data) @classmethod - def from_result(cls, bot: Red, result: Iterable, guild_id: int) -> "Moderation": + async def from_result(cls, bot: Red, result: Iterable, guild_id: int) -> "Moderation": if result[7] is not None and result[7] != "NULL": hours, minutes, seconds = map(int, result[7].split(':')) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) @@ -220,7 +270,7 @@ class Moderation(AuroraGuildModel): "changes": change_obj_list, "metadata": metadata if metadata else {}, } - return cls.from_dict(bot=bot, data=case) + return await cls.from_dict(bot=bot, data=case) @staticmethod async def connect() -> Connection: @@ -239,6 +289,17 @@ class Moderation(AuroraGuildModel): @classmethod async def execute(cls, query: str, parameters: tuple | None = None, bot: Red | None = None, guild_id: int | None = None, cursor: Cursor | None = None, return_obj: bool = True) -> Union[Tuple["Moderation"], Iterable[Row]]: + """Executes a query on the database. + + Arguments: + query (str): The query to execute. + parameters (tuple): The parameters to pass to the query. + bot (Red): The bot instance. + guild_id (int): The ID of the guild to execute the query on. + cursor (Cursor): The cursor to use for the query. + return_obj (bool): Whether to return the case object(s). Defaults to `True`. If `False`, returns a `Iterable` of `aiosqlite.Row` objects. + Returns: The result of the query, either as a `Tuple` of `Moderation` objects or an `Iterable` of `aiosqlite.Row` objects. + """ logger.trace("Executing query: \"%s\" with parameters \"%s\"", query, parameters) if not parameters: parameters = () @@ -261,18 +322,19 @@ class Moderation(AuroraGuildModel): for result in results: if result[0] == 0: continue - case = cls.from_result(bot=bot, result=result, guild_id=guild_id) + case = await cls.from_result(bot=bot, result=result, guild_id=guild_id) cases.append(case) return tuple(cases) return results @classmethod - async def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, offset: int = 0, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, offset: int = 0, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: params = [] query = f"SELECT * FROM moderation_{guild_id} ORDER BY moderation_id DESC" if types: query += f" WHERE moderation_type IN ({', '.join(['?' for _ in types])})" - params.extend(types) + for t in types: + params.append(t.key) if limit: query += " LIMIT ? OFFSET ?" params.extend((limit, offset)) @@ -293,22 +355,22 @@ class Moderation(AuroraGuildModel): raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") @classmethod - async def find_by_target(cls, bot: Red, guild_id: int, target: int, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def find_by_target(cls, bot: Red, guild_id: int, target: int, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE target_id = ?" if types: query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" query += " ORDER BY moderation_id DESC;" - return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(target, *types) if types else (target,), cursor=cursor) + return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(target, *[t.key for t in types]) if types else (target,), cursor=cursor) @classmethod - async def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE moderator_id = ?" if types: query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" query += " ORDER BY moderation_id DESC;" - return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderator, *types) if types else (moderator,), cursor=cursor) + return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderator, *[t.key for t in types]) if types else (moderator,), cursor=cursor) @classmethod async def log( @@ -332,6 +394,31 @@ class Moderation(AuroraGuildModel): metadata: dict | None = None, return_obj: bool = True, ) -> Union["Moderation", int]: + """Logs a moderation case in the database. + + Args: + bot (Red): The bot instance. + guild_id (int): The ID of the guild to log the case in. + moderator_id (int): The ID of the moderator who issued the case. + moderation_type (Type): The type of moderation case. See `aurora.models.moderation_types` for the built-in options. + target_type (str): The type of target. Should be either `user` or `channel`. + target_id (int): The ID of the target. + role_id (int): The ID of the role, if applicable. + duration (timedelta): The duration of the case, if applicable. + reason (str): The reason for the case. + database (sqlite3.Connection): The database connection to use to log the case. A connection will be automatically created if not provided. + timestamp (datetime): The timestamp of the case. Will be automatically generated if not provided. + resolved (bool): Whether the case is resolved. + resolved_by (int): The ID of the user who resolved the case. + resolved_reason (str): The reason the case was resolved. + expired (bool): Whether the case is expired. + changes (list): A list of changes to log. You usually shouldn't pass this, as it's automatically generated by the `/edit` and `/resolve` commands. + metadata (dict): A dictionary of metadata to store with the case. + return_obj (bool): Whether to return the case object. Defaults to `True`. If `False`, returns the case ID. + + Returns: + Union[Moderation, int]: The `Moderation` object if `return_obj` is `True`, otherwise the case ID. + """ from ..utilities.json import dumps if not timestamp: timestamp = datetime.fromtimestamp(time()) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 66ed9e8..fdfdfd1 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -1,19 +1,23 @@ +from datetime import timedelta from math import ceil +from time import time +from typing import Tuple -from discord import File, Guild, Member, TextChannel, User +from discord import AllowedMentions, File, Interaction, Member, Object, Role, TextChannel, User from discord.abc import Messageable -from discord.errors import HTTPException, NotFound +from discord.errors import Forbidden, HTTPException, NotFound from redbot.core import app_commands, commands from redbot.core.bot import Red -from redbot.core.commands.converter import parse_relativedelta +from redbot.core.commands.converter import parse_relativedelta, parse_timedelta from redbot.core.utils.chat_formatting import bold, error, humanize_timedelta, inline -from ..utilities.factory import message_factory -from ..utilities.registry import type_registry +from ..utilities.config import config +from ..utilities.factory import message_factory, resolve_factory +from ..utilities.logger import logger from ..utilities.utils import get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta from .moderation import Moderation -from .type import Type +from .type import Type, type_registry def get_icon(bot: Red) -> File: @@ -22,43 +26,597 @@ def get_icon(bot: Red) -> File: return get_footer_image(cog) raise ValueError("Aurora cog not found. How was this managed?") -@type_registry.register(key="note") class Note(Type): key="note" string="note" verb="noted" + embed_desc="received a " + + @classmethod + async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str) -> 'Note': + response = await ctx.send( + content=f"{target.mention} has {cls.embed_desc}{cls.string}!\n**Reason** - `{reason}`" + ) + + if silent is False: + try: + embed = await message_factory( + bot=ctx.bot, + color=await ctx.embed_color, + guild=ctx.guild, + moderator=ctx.author, + reason=reason, + moderation_type=cls(), + response=response, + ) + await target.send(embed=embed, file=get_icon(ctx.bot)) + except HTTPException: + pass + + moderation = await Moderation.log( + bot=ctx.bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type="user", + target_id=target.id, + role_id=None, + duration=None, + reason=reason, + ) + await response.edit( + content=f"{target.mention} has {cls.embed_desc}{cls.string}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" + ) + await log(ctx=ctx, moderation_id=moderation.id) + await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) + return cls() + + @classmethod + async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: + if await config.guild(moderation.guild).dm_users() is True: + try: + target = await moderation.bot.fetch_user(moderation.target_id) + embed = await resolve_factory( + moderation=moderation, + reason=reason + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except (Forbidden, HTTPException, NotFound): + pass + return True, "" -@type_registry.register(key="warn") class Warn(Type): key="warn" string="warn" verb="warned" -@type_registry.register(key="addrole") + @classmethod + async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str) -> 'Warn': + response = await ctx.send( + content=f"{target.mention} has {cls.embed_desc}{cls.verb}!\n**Reason** - `{reason}`" + ) + + if silent is False: + try: + embed = await message_factory( + bot=ctx.bot, + color=await ctx.embed_color, + guild=ctx.guild, + moderator=ctx.author, + reason=reason, + moderation_type=cls(), + response=response, + ) + await target.send(embed=embed, file=get_icon(ctx.bot)) + except HTTPException: + pass + + moderation = await Moderation.log( + bot=ctx.bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type="user", + target_id=target.id, + role_id=None, + duration=None, + reason=reason, + ) + await response.edit( + content=f"{target.mention} has {cls.embed_desc}{cls.verb}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" + ) + await log(ctx=ctx, moderation_id=moderation.id) + await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) + return cls() + + @classmethod + async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: + if await config.guild(moderation.guild).dm_users() is True: + try: + target = await moderation.bot.fetch_user(moderation.target_id) + embed = await resolve_factory( + moderation=moderation, + reason=reason + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except (Forbidden, HTTPException, NotFound): + pass + return True, "" + class AddRole(Type): key="addrole" string="addrole" verb="added a role to" + embed_desc="been given the " + + @classmethod + async def handler(cls, ctx: commands.Context, target: Member, role: Role, silent: bool, duration: str = None, reason: str = None): + addrole_whitelist = await config.guild(ctx.guild).addrole_whitelist() + + if not addrole_whitelist: + await ctx.send( + content=error("There are no whitelisted roles set for this server!"), + ephemeral=True, + ) + return + + if duration is not None: + parsed_time = parse_timedelta(duration) + if parsed_time is None: + await ctx.send( + content=error("Please provide a valid duration!"), ephemeral=True + ) + return + else: + parsed_time = None + + if role.id not in addrole_whitelist: + await ctx.send( + content=error("That role isn't whitelisted!"), ephemeral=True + ) + return + + if role.id in [user_role.id for user_role in target.roles]: + await ctx.send( + content=error(f"{target.mention} already has this role!"), + ephemeral=True, + ) + return + + response = await ctx.send( + content=f"{target.mention} has {cls.embed_desc}{role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" + ) + + if silent is False: + try: + embed = await message_factory( + bot=ctx.bot, + color=await ctx.embed_color(), + guild=ctx.guild, + moderator=ctx.author, + reason=reason, + moderation_type=cls(), + response=response, + duration=parsed_time, + role=role, + ) + await target.send(embed=embed, file=get_icon(ctx.bot)) + except HTTPException: + pass + + await target.add_roles( + role, + reason=f"Role added by {ctx.author.id}{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''} for: {reason}", + ) + + moderation = await Moderation.log( + bot=ctx.bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type="user", + target_id=target.id, + role_id=role.id, + duration=parsed_time, + reason=reason, + ) + await response.edit( + content=f"{target.mention} has {cls.embed_desc}{role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`", + ) + await log(ctx=ctx, moderation_id=moderation.id) + await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) + return cls() + + @classmethod + async def duration_edit_handler(cls, interaction: Interaction, old_moderation: Moderation, new_moderation: Moderation) -> bool: # pylint: disable=unused-argument + return True + + @classmethod + async def expiry_handler(cls, moderation: Moderation) -> int: + try: + target = await moderation.get_target() + + await target.remove_roles( + Object(moderation.role_id), reason=f"Automatic role removal from case #{moderation.id}" + ) + + if await config.guild(moderation.guild).dm_users() is True: + try: + embed = await message_factory( + bot=moderation.bot, + color=await moderation.bot.get_embed_color(moderation.guild.channels[0]), + guild=moderation.guild, + reason=f"Automatic role removal from case #{moderation.id}", + moderation_type=type_registry["removerole"], + moderator=None, + duration=None, + response=None, + case=False, + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except HTTPException: + pass + logger.trace( + "Removed role %s from %s (%s)", + moderation.role_id, + target.name, + target.id, + ) + return 1 + except ( + NotFound, + Forbidden, + HTTPException, + ) as e: + logger.error( + "Removing the role %s from user %s failed due to: \n%s", + moderation.role_id, + moderation.target_id, + e, + ) + return 0 -@type_registry.register(key="removerole") class RemoveRole(Type): key="removerole" string="removerole" verb="removed a role from" + embed_desc="had the " + + @classmethod + async def handler(cls, ctx: commands.Context, target: Member, role: Role, silent: bool, duration: str = None, reason: str = None): + addrole_whitelist = await config.guild(ctx.guild).addrole_whitelist() + + if not addrole_whitelist: + await ctx.send( + content=error("There are no whitelisted roles set for this server!"), + ephemeral=True, + ) + return + + if duration is not None: + parsed_time = parse_timedelta(duration) + if parsed_time is None: + await ctx.send( + content=error("Please provide a valid duration!"), ephemeral=True + ) + return + else: + parsed_time = None + + if role.id not in addrole_whitelist: + await ctx.send( + content=error("That role isn't whitelisted!"), ephemeral=True + ) + return + + if role.id not in [user_role.id for user_role in target.roles]: + await ctx.send( + content=error(f"{target.mention} does not have this role!"), + ephemeral=True, + ) + return + + response = await ctx.send( + content=f"{target.mention} has {cls.embed_desc}{role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" + ) + + if silent is False: + try: + embed = await message_factory( + bot=ctx.bot, + color=await ctx.embed_color(), + guild=ctx.guild, + moderator=ctx.author, + reason=reason, + moderation_type="removerole", + response=response, + duration=parsed_time, + role=role, + ) + await target.send(embed=embed, file=get_icon(ctx.bot)) + except HTTPException: + pass + + await target.remove_roles( + role, + reason=f"Role removed by {ctx.author.id}{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''} for: {reason}", + ) + + moderation = await Moderation.log( + bot=ctx.bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type="user", + target_id=target.id, + role_id=role.id, + duration=parsed_time, + reason=reason, + ) + await response.edit( + content=f"{target.mention} has {cls.embed_desc}{role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`", + ) + await log(ctx=ctx, moderation_id=moderation.id) + await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) + return cls() + + @classmethod + async def duration_edit_handler(cls, interaction: Interaction, old_moderation: Moderation, new_moderation: Moderation) -> bool: # pylint: disable=unused-argument + return True + + @classmethod + async def expiry_handler(cls, moderation: Moderation) -> int: + try: + target = await moderation.get_target() + + await target.add_roles( + Object(moderation.role_id), reason=f"Automatic role addition from case #{moderation.id}" + ) + if await config.guild(moderation.guild).dm_users() is True: + try: + embed = await message_factory( + bot=moderation.bot, + color=await moderation.bot.get_embed_color(moderation.guild.channels[0]), + guild=moderation.guild, + reason=f"Automatic role addition from case #{moderation.id}", + moderation_type=type_registry["addrole"], + moderator=None, + duration=None, + response=None, + case=False, + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except HTTPException: + pass + logger.trace( + "Added role %s to %s (%s)", + moderation.role_id, + target.name, + target.id, + ) + return 1 + except ( + NotFound, + Forbidden, + HTTPException, + ) as e: + logger.error( + "Adding the role %s to user %s failed due to: \n%s", + moderation.role_id, + moderation.target_id, + e, + ) + return 0 + + @classmethod + async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: + try: + target = await moderation.get_target() + await target.add_roles( + Object(moderation.role_id), reason=reason + ) + if await config.guild(moderation.guild).dm_users() is True: + try: + embed = await resolve_factory( + moderation=moderation, + reason=reason + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except HTTPException: + pass + logger.trace( + "Added role %s to %s (%s)", + moderation.role_id, + target.name, + target.id, + ) + return True, "" + except (NotFound, Forbidden, HTTPException) as e: + logger.error( + "Failed to add role %s to user %s (%s)\n%s", + moderation.role_id, + target.name, + target.id, + e, + ) + return False, "Failed to add role to user." -@type_registry.register(key="mute") class Mute(Type): key="mute" string="mute" verb="muted" -@type_registry.register(key="unmute") + @classmethod + async def handler(cls, ctx: commands.Context, target: Member, silent: bool, duration: str, reason: str = None): + if target.is_timed_out() is True: + await ctx.send( + error(f"{target.mention} is already muted!"), + allowed_mentions=AllowedMentions(users=False), + ephemeral=True, + ) + return + + try: + parsed_time = parse_timedelta(duration, maximum=timedelta(days=28)) + if parsed_time is None: + await ctx.send( + error("Please provide a valid duration!"), ephemeral=True + ) + return + except commands.BadArgument: + await ctx.send( + error("Please provide a duration that is less than 28 days."), ephemeral=True + ) + return + + await target.timeout( + parsed_time, reason=f"Muted by {ctx.author.id} for: {reason}" + ) + + response = await ctx.send( + content=f"{target.mention} has been muted for {humanize_timedelta(timedelta=parsed_time)}!\n**Reason** - `{reason}`" + ) + + if silent is False: + try: + embed = await message_factory( + bot=ctx.bot, + color=await ctx.embed_color(), + guild=ctx.guild, + moderator=ctx.author, + reason=reason, + moderation_type=cls(), + response=response, + duration=parsed_time, + ) + await target.send(embed=embed, file=get_icon(ctx.bot)) + except HTTPException: + pass + + moderation = await Moderation.log( + bot=ctx.bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type="user", + target_id=target.id, + role_id=None, + duration=parsed_time, + reason=reason, + ) + await response.edit( + content=f"{target.mention} has been muted for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" + ) + await log(ctx=ctx, moderation_id=moderation.id) + await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) + return cls() + + @classmethod + async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: + try: + target = await moderation.guild.fetch_member(moderation.target_id) + except (Forbidden, HTTPException, NotFound): + return False, "User is not in the server, so I cannot unmute them." + if target.is_timed_out() is False: + return True, "" + await target.timeout(None, reason=reason) + + if await config.guild(moderation.guild).dm_users() is True: + try: + embed = await resolve_factory( + moderation=moderation, + reason=reason + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except (Forbidden, HTTPException): + pass + return True, "" + + @classmethod + async def duration_edit_handler(cls, interaction: Interaction, old_moderation: Moderation, new_moderation: Moderation) -> bool: # pylint: disable=unused-argument + if ( + time() - new_moderation.unix_timestamp + ) + new_moderation.duration.total_seconds() > 2419200: + await interaction.response.send_message( + content=error( + "Please provide a duration that is less than 28 days from the initial moderation." + ), + ephemeral=True + ) + return False + + try: + member = await interaction.guild.fetch_member( + new_moderation.target_id + ) + + await member.timeout( + new_moderation.duration, + reason=f"Case #{new_moderation.id:,} edited by {interaction.user.id}", + ) + except NotFound: + pass + return True + class Unmute(Type): key="unmute" string="unmute" verb="unmuted" -@type_registry.register(key="kick") + @classmethod + async def handler(cls, ctx: commands.Context, target: Member, silent: bool, reason: str = None): + if target.is_timed_out() is False: + await ctx.send( + content=error(f"{target.mention} is not muted!"), + allowed_mentions=AllowedMentions(users=False), + ephemeral=True, + ) + return + + if reason: + await target.timeout( + None, reason=f"{cls.verb.title()} by {ctx.author.id} for: {reason}" + ) + else: + await target.timeout(None, reason=f"{cls.verb.title()} by {ctx.author.id}") + reason = "No reason given." + + response_message = await ctx.send( + content=f"{target.mention} has been {cls.verb}!\n**Reason** - `{reason}`" + ) + + if silent is False: + try: + embed = await message_factory( + bot=ctx.bot, + color=await ctx.embed_color(), + guild=ctx.guild, + moderator=ctx.author, + reason=reason, + moderation_type="unmuted", + response=response_message, + ) + await target.send(embed=embed, file=get_icon(ctx.bot)) + except HTTPException: + pass + + moderation = await Moderation.log( + bot=ctx.bot, + guild_id=ctx.guild.id, + moderator_id=ctx.author.id, + moderation_type=cls(), + target_type="user", + target_id=target.id, + role_id=None, + duration=None, + reason=reason, + ) + await response_message.edit( + content=f"{target.mention} has been {cls.verb}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" + ) + await log(ctx=ctx, moderation_id=moderation.id) + await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) + class Kick(Type): key="kick" string="kick" @@ -74,7 +632,7 @@ class Kick(Type): try: embed = await message_factory( bot=bot, - color=await bot.get_embed_color(ctx.channel), + color=await ctx.embed_color(), guild=ctx.guild, reason=reason, moderation_type=cls(), @@ -99,10 +657,24 @@ class Kick(Type): reason=reason ) await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") - await log(ctx, moderation.id) - await send_evidenceformat(ctx, moderation.id) + await log(ctx=ctx, moderation_id=moderation.id) + await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) return cls -@type_registry.register(key="ban") + + @classmethod + async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: + if await config.guild(moderation.guild).dm_users() is True: + try: + target = await moderation.bot.fetch_user(moderation.target_id) + embed = await resolve_factory( + moderation=moderation, + reason=reason + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except (Forbidden, HTTPException, NotFound): + pass + return True, "" + class Ban(Type): key="ban" string="ban" @@ -129,7 +701,7 @@ class Ban(Type): try: embed = await message_factory( bot=bot, - color=await bot.get_embed_color(ctx.channel), + color=await ctx.embed_color(), guild=ctx.guild, reason=reason, moderation_type=cls(), @@ -154,34 +726,35 @@ class Ban(Type): reason=reason ) await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") - await log(ctx, moderation.id) - await send_evidenceformat(ctx, moderation.id) + await log(ctx=ctx, moderation_id=moderation.id) + await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) return cls @classmethod - async def resolve_handler(cls, bot: Red, guild: Guild, target: Member | User, reason: str | None = None) -> None: + async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: try: - await guild.fetch_ban(user=target) - except NotFound: - return - await guild.unban(user=target, reason=reason) + target = await moderation.bot.fetch_user(moderation.target_id) + except (HTTPException, NotFound): + return False, "Fetching the target failed, so I cannot unban them." try: - embed = await message_factory( - bot=bot, - color=await bot.get_embed_color(guild.channels[0]), - guild=guild, - reason=reason, - moderation_type=Unban(), - moderator=None, - duration=None, - response=None - ) - await target.send(embed=embed, file=get_icon(bot)) - except HTTPException: - pass + await moderation.guild.unban(user=target, reason=reason) + except (NotFound, Forbidden, HTTPException) as e: + if e == NotFound: + return True, "" + return False, "I do not have permission to unban this user." + + if await config.guild(moderation.guild).dm_users() is True: + try: + embed = await resolve_factory( + moderation=moderation, + reason=reason + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except (Forbidden, HTTPException): + pass + return True, "" -@type_registry.register(key="tempban") class Tempban(Ban): key="tempban" string="tempban" @@ -216,7 +789,7 @@ class Tempban(Ban): try: embed = await message_factory( bot=bot, - color=await bot.get_embed_color(ctx.channel), + color=await ctx.embed_color(), guild=ctx.guild, reason=reason, moderation_type=cls(), @@ -245,7 +818,54 @@ class Tempban(Ban): await send_evidenceformat(ctx, moderation.id) return cls -@type_registry.register(key="softban") + @classmethod + async def expiry_handler(cls, moderation: Moderation) -> int: + reason = f"Automatic {Unban.string} from case #{moderation.id}" + try: + target = await moderation.get_target() + await moderation.guild.unban(user=target, reason=reason) + + if await config.guild(moderation.guild).dm_users() is True: + try: + embed = await message_factory( + bot=moderation.bot, + color=await moderation.bot.get_embed_color(moderation.guild.channels[0]), + guild=moderation.guild, + reason=reason, + moderation_type=type_registry["unban"], + moderator=None, + duration=None, + response=None, + case=False, + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except HTTPException: + pass + logger.trace( + "%s %s (%s) from %s (%s)", + Unban.verb.title(), + target.name, + target.id, + moderation.guild.name, + moderation.guild.id, + ) + return 1 + except (NotFound, Forbidden, HTTPException) as e: + logger.error( + "Failed to %s %s (%s) from %s (%s)\n%s", + Unban.string, + target.name, + target.id, + moderation.guild.name, + moderation.guild.id, + e, + ) + return 0 + + @classmethod + async def duration_edit_handler(cls, interaction: Interaction, old_moderation: Moderation, new_moderation: Moderation) -> bool: # pylint: disable=unused-argument + return True + class Softban(Type): key="softban" string="softban" @@ -272,7 +892,7 @@ class Softban(Type): try: embed = await message_factory( bot=bot, - color=await bot.get_embed_color(ctx.channel), + color=await ctx.embed_color(), guild=ctx.guild, reason=reason, moderation_type=cls(), @@ -302,7 +922,20 @@ class Softban(Type): await send_evidenceformat(ctx, moderation.id) return cls -@type_registry.register(key="unban") + @classmethod + async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: + if await config.guild(moderation.guild).dm_users() is True: + try: + target = await moderation.bot.fetch_user(moderation.target_id) + embed = await resolve_factory( + moderation=moderation, + reason=reason + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except (Forbidden, HTTPException, NotFound): + pass + return True, "" + class Unban(Type): key="unban" string="unban" @@ -324,7 +957,7 @@ class Unban(Type): try: embed = await message_factory( bot=bot, - color=await bot.get_embed_color(ctx.channel), + color=await ctx.embed_color(), guild=ctx.guild, reason=reason, moderation_type=cls(), @@ -353,7 +986,6 @@ class Unban(Type): await send_evidenceformat(ctx, moderation.id) return cls -@type_registry.register(key="slowmode") class Slowmode(Type): key="slowmode" string="slowmode" @@ -393,7 +1025,6 @@ class Slowmode(Type): await log(ctx, moderation.id) return cls -@type_registry.register(key="lockdown") class Lockdown(Type): key="lockdown" string="lockdown" diff --git a/aurora/models/type.py b/aurora/models/type.py index 92e734b..a677030 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -1,36 +1,82 @@ -from typing import Any +from abc import ABC +from typing import List, Tuple -from discord import Guild, Member, User +from class_registry import AutoRegister, ClassRegistry +from discord import Interaction, Member, User from discord.abc import Messageable from redbot.core import commands -from redbot.core.bot import Red +type_registry: List['Type'] = ClassRegistry(attr_name='key', unique=True) -#@type_registry.register(key="type") -class Type(object): - key = "type" # this should ALWAYS be the same as the registry key, and should NEVER be localized +class Type(ABC, AutoRegister(type_registry)): + """This is a base class for moderation types. + + Attributes: + key (str): The key to use for this type. This should be unique, as this is how the type is registered internally. Changing this key will break existing cases with this type. + string (str): The string to display for this type. + verb (str): The verb to use for this type. + embed_desc (str): The string to use for embed descriptions. + channel (bool): Whether this type targets channels or users. If this is `true` in a subclass, its overriden handler methods should be typed with `discord.abc.Messageable` instead of `discord.Member | discord.User`. + + Properties: + name (str): The string to display for this type. This is the same as the `string` attribute. + """ + + key = "type" string = "type" verb = "typed" - embed_desc = "been" - channel = False # if this is True, the overridden handler methods should be typed with `discord.abc.Messageable` instead of `discord.Member | discord.User` + embed_desc = "been " + channel = False + + @property + def name(self) -> str: + """Alias for the `string` attribute.""" + return self.string def __str__(self) -> str: return self.string @classmethod async def handler(cls, ctx: commands.Context, target: Member | User | Messageable, silent: bool, **kwargs) -> 'Type': # pylint: disable=unused-argument - """This method should be overridden by any child classes, but should retain the same starting keyword arguments.""" + """This method should be overridden by any child classes, but should retain the same starting keyword arguments. + + Arguments: + ctx (commands.Context): The context of the command. + target (discord.Member | discord.User | discord.abc.Messageable): The target of the moderation. + silent (bool): Whether details about the moderation should be DM'ed to the target of the moderation. + """ raise NotImplementedError @classmethod - async def resolve_handler(cls, bot: Red, guild: Guild, target: Member | User | Messageable, reason: str | None = None, **kwargs) -> Any: # pylint: disable=unused-argument + async def resolve_handler(cls, moderation, reason: str) -> Tuple[bool, str]: # pylint: disable=unused-argument """This method should be overridden by any resolvable child classes, but should retain the same keyword arguments. - If your moderation type should not be resolvable, do not override this.""" + If your moderation type should not be resolvable, do not override this. + + Arguments: + moderation (aurora.models.Moderation): The moderation to resolve. + reason (str): The reason for resolving the moderation. + """ raise NotImplementedError @classmethod - async def expiry_handler(cls, bot: Red, guild: Guild, target: Member | User | Messageable, **kwargs) -> Any: # pylint: disable=unused-argument - """This method should be overridden by any expirable child classes, but should retain the same keyword arguments. - If your moderation type should not expire, do not override this.""" + async def expiry_handler(cls, moderation) -> int: # pylint: disable=unused-argument + """This method should be overridden by any expirable child classes, but should retain the same keyword arguments and return an integer. + If your moderation type should not expire, do not override this, but also do not set an `end_timestamp` when you log your moderation. + + Arguments: + moderation (aurora.models.Moderation): The moderation that is expiring. + """ + raise NotImplementedError + + @classmethod + async def duration_edit_handler(cls, interaction: Interaction, old_moderation, new_moderation) -> bool: # pylint: disable=unused-argument + """This method should be overridden by any child classes with editable durations, but should retain the same keyword arguments and should return True if the duration was successfully modified, or False if it was not. + If your moderation type's duration should not be editable, do not override this. + + Arguments: + interaction (discord.Interaction): The interaction that triggered the duration edit. + old_moderation (aurora.models.Moderation): The old moderation, from before the `/edit` command was invoked. + new_moderation (aurora.models.Moderation): The current state of the moderation. + """ raise NotImplementedError diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 76c8d9b..9cce8cc 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -24,6 +24,7 @@ async def message_factory( duration: timedelta | None = None, response: Message | None = None, role: Role | None = None, + case: bool = True, ) -> Embed: """This function creates a message from set parameters, meant for contacting the moderated user. @@ -37,6 +38,7 @@ async def message_factory( duration (timedelta, optional): The duration of the moderation. Defaults to None. response (Message, optional): The response message. Defaults to None. role (Role, optional): The role that was added or removed. Defaults to None. + case (bool, optional): Whether the message is for a moderation case. Defaults to True. Returns: @@ -57,22 +59,9 @@ async def message_factory( else: embed_duration = "" - # if moderation_type.type == "note": - # embed_desc = "received a" - # elif moderation_type.type == "addrole": - # embed_desc = f"received the {role.name} role" - # title = "Role Added" - # verb = "" - # elif moderation_type.type == "removerole": - # embed_desc = f"lost the {role.name} role" - # title = "Role Removed" - # verb = "" - # else: - # embed_desc = "been" - embed = Embed( title=str.title(moderation_type.verb), - description=f"You have {moderation_type.embed_desc} {moderation_type.verb}{embed_duration} in {guild_name}.", + description=f"You have {moderation_type.embed_desc}{moderation_type.verb}{embed_duration} in {guild_name}.", color=color, timestamp=datetime.now(), ) @@ -89,14 +78,43 @@ async def message_factory( else: embed.set_author(name=guild.name) + if case: + embed.set_footer( + text=f"Case #{await Moderation.get_next_case_number(bot=bot, guild_id=guild.id):,}", + icon_url="attachment://arrow.png", + ) + + return embed + +async def resolve_factory(moderation: Moderation, reason: str) -> Embed: + """This function creates a resolved embed from set parameters, meant for contacting the moderated user. + + Args: + moderation (aurora.models.Moderation): The moderation object. + reason (str): The reason for resolving the moderation. + Returns: `discord.Embed` + """ + + embed = Embed( + title=str.title(moderation.type.name) + " Resolved", + description=f"Your {moderation.type.name} in {moderation.guild.name} has been resolved.", + color=await moderation.bot.get_embed_color(moderation.guild.channels[0]), + timestamp=datetime.now(), + ) + + embed.add_field(name="Reason", value=f"`{reason}`", inline=False) + + if moderation.guild.icon.url is not None: + embed.set_author(name=moderation.guild.name, icon_url=moderation.guild.icon.url) + else: + embed.set_author(name=moderation.guild.name) embed.set_footer( - text=f"Case #{await Moderation.get_next_case_number(bot=bot, guild_id=guild.id):,}", + text=f"Case #{moderation.id:,}", icon_url="attachment://arrow.png", ) return embed - async def log_factory( ctx: commands.Context, moderation: Moderation, resolved: bool = False ) -> Embed: diff --git a/aurora/utilities/moderate.py b/aurora/utilities/moderate.py index 05fc245..1a8e085 100644 --- a/aurora/utilities/moderate.py +++ b/aurora/utilities/moderate.py @@ -3,9 +3,8 @@ from typing import List, Union import discord from redbot.core import app_commands, commands -from ..models.moderation_types import Type +from ..models.type import Type, type_registry from .config import config -from .registry import type_registry from .utils import check_moddable diff --git a/aurora/utilities/registry.py b/aurora/utilities/registry.py deleted file mode 100644 index 7aca3c1..0000000 --- a/aurora/utilities/registry.py +++ /dev/null @@ -1,3 +0,0 @@ -from class_registry import ClassRegistry - -type_registry = ClassRegistry() -- 2.45.3 From ad0d981888d5c992ce6a6bd4af664b6a3e880fc2 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 15:28:39 -0400 Subject: [PATCH 226/376] fix(aurora): hopefully fixed a pydantic schema error --- aurora/models/moderation_types.py | 39 +++++++++++++++++++++++++++++++ aurora/models/type.py | 12 ++++++---- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index fdfdfd1..324befd 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -32,6 +32,9 @@ class Note(Type): verb="noted" embed_desc="received a " + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str) -> 'Note': response = await ctx.send( @@ -90,6 +93,9 @@ class Warn(Type): string="warn" verb="warned" + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str) -> 'Warn': response = await ctx.send( @@ -149,6 +155,9 @@ class AddRole(Type): verb="added a role to" embed_desc="been given the " + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member, role: Role, silent: bool, duration: str = None, reason: str = None): addrole_whitelist = await config.guild(ctx.guild).addrole_whitelist() @@ -282,6 +291,9 @@ class RemoveRole(Type): verb="removed a role from" embed_desc="had the " + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member, role: Role, silent: bool, duration: str = None, reason: str = None): addrole_whitelist = await config.guild(ctx.guild).addrole_whitelist() @@ -446,6 +458,9 @@ class Mute(Type): string="mute" verb="muted" + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member, silent: bool, duration: str, reason: str = None): if target.is_timed_out() is True: @@ -563,6 +578,9 @@ class Unmute(Type): string="unmute" verb="unmuted" + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member, silent: bool, reason: str = None): if target.is_timed_out() is False: @@ -622,6 +640,9 @@ class Kick(Type): string="kick" verb="kicked" + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None) -> 'Kick': """Kick a user.""" @@ -680,6 +701,9 @@ class Ban(Type): string="ban" verb="banned" + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Ban': """Ban a user.""" @@ -760,6 +784,9 @@ class Tempban(Ban): string="tempban" verb="tempbanned" + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, duration: str, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Ban': """Ban a user.""" @@ -871,6 +898,9 @@ class Softban(Type): string="softban" verb="softbanned" + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Softban': """Softban a user.""" @@ -941,6 +971,9 @@ class Unban(Type): string="unban" verb="unbanned" + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None) -> 'Unban': """Unban a user.""" @@ -992,6 +1025,9 @@ class Slowmode(Type): verb="set the slowmode in" channel=True + def void(self) -> None: + return None + @classmethod async def handler(cls, ctx: commands.Context, target: Messageable, silent: bool, duration: str, reason: str) -> 'Slowmode': # pylint: disable=unused-argument """Set the slowmode in a channel.""" @@ -1030,3 +1066,6 @@ class Lockdown(Type): string="lockdown" verb="locked down" channel=True + + def void(self) -> None: + return None diff --git a/aurora/models/type.py b/aurora/models/type.py index a677030..292f1ce 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -1,6 +1,5 @@ - -from abc import ABC -from typing import List, Tuple +from abc import abstractmethod +from typing import Any, List, Tuple from class_registry import AutoRegister, ClassRegistry from discord import Interaction, Member, User @@ -9,7 +8,7 @@ from redbot.core import commands type_registry: List['Type'] = ClassRegistry(attr_name='key', unique=True) -class Type(ABC, AutoRegister(type_registry)): +class Type(object, metaclass=AutoRegister(type_registry)): """This is a base class for moderation types. Attributes: @@ -29,6 +28,11 @@ class Type(ABC, AutoRegister(type_registry)): embed_desc = "been " channel = False + @abstractmethod + def void(self) -> Any: + """This method should be overridden by any child classes. This is a placeholder to allow for automatic class registration.""" + raise NotImplementedError + @property def name(self) -> str: """Alias for the `string` attribute.""" -- 2.45.3 From 47c8116ee0c6ec52ffb157fd5b89377a25d27283 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 15:42:58 -0400 Subject: [PATCH 227/376] misc(aurora): removed useless whitespace from the top of a file --- aurora/models/moderation_types.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 324befd..ffa38ca 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -1,4 +1,3 @@ - from datetime import timedelta from math import ceil from time import time -- 2.45.3 From 63e6f4b5520e26af9ca6d1207c1f9e7214a3cbdc Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 15:49:54 -0400 Subject: [PATCH 228/376] fix(aurora): pylint fixes --- aurora/models/moderation_types.py | 3 ++- aurora/models/type.py | 2 +- aurora/utilities/factory.py | 2 -- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index ffa38ca..c798517 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -1,3 +1,4 @@ +# pylint: disable=abstract-method from datetime import timedelta from math import ceil from time import time @@ -787,7 +788,7 @@ class Tempban(Ban): return None @classmethod - async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, duration: str, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Ban': + async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, duration: str, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Ban': # pylint: disabled=arguments-renamed """Ban a user.""" bot = ctx.bot try: diff --git a/aurora/models/type.py b/aurora/models/type.py index 292f1ce..a979d2b 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -8,7 +8,7 @@ from redbot.core import commands type_registry: List['Type'] = ClassRegistry(attr_name='key', unique=True) -class Type(object, metaclass=AutoRegister(type_registry)): +class Type(metaclass=AutoRegister(type_registry)): """This is a base class for moderation types. Attributes: diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 9cce8cc..e90af3c 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -23,7 +23,6 @@ async def message_factory( moderator: Union[Member, User] | None = None, duration: timedelta | None = None, response: Message | None = None, - role: Role | None = None, case: bool = True, ) -> Embed: """This function creates a message from set parameters, meant for contacting the moderated user. @@ -37,7 +36,6 @@ async def message_factory( moderator (Union[Member, User], optional): The moderator who performed the moderation. Defaults to None. duration (timedelta, optional): The duration of the moderation. Defaults to None. response (Message, optional): The response message. Defaults to None. - role (Role, optional): The role that was added or removed. Defaults to None. case (bool, optional): Whether the message is for a moderation case. Defaults to True. -- 2.45.3 From 8d03022453653a06b902d91b4d49547a0a372d14 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 15:52:27 -0400 Subject: [PATCH 229/376] fix(aurora): more pylint fixes --- aurora/models/moderation_types.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index c798517..e1a261d 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -207,7 +207,6 @@ class AddRole(Type): moderation_type=cls(), response=response, duration=parsed_time, - role=role, ) await target.send(embed=embed, file=get_icon(ctx.bot)) except HTTPException: @@ -343,7 +342,6 @@ class RemoveRole(Type): moderation_type="removerole", response=response, duration=parsed_time, - role=role, ) await target.send(embed=embed, file=get_icon(ctx.bot)) except HTTPException: @@ -788,7 +786,7 @@ class Tempban(Ban): return None @classmethod - async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, duration: str, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Ban': # pylint: disabled=arguments-renamed + async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, duration: str, reason: str = None, delete_messages: app_commands.Choice | None = None) -> 'Ban': # pylint: disable=arguments-renamed """Ban a user.""" bot = ctx.bot try: -- 2.45.3 From ea12d362df31fb0f2c9f9dc51b72062b89387d5b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 15:55:16 -0400 Subject: [PATCH 230/376] fix(aurora): final pylint fixes --- aurora/models/moderation_types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index e1a261d..8b50df4 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -808,7 +808,7 @@ class Tempban(Ban): except ValueError: await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) - response_message = await ctx.send(f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}") + response_message = await ctx.send(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}") if silent is False: try: @@ -1055,7 +1055,7 @@ class Slowmode(Type): duration=parsed_time, reason=None ) - await ctx.send(f"{ctx.author.mention} has {cls.verb} {target.mention} to {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}") + await ctx.send(content=f"{ctx.author.mention} has {cls.verb} {target.mention} to {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}") await log(ctx, moderation.id) return cls -- 2.45.3 From c4c5b323a30a610c8ffc826fdbb2abb633a7fb85 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 15:58:15 -0400 Subject: [PATCH 231/376] fix(aurora): ACTUALLY final pylint fixes --- aurora/models/moderation_types.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 8b50df4..3244ea2 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -808,7 +808,7 @@ class Tempban(Ban): except ValueError: await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) - response_message = await ctx.send(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}") + response_message = await ctx.send(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}!\n{bold(text='Reason:')} {inline(text=reason)}") if silent is False: try: @@ -838,7 +838,7 @@ class Tempban(Ban): duration=parsed_time, reason=reason ) - await response_message.edit(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") + await response_message.edit(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}! (Case {inline(text=f'#{moderation.id}')})\n{bold(text='Reason:')} {inline(reason)}") await log(ctx, moderation.id) await send_evidenceformat(ctx, moderation.id) return cls @@ -1030,16 +1030,16 @@ class Slowmode(Type): async def handler(cls, ctx: commands.Context, target: Messageable, silent: bool, duration: str, reason: str) -> 'Slowmode': # pylint: disable=unused-argument """Set the slowmode in a channel.""" bot = ctx.bot - parsed_time = parse_relativedelta(duration) + parsed_time = parse_relativedelta(argument=duration) if not parsed_time: - await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) + await ctx.send(content=error(text="Please provide a valid duration!"), ephemeral=True) try: - parsed_time = timedelta_from_relativedelta(parsed_time) + parsed_time = timedelta_from_relativedelta(relativedelta=parsed_time) except ValueError: - await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) + await ctx.send(content=error(text="Please provide a valid duration!"), ephemeral=True) if ceil(parsed_time.total_seconds()) > 21600: - await ctx.send(content=error("The slowmode duration cannot exceed 6 hours!"), ephemeral=True) + await ctx.send(content=error(text="The slowmode duration cannot exceed 6 hours!"), ephemeral=True) return if isinstance(target, TextChannel): @@ -1055,8 +1055,8 @@ class Slowmode(Type): duration=parsed_time, reason=None ) - await ctx.send(content=f"{ctx.author.mention} has {cls.verb} {target.mention} to {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}") - await log(ctx, moderation.id) + await ctx.send(content=f"{ctx.author.mention} has {cls.verb} {target.mention} to {humanize_timedelta(parsed_time)}!\n{bold(text='Reason:')} {inline(text=reason)}") + await log(ctx=ctx, moderation_id=moderation.id) return cls class Lockdown(Type): -- 2.45.3 From f1e763673bfbb09c3311993d2b5eaeae56403303 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 16:02:19 -0400 Subject: [PATCH 232/376] fix(aurora): legitimately the final pylint fixes for now --- aurora/models/moderation_types.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 3244ea2..0511333 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -803,12 +803,14 @@ class Tempban(Ban): parsed_time = parse_relativedelta(duration) if not parsed_time: await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) + return cls try: parsed_time = timedelta_from_relativedelta(parsed_time) except ValueError: await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) + return cls - response_message = await ctx.send(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}!\n{bold(text='Reason:')} {inline(text=reason)}") + response_message = await ctx.send(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(timedelta=parsed_time)}!\n{bold(text='Reason:')} {inline(text=reason)}") if silent is False: try: @@ -838,7 +840,7 @@ class Tempban(Ban): duration=parsed_time, reason=reason ) - await response_message.edit(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(parsed_time)}! (Case {inline(text=f'#{moderation.id}')})\n{bold(text='Reason:')} {inline(reason)}") + await response_message.edit(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(timedelta=parsed_time)}! (Case {inline(text=f'#{moderation.id}')})\n{bold(text='Reason:')} {inline(reason)}") await log(ctx, moderation.id) await send_evidenceformat(ctx, moderation.id) return cls @@ -1033,14 +1035,16 @@ class Slowmode(Type): parsed_time = parse_relativedelta(argument=duration) if not parsed_time: await ctx.send(content=error(text="Please provide a valid duration!"), ephemeral=True) + return cls try: parsed_time = timedelta_from_relativedelta(relativedelta=parsed_time) except ValueError: await ctx.send(content=error(text="Please provide a valid duration!"), ephemeral=True) + return cls if ceil(parsed_time.total_seconds()) > 21600: await ctx.send(content=error(text="The slowmode duration cannot exceed 6 hours!"), ephemeral=True) - return + return cls if isinstance(target, TextChannel): await target.edit(slowmode_delay=ceil(parsed_time.total_seconds())) @@ -1055,7 +1059,7 @@ class Slowmode(Type): duration=parsed_time, reason=None ) - await ctx.send(content=f"{ctx.author.mention} has {cls.verb} {target.mention} to {humanize_timedelta(parsed_time)}!\n{bold(text='Reason:')} {inline(text=reason)}") + await ctx.send(content=f"{ctx.author.mention} has {cls.verb} {target.mention} to {humanize_timedelta(timedelta=parsed_time)}!\n{bold(text='Reason:')} {inline(text=reason)}") await log(ctx=ctx, moderation_id=moderation.id) return cls -- 2.45.3 From b37958425153c932141f803b6eec117b23832ba2 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 16:05:05 -0400 Subject: [PATCH 233/376] fix(aurora): fixed a TypeError in the note and warn handlers --- aurora/models/moderation_types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 0511333..6f1cb05 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -45,7 +45,7 @@ class Note(Type): try: embed = await message_factory( bot=ctx.bot, - color=await ctx.embed_color, + color=await ctx.embed_color(), guild=ctx.guild, moderator=ctx.author, reason=reason, @@ -106,7 +106,7 @@ class Warn(Type): try: embed = await message_factory( bot=ctx.bot, - color=await ctx.embed_color, + color=await ctx.embed_color(), guild=ctx.guild, moderator=ctx.author, reason=reason, -- 2.45.3 From 6edda87baabbe194c7c09049ab94022b79e96d84 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 16:30:34 -0400 Subject: [PATCH 234/376] fix(aurora): add a resolve_handler to AddRole (oops!) --- aurora/models/moderation_types.py | 36 +++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 6f1cb05..3b29bf4 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -30,7 +30,6 @@ class Note(Type): key="note" string="note" verb="noted" - embed_desc="received a " def void(self) -> None: return None @@ -284,6 +283,39 @@ class AddRole(Type): ) return 0 + @classmethod + async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: + try: + target = await moderation.guild.fetch_member(moderation.target_id) + await target.remove_roles( + Object(moderation.role_id), reason=reason + ) + if await config.guild(moderation.guild).dm_users() is True: + try: + embed = await resolve_factory( + moderation=moderation, + reason=reason + ) + await target.send(embed=embed, file=get_icon(bot=moderation.bot)) + except HTTPException: + pass + logger.trace( + "Removed role %s from %s (%s)", + moderation.role_id, + target.name, + target.id, + ) + return True, "" + except (NotFound, Forbidden, HTTPException) as e: + logger.error( + "Failed to remove role %s from user %s (%s)\n%s", + moderation.role_id, + target.name, + target.id, + e, + ) + return False, "Failed to remove role from user." + class RemoveRole(Type): key="removerole" string="removerole" @@ -294,7 +326,7 @@ class RemoveRole(Type): return None @classmethod - async def handler(cls, ctx: commands.Context, target: Member, role: Role, silent: bool, duration: str = None, reason: str = None): + async def handler(cls, ctx: commands.Context, target: Member, role: Role, silent: bool, duration: str | None = None, reason: str = None): addrole_whitelist = await config.guild(ctx.guild).addrole_whitelist() if not addrole_whitelist: -- 2.45.3 From 7f0bd8c1a8f3f376c08de46aa5c9da4483ba1598 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Fri, 12 Jul 2024 16:33:00 -0400 Subject: [PATCH 235/376] fix(aurora): fixed the Moderation.update() method being broken --- aurora/models/moderation.py | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 471d133..b49894b 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -132,27 +132,6 @@ class Moderation(AuroraGuildModel): success, msg = await self.type.resolve_handler(moderation=self, reason=reason) - # if self.type in ["UNMUTE", "UNBAN"]: - # raise TypeError("Cannot resolve an unmute or unban case!") - - # if self.type == "MUTE": - # try: - # guild: discord.Guild = await self.bot.fetch_guild(self.guild_id) - # member = await guild.fetch_member(self.target_id) - - # await member.timeout( - # None, reason=f"Case {self.moderation_id} resolved by {resolved_by}{' for '+ reason if reason else ''}" - # ) - # except NotFound: - # pass - - # if self.type in ["BAN", "TEMPBAN"]: - # try: - # guild: discord.Guild = await self.bot.fetch_guild(self.guild_id) - # await guild.unban(await self.get_target(), reason=f"Case {self.moderation_id} resolved by {resolved_by}{' for '+ reason if reason else ''}") - # except NotFound: - # pass - if not self.changes: self.changes.append(Change.from_dict(self.bot, { "type": "ORIGINAL", @@ -178,7 +157,7 @@ class Moderation(AuroraGuildModel): await self.execute(query, ( self.timestamp.timestamp(), - self.moderation_type.moderation_type, + self.moderation_type.key, self.target_type, self.moderator_id, self.role_id, @@ -198,7 +177,7 @@ class Moderation(AuroraGuildModel): self.moderation_id, self.guild_id, self.timestamp.timestamp(), - self.moderation_type, + self.moderation_type.key, self.target_type, self.moderator_id, self.role_id, -- 2.45.3 From 1a3af342dfe862afee4bdb4a6abdba539b0c2192 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 10 Aug 2024 13:17:16 -0400 Subject: [PATCH 236/376] feat(aurora): allow for querying moderation history by date (before/after) --- aurora/aurora.py | 29 ++++++++++++++++++--- aurora/info.json | 2 +- aurora/models/moderation.py | 34 ++++++++++++++++++++---- poetry.lock | 52 ++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 5 files changed, 108 insertions(+), 10 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 1e7fb11..58dcbc8 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -13,6 +13,7 @@ from datetime import datetime, timedelta, timezone from math import ceil import discord +from dateparser import parse from discord.ext import tasks from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice @@ -520,6 +521,8 @@ class Aurora(commands.Cog): moderator: discord.User | None = None, pagesize: app_commands.Range[int, 1, 20] | None = None, page: int = 1, + before: str | None = None, + after: str | None = None, ephemeral: bool | None = None, inline: bool | None = None, export: bool = False, @@ -536,6 +539,10 @@ class Aurora(commands.Cog): Amount of infractions to list per page page: int Page to select + before: str + List infractions before a certain date + after: str + List infractions after a certain date ephemeral: bool Hide the command response inline: bool @@ -570,6 +577,22 @@ class Aurora(commands.Cog): or 5 ) + if before: + before = parse(before) + if before is None: + return await interaction.response.send_message( + content=error("Invalid date format for `before`."), ephemeral=True + ) + before = before.replace(tzinfo=timezone.utc) + + if after: + after = parse(after) + if after is None: + return await interaction.response.send_message( + content=error("Invalid date format for `after`."), ephemeral=True + ) + after = after.replace(tzinfo=timezone.utc) + await interaction.response.defer(ephemeral=ephemeral) permissions = check_permissions( @@ -586,13 +609,13 @@ class Aurora(commands.Cog): if target: filename = f"moderation_target_{str(target.id)}_{str(interaction.guild.id)}.json" - moderations = await Moderation.find_by_target(interaction.client, interaction.guild.id, target.id) + moderations = await Moderation.find_by_target(bot=interaction.client, guild_id=interaction.guild.id, target=target.id, before=before, after=after) elif moderator: filename = f"moderation_moderator_{str(moderator.id)}_{str(interaction.guild.id)}.json" - moderations = await Moderation.find_by_moderator(interaction.client, interaction.guild.id, moderator.id) + moderations = await Moderation.find_by_moderator(bot=interaction.client, guild_id=interaction.guild.id, moderator=moderator.id, before=before, after=after) else: filename = f"moderation_{str(interaction.guild.id)}.json" - moderations = await Moderation.get_latest(interaction.client, interaction.guild.id) + moderations = await Moderation.get_latest(bot=interaction.client, guild_id=interaction.guild.id, before=before, after=after) if export: try: diff --git a/aurora/info.json b/aurora/info.json index 00d919d..1c60b08 100644 --- a/aurora/info.json +++ b/aurora/info.json @@ -9,7 +9,7 @@ "disabled": false, "min_bot_version": "3.5.0", "min_python_version": [3, 10, 0], - "requirements": ["pydantic", "aiosqlite", "phx-class-registry"], + "requirements": ["pydantic", "aiosqlite", "phx-class-registry", "dateparser"], "tags": [ "mod", "moderate", diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index b49894b..bcadbb2 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -307,13 +307,19 @@ class Moderation(AuroraGuildModel): return results @classmethod - async def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, offset: int = 0, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def get_latest(cls, bot: Red, guild_id: int, before: datetime = None, after: datetime = None, limit: int | None = None, offset: int = 0, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: params = [] query = f"SELECT * FROM moderation_{guild_id} ORDER BY moderation_id DESC" if types: query += f" WHERE moderation_type IN ({', '.join(['?' for _ in types])})" for t in types: params.append(t.key) + if before: + query += " WHERE timestamp < ?" + params.append(before.timestamp()) + if after: + query += " WHERE timestamp > ?" + params.append(after.timestamp()) if limit: query += " LIMIT ? OFFSET ?" params.extend((limit, offset)) @@ -334,22 +340,40 @@ class Moderation(AuroraGuildModel): raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") @classmethod - async def find_by_target(cls, bot: Red, guild_id: int, target: int, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def find_by_target(cls, bot: Red, guild_id: int, target: int, before: datetime = None, after: datetime = None, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE target_id = ?" + params = [target] if types: query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" + for t in types: + params.append(t.key) + if before: + query += " AND timestamp < ?" + params.append(before.timestamp()) + if after: + query += " AND timestamp > ?" + params.append(after.timestamp()) query += " ORDER BY moderation_id DESC;" - return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(target, *[t.key for t in types]) if types else (target,), cursor=cursor) + return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=params, cursor=cursor) @classmethod - async def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, before: datetime = None, after: datetime = None, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE moderator_id = ?" + params = [moderator] if types: query += f" AND moderation_type IN ({', '.join(['?' for _ in types])})" + for t in types: + params.append(t.key) + if before: + query += " AND timestamp < ?" + params.append(before.timestamp()) + if after: + query += " AND timestamp > ?" + params.append(after.timestamp()) query += " ORDER BY moderation_id DESC;" - return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=(moderator, *[t.key for t in types]) if types else (moderator,), cursor=cursor) + return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=params, cursor=cursor) @classmethod async def log( diff --git a/poetry.lock b/poetry.lock index 373a6f5..e8bdc34 100644 --- a/poetry.lock +++ b/poetry.lock @@ -668,6 +668,28 @@ webencodings = "*" doc = ["sphinx", "sphinx_rtd_theme"] test = ["flake8", "isort", "pytest"] +[[package]] +name = "dateparser" +version = "1.2.0" +description = "Date parsing library designed to parse dates from HTML pages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dateparser-1.2.0-py2.py3-none-any.whl", hash = "sha256:0b21ad96534e562920a0083e97fd45fa959882d4162acc358705144520a35830"}, + {file = "dateparser-1.2.0.tar.gz", hash = "sha256:7975b43a4222283e0ae15be7b4999d08c9a70e2d378ac87385b1ccf2cffbbb30"}, +] + +[package.dependencies] +python-dateutil = "*" +pytz = "*" +regex = "<2019.02.19 || >2019.02.19,<2021.8.27 || >2021.8.27" +tzlocal = "*" + +[package.extras] +calendars = ["convertdate", "hijri-converter"] +fasttext = ["fasttext"] +langdetect = ["langdetect"] + [[package]] name = "defusedxml" version = "0.7.1" @@ -2373,6 +2395,34 @@ files = [ {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + +[[package]] +name = "tzlocal" +version = "5.2" +description = "tzinfo object for the local timezone" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"}, + {file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"}, +] + +[package.dependencies] +tzdata = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] + [[package]] name = "urllib3" version = "2.2.1" @@ -2690,4 +2740,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "6d09969e0ad7adff5aa105915c5c9e0354b4b7aceb80b9c2b3fb800bb08f21d4" +content-hash = "bc58f1f72ca73806c414042a78294e73c4119906b57fceb045ab48414928849e" diff --git a/pyproject.toml b/pyproject.toml index 39c6670..d185fe3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,7 @@ beautifulsoup4 = "^4.12.3" markdownify = "^0.12.1" aiosqlite = "^0.20.0" phx-class-registry = "^4.1.0" +dateparser = "^1.2.0" [tool.poetry.group.dev] optional = true -- 2.45.3 From 49cf7c9005826a0daece4ba4033a17cd5fd69ce6 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 10 Aug 2024 13:27:49 -0400 Subject: [PATCH 237/376] feat(aurora): switch from dateparser to dateutil and add on parameter to history command --- aurora/aurora.py | 65 +++++++++++++++++++++++++++++++++++++----------- aurora/info.json | 2 +- poetry.lock | 52 +------------------------------------- pyproject.toml | 1 - 4 files changed, 52 insertions(+), 68 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 58dcbc8..bedd3c1 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -13,7 +13,7 @@ from datetime import datetime, timedelta, timezone from math import ceil import discord -from dateparser import parse +from dateutil.parser import ParserError, parse from discord.ext import tasks from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice @@ -521,6 +521,7 @@ class Aurora(commands.Cog): moderator: discord.User | None = None, pagesize: app_commands.Range[int, 1, 20] | None = None, page: int = 1, + on: str | None = None, before: str | None = None, after: str | None = None, ephemeral: bool | None = None, @@ -539,6 +540,8 @@ class Aurora(commands.Cog): Amount of infractions to list per page page: int Page to select + on: str + List infractions on a certain date before: str List infractions before a certain date after: str @@ -577,21 +580,53 @@ class Aurora(commands.Cog): or 5 ) - if before: - before = parse(before) - if before is None: - return await interaction.response.send_message( - content=error("Invalid date format for `before`."), ephemeral=True - ) - before = before.replace(tzinfo=timezone.utc) + if before and not on: + try: + before = parse(before) + except (ParserError, OverflowError) as e: + if e == ParserError: + await interaction.response.send_message( + content=error("Invalid date format for `before` parameter!"), ephemeral=True + ) + return + if e == OverflowError: + await interaction.response.send_message( + content=error("Date is too far in the future!"), ephemeral=True + ) + return - if after: - after = parse(after) - if after is None: - return await interaction.response.send_message( - content=error("Invalid date format for `after`."), ephemeral=True - ) - after = after.replace(tzinfo=timezone.utc) + if after and not on: + try: + after = parse(after) + except (ParserError, OverflowError) as e: + if e == ParserError: + await interaction.response.send_message( + content=error("Invalid date format for `after` parameter!"), ephemeral=True + ) + return + if e == OverflowError: + await interaction.response.send_message( + content=error("Date is too far in the future!"), ephemeral=True + ) + return + + if on: + try: + on = parse(on) + except (ParserError, OverflowError) as e: + if e == ParserError: + await interaction.response.send_message( + content=error("Invalid date format for `on` parameter!"), ephemeral=True + ) + return + if e == OverflowError: + await interaction.response.send_message( + content=error("Date is too far in the future!"), ephemeral=True + ) + return + + before = on + timedelta(days=1) + after = on - timedelta(days=1) await interaction.response.defer(ephemeral=ephemeral) diff --git a/aurora/info.json b/aurora/info.json index 1c60b08..00d919d 100644 --- a/aurora/info.json +++ b/aurora/info.json @@ -9,7 +9,7 @@ "disabled": false, "min_bot_version": "3.5.0", "min_python_version": [3, 10, 0], - "requirements": ["pydantic", "aiosqlite", "phx-class-registry", "dateparser"], + "requirements": ["pydantic", "aiosqlite", "phx-class-registry"], "tags": [ "mod", "moderate", diff --git a/poetry.lock b/poetry.lock index e8bdc34..373a6f5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -668,28 +668,6 @@ webencodings = "*" doc = ["sphinx", "sphinx_rtd_theme"] test = ["flake8", "isort", "pytest"] -[[package]] -name = "dateparser" -version = "1.2.0" -description = "Date parsing library designed to parse dates from HTML pages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "dateparser-1.2.0-py2.py3-none-any.whl", hash = "sha256:0b21ad96534e562920a0083e97fd45fa959882d4162acc358705144520a35830"}, - {file = "dateparser-1.2.0.tar.gz", hash = "sha256:7975b43a4222283e0ae15be7b4999d08c9a70e2d378ac87385b1ccf2cffbbb30"}, -] - -[package.dependencies] -python-dateutil = "*" -pytz = "*" -regex = "<2019.02.19 || >2019.02.19,<2021.8.27 || >2021.8.27" -tzlocal = "*" - -[package.extras] -calendars = ["convertdate", "hijri-converter"] -fasttext = ["fasttext"] -langdetect = ["langdetect"] - [[package]] name = "defusedxml" version = "0.7.1" @@ -2395,34 +2373,6 @@ files = [ {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] -[[package]] -name = "tzdata" -version = "2024.1" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -files = [ - {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, - {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, -] - -[[package]] -name = "tzlocal" -version = "5.2" -description = "tzinfo object for the local timezone" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"}, - {file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"}, -] - -[package.dependencies] -tzdata = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] - [[package]] name = "urllib3" version = "2.2.1" @@ -2740,4 +2690,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "bc58f1f72ca73806c414042a78294e73c4119906b57fceb045ab48414928849e" +content-hash = "6d09969e0ad7adff5aa105915c5c9e0354b4b7aceb80b9c2b3fb800bb08f21d4" diff --git a/pyproject.toml b/pyproject.toml index d185fe3..39c6670 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,6 @@ beautifulsoup4 = "^4.12.3" markdownify = "^0.12.1" aiosqlite = "^0.20.0" phx-class-registry = "^4.1.0" -dateparser = "^1.2.0" [tool.poetry.group.dev] optional = true -- 2.45.3 From 14dc256919e519461c02ec7d2eff6e6869c6843f Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 10 Aug 2024 13:32:37 -0400 Subject: [PATCH 238/376] fix(aurora); log when Modereation.execute() fails with an operationalerror --- aurora/models/moderation.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index bcadbb2..d8d930a 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -289,7 +289,12 @@ class Moderation(AuroraGuildModel): else: no_cursor = False - await cursor.execute(query, parameters) + try: + await cursor.execute(query, parameters) + except OperationalError as e: + logger.error("Error executing query: \"%s\" with parameters \"%s\"\nError:\n%s", + query, parameters, e) + raise OperationalError(f"Error executing query: \"{query}\" with parameters \"{parameters}\"") from e results = await cursor.fetchall() await database.commit() if no_cursor: -- 2.45.3 From 14750787b2df1e7570562a97279beae22396308a Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 10 Aug 2024 13:34:15 -0400 Subject: [PATCH 239/376] fix(aurora): cast timestamps to integers --- aurora/models/moderation.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index d8d930a..6d00fc2 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -321,10 +321,10 @@ class Moderation(AuroraGuildModel): params.append(t.key) if before: query += " WHERE timestamp < ?" - params.append(before.timestamp()) + params.append(int(before.timestamp())) if after: query += " WHERE timestamp > ?" - params.append(after.timestamp()) + params.append(int(after.timestamp())) if limit: query += " LIMIT ? OFFSET ?" params.extend((limit, offset)) @@ -354,10 +354,10 @@ class Moderation(AuroraGuildModel): params.append(t.key) if before: query += " AND timestamp < ?" - params.append(before.timestamp()) + params.append(int(before.timestamp())) if after: query += " AND timestamp > ?" - params.append(after.timestamp()) + params.append(int(after.timestamp())) query += " ORDER BY moderation_id DESC;" return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=params, cursor=cursor) @@ -372,10 +372,10 @@ class Moderation(AuroraGuildModel): params.append(t.key) if before: query += " AND timestamp < ?" - params.append(before.timestamp()) + params.append(int(before.timestamp())) if after: query += " AND timestamp > ?" - params.append(after.timestamp()) + params.append(int(after.timestamp())) query += " ORDER BY moderation_id DESC;" return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=params, cursor=cursor) -- 2.45.3 From f3246366ffa484fc53c4c2aa52b47a7f128ba9c3 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 10 Aug 2024 13:42:15 -0400 Subject: [PATCH 240/376] fix(aurora): fixed Moderation.get_latest() breaking when using only before and after, and no other kwargs --- aurora/aurora.py | 2 +- aurora/models/moderation.py | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index bedd3c1..c707e6a 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -44,7 +44,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["SeaswimmerTheFsh"] - __version__ = "2.4.0" + __version__ = "2.4.1" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 6d00fc2..111bb5b 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -315,16 +315,22 @@ class Moderation(AuroraGuildModel): async def get_latest(cls, bot: Red, guild_id: int, before: datetime = None, after: datetime = None, limit: int | None = None, offset: int = 0, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: params = [] query = f"SELECT * FROM moderation_{guild_id} ORDER BY moderation_id DESC" + conditions = [] + if types: - query += f" WHERE moderation_type IN ({', '.join(['?' for _ in types])})" + conditions.append(f"moderation_type IN ({', '.join(['?' for _ in types])})") for t in types: params.append(t.key) if before: - query += " WHERE timestamp < ?" + conditions.append("timestamp < ?") params.append(int(before.timestamp())) if after: - query += " WHERE timestamp > ?" + conditions.append("timestamp > ?") params.append(int(after.timestamp())) + + if conditions: + query += " WHERE " + " AND ".join(conditions) + if limit: query += " LIMIT ? OFFSET ?" params.extend((limit, offset)) -- 2.45.3 From cb424ed7222abfa9e537f46f899c3e58c64b8f83 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 10 Aug 2024 13:44:18 -0400 Subject: [PATCH 241/376] fix(aurora): fixed another OperationalError --- aurora/models/moderation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 111bb5b..c586a66 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -314,7 +314,7 @@ class Moderation(AuroraGuildModel): @classmethod async def get_latest(cls, bot: Red, guild_id: int, before: datetime = None, after: datetime = None, limit: int | None = None, offset: int = 0, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: params = [] - query = f"SELECT * FROM moderation_{guild_id} ORDER BY moderation_id DESC" + query = f"SELECT * FROM moderation_{guild_id}" conditions = [] if types: @@ -334,7 +334,7 @@ class Moderation(AuroraGuildModel): if limit: query += " LIMIT ? OFFSET ?" params.extend((limit, offset)) - query += ";" + query += " ORDER BY moderation_id DESC;" return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=tuple(params) if params else (), cursor=cursor) @classmethod -- 2.45.3 From 2e3640b738d0041fad6ad6d1d006a50c3af18d1f Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 10 Aug 2024 13:50:47 -0400 Subject: [PATCH 242/376] fix(aurora): make `on` more accurate --- aurora/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index c707e6a..2e07250 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -625,8 +625,8 @@ class Aurora(commands.Cog): ) return - before = on + timedelta(days=1) - after = on - timedelta(days=1) + before = datetime.combine(on, datetime.max.time()) + after = datetime.combhine(on, datetime.min.time()) await interaction.response.defer(ephemeral=ephemeral) -- 2.45.3 From de06490050333535c0d528bd5d789e488d6bea62 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Sat, 10 Aug 2024 13:51:17 -0400 Subject: [PATCH 243/376] fix(aurora): typo --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 2e07250..3e4ab35 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -626,7 +626,7 @@ class Aurora(commands.Cog): return before = datetime.combine(on, datetime.max.time()) - after = datetime.combhine(on, datetime.min.time()) + after = datetime.combine(on, datetime.min.time()) await interaction.response.defer(ephemeral=ephemeral) -- 2.45.3 From 9c345ed96b048e5f60eb8fa022e6387c04a3f90d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 17:39:13 -0400 Subject: [PATCH 244/376] feat(aurora): add per-type configuration options and a menu to configure them none of the options do anything yet, this is just creating the configuration keys and the menu to modify them --- aurora/aurora.py | 20 +++++++++++-- aurora/menus/types.py | 58 +++++++++++++++++++++++++++++++++++++ aurora/models/type.py | 4 +-- aurora/utilities/config.py | 10 +++++++ aurora/utilities/factory.py | 36 +++++++++++++++++++++++ 5 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 aurora/menus/types.py diff --git a/aurora/aurora.py b/aurora/aurora.py index 3e4ab35..4e5f36a 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -15,6 +15,7 @@ from math import ceil import discord from dateutil.parser import ParserError, parse from discord.ext import tasks +from menus.types import Types from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red @@ -31,7 +32,7 @@ from .models.change import Change from .models.moderation import Moderation from .models.type import type_registry from .utilities.config import config, register_config -from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, overrides_embed +from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, overrides_embed, type_embed from .utilities.json import dump from .utilities.logger import logger from .utilities.moderate import moderate @@ -44,7 +45,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["SeaswimmerTheFsh"] - __version__ = "2.4.1" + __version__ = "2.4.2" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -1115,6 +1116,21 @@ class Aurora(commands.Cog): msg = await ctx.send(embed=await guild_embed(ctx)) await msg.edit(view=Guild(ctx, msg, 60)) + @aurora_settings.command(name="type") + @commands.admin_or_permissions(manage_guild=True) + @commands.guild_only() + async def aurora_settings_type(self, ctx: commands.Context, moderation_type: str): + """Manage configuration options for specific moderation types. + + See [the documentation](https://seacogs.coastalcommits.com/Aurora/Types) for a list of built-in moderation types.""" + registered_type = type_registry.get(moderation_type) + if not registered_type: + types = "`, `".join(type_registry.keys()) + await ctx.send(error("`moderation_type` is not a valid moderation type.\nValid types are:\n" + types)) + return + msg = await ctx.send(embed=await type_embed(ctx, registered_type)) + await msg.edit(view=Types(ctx, msg, registered_type)) + @aurora_settings.command(name="addrole", aliases=["removerole"]) @commands.admin_or_permissions(manage_guild=True) @commands.guild_only() diff --git a/aurora/menus/types.py b/aurora/menus/types.py new file mode 100644 index 0000000..8946c28 --- /dev/null +++ b/aurora/menus/types.py @@ -0,0 +1,58 @@ +from discord import ButtonStyle, Interaction, Message, ui +from redbot.core import commands + +from ..models.type import Type +from ..utilities.config import config +from ..utilities.factory import type_embed + + +class Types(ui.View): + def __init__(self, ctx: commands.Context, message: Message, moderation_type: Type, timeout: int | None = None): + super().__init__() + self.ctx = ctx + self.message = message + self.type = moderation_type + self.timeout = timeout + + async def on_timeout(self): + await self.message.edit(view=None) + + @ui.button(label="Show in History", style=ButtonStyle.green, row=0) + async def show_in_history(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument + if not interaction.user.guild_permissions.manage_guild and not interaction.user.guild_permissions.administrator: + await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) + return + await interaction.response.defer() + current_setting = await config.custom("type", interaction.guild.id, self.type.key).show_in_history() + await config.custom("type", interaction.guild.id, self.type.key).show_in_history.set(not current_setting) + await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) + + @ui.button(label="Show Moderator", style=ButtonStyle.green, row=0) + async def show_moderator(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument + if not interaction.user.guild_permissions.manage_guild and not interaction.user.guild_permissions.administrator: + await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) + return + await interaction.response.defer() + current_setting = await config.custom("type", interaction.guild.id, self.type.key).show_moderator() + await config.custom("type", interaction.guild.id, self.type.key).show_moderator.set(not current_setting) + await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) + + @ui.button(label="Use Discord Permissions", style=ButtonStyle.green, row=0) + async def use_discord_permissions(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument + if not interaction.user.guild_permissions.manage_guild and not interaction.user.guild_permissions.administrator: + await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) + return + await interaction.response.defer() + current_setting = await config.custom("type", interaction.guild.id, self.type.key).use_discord_permissions() + await config.custom("type", interaction.guild.id, self.type.key).use_discord_permissions.set(not current_setting) + await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) + + @ui.button(label="DM Users", style=ButtonStyle.green, row=0) + async def dm_users(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument + if not interaction.user.guild_permissions.manage_guild and not interaction.user.guild_permissions.administrator: + await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) + return + await interaction.response.defer() + current_setting = await config.custom("type", interaction.guild.id, self.type.key).dm_users() + await config.custom("type", interaction.guild.id, self.type.key).dm_users.set(not current_setting) + await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) diff --git a/aurora/models/type.py b/aurora/models/type.py index a979d2b..d5cf568 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -1,12 +1,12 @@ from abc import abstractmethod -from typing import Any, List, Tuple +from typing import Any, Dict, Tuple from class_registry import AutoRegister, ClassRegistry from discord import Interaction, Member, User from discord.abc import Messageable from redbot.core import commands -type_registry: List['Type'] = ClassRegistry(attr_name='key', unique=True) +type_registry: Dict['str', 'Type'] = ClassRegistry(attr_name='key', unique=True) class Type(metaclass=AutoRegister(type_registry)): """This is a base class for moderation types. diff --git a/aurora/utilities/config.py b/aurora/utilities/config.py index 0b5e503..5fa9f19 100644 --- a/aurora/utilities/config.py +++ b/aurora/utilities/config.py @@ -27,3 +27,13 @@ def register_config(config_obj: Config): history_inline_pagesize=None, auto_evidenceformat=None, ) + + moderation_type = { + "show_in_history": bool, + "show_moderator": bool, + "use_discord_permissions": bool, + "dm_users": bool, + } + + config_obj.init_custom("type", 2) + config_obj.register_custom("type", **moderation_type) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index e90af3c..dc38918 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -544,3 +544,39 @@ async def immune_embed(ctx: commands.Context) -> Embed: e.description += "\n\n" + immune_str return e + +async def type_embed(ctx: commands.Context, moderation_type = Type) -> Embed: + """Generates a configuration menu field value for a guild's settings.""" + + type_settings = { + "show_in_history": await config.custom("type", ctx.guild.id, moderation_type.key).show_in_history(), + "show_moderator": await config.custom("type", ctx.guild.id, moderation_type.key).show_moderator(), + "use_discord_permissions": await config.custom("type", ctx.guild.id, moderation_type.key).use_discord_permissions(), + "dm_users": await config.custom("type", ctx.guild.id, moderation_type.key).dm_users(), + } + + guild_str = [ + "- " + + bold("Show in History: ") + + get_bool_emoji(type_settings["show_in_history"]), + "- " + + bold("Show Moderator: ") + + get_bool_emoji(type_settings["show_moderator"]), + "- " + + bold("Use Discord Permissions: ") + + get_bool_emoji(type_settings["use_discord_permissions"]), + "- " + + bold("DM Users: ") + + get_bool_emoji(type_settings["dm_users"]), + ] + guild_str = "\n".join(guild_str) + + e = await _config(ctx) + e.title += ": Server Configuration" + e.description = ( + """ + Use the buttons below to manage Aurora's server configuration.\n + """ + + guild_str + ) + return e -- 2.45.3 From 9726b1423cf2eff32e9a92a2b818a83ba47277e0 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 17:40:17 -0400 Subject: [PATCH 245/376] fix(aurora): fixed a `ModuleNotFoundError` being caused by a typo --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 4e5f36a..20bff21 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -15,7 +15,6 @@ from math import ceil import discord from dateutil.parser import ParserError, parse from discord.ext import tasks -from menus.types import Types from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red @@ -28,6 +27,7 @@ from .menus.addrole import Addrole from .menus.guild import Guild from .menus.immune import Immune from .menus.overrides import Overrides +from .menus.types import Types from .models.change import Change from .models.moderation import Moderation from .models.type import type_registry -- 2.45.3 From c134a3ed181e285cd52501a8210811e99d12f8ce Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 17:42:46 -0400 Subject: [PATCH 246/376] fix(aurora): maybe fixed a TypeError? --- aurora/menus/types.py | 16 ++++++++-------- aurora/utilities/config.py | 4 ++-- aurora/utilities/factory.py | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/aurora/menus/types.py b/aurora/menus/types.py index 8946c28..3850a6a 100644 --- a/aurora/menus/types.py +++ b/aurora/menus/types.py @@ -23,8 +23,8 @@ class Types(ui.View): await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) return await interaction.response.defer() - current_setting = await config.custom("type", interaction.guild.id, self.type.key).show_in_history() - await config.custom("type", interaction.guild.id, self.type.key).show_in_history.set(not current_setting) + current_setting = await config.custom("types", interaction.guild.id, self.type.key).show_in_history() + await config.custom("types", interaction.guild.id, self.type.key).show_in_history.set(not current_setting) await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) @ui.button(label="Show Moderator", style=ButtonStyle.green, row=0) @@ -33,8 +33,8 @@ class Types(ui.View): await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) return await interaction.response.defer() - current_setting = await config.custom("type", interaction.guild.id, self.type.key).show_moderator() - await config.custom("type", interaction.guild.id, self.type.key).show_moderator.set(not current_setting) + current_setting = await config.custom("types", interaction.guild.id, self.type.key).show_moderator() + await config.custom("types", interaction.guild.id, self.type.key).show_moderator.set(not current_setting) await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) @ui.button(label="Use Discord Permissions", style=ButtonStyle.green, row=0) @@ -43,8 +43,8 @@ class Types(ui.View): await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) return await interaction.response.defer() - current_setting = await config.custom("type", interaction.guild.id, self.type.key).use_discord_permissions() - await config.custom("type", interaction.guild.id, self.type.key).use_discord_permissions.set(not current_setting) + current_setting = await config.custom("types", interaction.guild.id, self.type.key).use_discord_permissions() + await config.custom("types", interaction.guild.id, self.type.key).use_discord_permissions.set(not current_setting) await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) @ui.button(label="DM Users", style=ButtonStyle.green, row=0) @@ -53,6 +53,6 @@ class Types(ui.View): await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) return await interaction.response.defer() - current_setting = await config.custom("type", interaction.guild.id, self.type.key).dm_users() - await config.custom("type", interaction.guild.id, self.type.key).dm_users.set(not current_setting) + current_setting = await config.custom("types", interaction.guild.id, self.type.key).dm_users() + await config.custom("types", interaction.guild.id, self.type.key).dm_users.set(not current_setting) await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) diff --git a/aurora/utilities/config.py b/aurora/utilities/config.py index 5fa9f19..068cb20 100644 --- a/aurora/utilities/config.py +++ b/aurora/utilities/config.py @@ -35,5 +35,5 @@ def register_config(config_obj: Config): "dm_users": bool, } - config_obj.init_custom("type", 2) - config_obj.register_custom("type", **moderation_type) + config_obj.init_custom("types", 2) + config_obj.register_custom("types", **moderation_type) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index dc38918..6bc5cd3 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -549,10 +549,10 @@ async def type_embed(ctx: commands.Context, moderation_type = Type) -> Embed: """Generates a configuration menu field value for a guild's settings.""" type_settings = { - "show_in_history": await config.custom("type", ctx.guild.id, moderation_type.key).show_in_history(), - "show_moderator": await config.custom("type", ctx.guild.id, moderation_type.key).show_moderator(), - "use_discord_permissions": await config.custom("type", ctx.guild.id, moderation_type.key).use_discord_permissions(), - "dm_users": await config.custom("type", ctx.guild.id, moderation_type.key).dm_users(), + "show_in_history": await config.custom("types", ctx.guild.id, moderation_type.key).show_in_history(), + "show_moderator": await config.custom("types", ctx.guild.id, moderation_type.key).show_moderator(), + "use_discord_permissions": await config.custom("types", ctx.guild.id, moderation_type.key).use_discord_permissions(), + "dm_users": await config.custom("types", ctx.guild.id, moderation_type.key).dm_users(), } guild_str = [ -- 2.45.3 From 290ac5947f0f7229d38c234a6f43cc5520568c60 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 17:44:39 -0400 Subject: [PATCH 247/376] fix(aurora): actually fixed the previous TypeError --- aurora/utilities/config.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aurora/utilities/config.py b/aurora/utilities/config.py index 068cb20..4820ee7 100644 --- a/aurora/utilities/config.py +++ b/aurora/utilities/config.py @@ -29,10 +29,10 @@ def register_config(config_obj: Config): ) moderation_type = { - "show_in_history": bool, - "show_moderator": bool, - "use_discord_permissions": bool, - "dm_users": bool, + "show_in_history": None, + "show_moderator": None, + "use_discord_permissions": None, + "dm_users": None, } config_obj.init_custom("types", 2) -- 2.45.3 From 7c69a894422e0db8a9d1771b0a21432aebd80ad4 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 17:44:48 -0400 Subject: [PATCH 248/376] feat(aurora): added reset button to the types menu --- aurora/menus/types.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/aurora/menus/types.py b/aurora/menus/types.py index 3850a6a..f943d90 100644 --- a/aurora/menus/types.py +++ b/aurora/menus/types.py @@ -56,3 +56,12 @@ class Types(ui.View): current_setting = await config.custom("types", interaction.guild.id, self.type.key).dm_users() await config.custom("types", interaction.guild.id, self.type.key).dm_users.set(not current_setting) await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) + + @ui.button(label="Reset", style=ButtonStyle.red, row=1) + async def reset(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument + if not interaction.user.guild_permissions.manage_guild and not interaction.user.guild_permissions.administrator: + await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) + return + await interaction.response.defer() + await config.custom("types", interaction.guild.id, self.type.key).clear() + await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) -- 2.45.3 From bf36e9922480f62f8a5750db63e7cf1d9c47567b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 17:48:01 -0400 Subject: [PATCH 249/376] fix(aurora): fixed a registry error --- aurora/aurora.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 20bff21..63900ef 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -13,6 +13,7 @@ from datetime import datetime, timedelta, timezone from math import ceil import discord +from class_registry.registry import RegistryKeyError from dateutil.parser import ParserError, parse from discord.ext import tasks from redbot.core import app_commands, commands, data_manager @@ -1122,9 +1123,10 @@ class Aurora(commands.Cog): async def aurora_settings_type(self, ctx: commands.Context, moderation_type: str): """Manage configuration options for specific moderation types. - See [the documentation](https://seacogs.coastalcommits.com/Aurora/Types) for a list of built-in moderation types.""" - registered_type = type_registry.get(moderation_type) - if not registered_type: + See [the documentation](https://seacogs.coastalcommits.com/Aurora/Types) for a list of built-in moderation types, or run this command with a junk argument (`awasd` or something) to see a list of valid types.""" + try: + registered_type = type_registry.get(moderation_type) + except RegistryKeyError: types = "`, `".join(type_registry.keys()) await ctx.send(error("`moderation_type` is not a valid moderation type.\nValid types are:\n" + types)) return -- 2.45.3 From 08278c2de4a43a5d1372b0e4592c631aa10a51aa Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 17:49:51 -0400 Subject: [PATCH 250/376] fix(aurora): fixed some formatting --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 63900ef..682bd11 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1128,7 +1128,7 @@ class Aurora(commands.Cog): registered_type = type_registry.get(moderation_type) except RegistryKeyError: types = "`, `".join(type_registry.keys()) - await ctx.send(error("`moderation_type` is not a valid moderation type.\nValid types are:\n" + types)) + await ctx.send(error(f"`{moderation_type}` is not a valid moderation type.\nValid types are:\n`{types}`")) return msg = await ctx.send(embed=await type_embed(ctx, registered_type)) await msg.edit(view=Types(ctx, msg, registered_type)) -- 2.45.3 From 4d408ff616be05529f4c151f848068718370e81e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 18:13:04 -0400 Subject: [PATCH 251/376] feat(aurora): implemented the per-type configuration options so they actually do something --- aurora/aurora.py | 27 ++++++++++++++++++++++++--- aurora/utilities/factory.py | 14 ++++++++++---- aurora/utilities/moderate.py | 13 ++++++++----- aurora/utilities/utils.py | 10 ++++++++-- 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 682bd11..7a0f940 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -526,6 +526,7 @@ class Aurora(commands.Cog): on: str | None = None, before: str | None = None, after: str | None = None, + types: str | None = None, ephemeral: bool | None = None, inline: bool | None = None, export: bool = False, @@ -548,6 +549,8 @@ class Aurora(commands.Cog): List infractions before a certain date after: str List infractions after a certain date + types: bool + List infractions of specific types, comma separated ephemeral: bool Hide the command response inline: bool @@ -644,15 +647,33 @@ class Aurora(commands.Cog): ) return + type_list = [] + registry_values = type_registry.values() + if types: + for t in types.split(","): + stripped = t.strip().lower() + if stripped == "all": + type_list.clear() + type_list = registry_values + break + try: + type_list.append(type_registry[stripped]) + except RegistryKeyError: + continue + else: + for t in registry_values: + if await config.custom("types", interaction.guild.id, t.key).show_in_history(): + type_list.append(t) + if target: filename = f"moderation_target_{str(target.id)}_{str(interaction.guild.id)}.json" - moderations = await Moderation.find_by_target(bot=interaction.client, guild_id=interaction.guild.id, target=target.id, before=before, after=after) + moderations = await Moderation.find_by_target(bot=interaction.client, guild_id=interaction.guild.id, target=target.id, before=before, after=after, types=type_list) elif moderator: filename = f"moderation_moderator_{str(moderator.id)}_{str(interaction.guild.id)}.json" - moderations = await Moderation.find_by_moderator(bot=interaction.client, guild_id=interaction.guild.id, moderator=moderator.id, before=before, after=after) + moderations = await Moderation.find_by_moderator(bot=interaction.client, guild_id=interaction.guild.id, moderator=moderator.id, before=before, after=after, types=type_list) else: filename = f"moderation_{str(interaction.guild.id)}.json" - moderations = await Moderation.get_latest(bot=interaction.client, guild_id=interaction.guild.id, before=before, after=after) + moderations = await Moderation.get_latest(bot=interaction.client, guild_id=interaction.guild.id, before=before, after=after, types=type_list) if export: try: diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 6bc5cd3..55c8f47 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -64,7 +64,11 @@ async def message_factory( timestamp=datetime.now(), ) - if await config.guild(guild).show_moderator() and moderator is not None: + show_moderator = await config.custom("types", guild.id, moderation_type.key).show_moderator() + if show_moderator is None: + show_moderator = await config.guild(guild).show_moderator() + + if show_moderator and moderator is not None: embed.add_field( name="Moderator", value=f"`{moderator.name} ({moderator.id})`", inline=False ) @@ -572,10 +576,12 @@ async def type_embed(ctx: commands.Context, moderation_type = Type) -> Embed: guild_str = "\n".join(guild_str) e = await _config(ctx) - e.title += ": Server Configuration" + e.title += f": {moderation_type.string} Configuration" e.description = ( - """ - Use the buttons below to manage Aurora's server configuration.\n + f""" + Use the buttons below to manage Aurora's configuration for the {moderation_type.string} moderation type. + If an option has a question mark (\N{BLACK QUESTION MARK ORNAMENT}\N{VARIATION SELECTOR-16}) next to it, Aurora will default to the guild level setting instead. + See `{ctx.prefix}aurora set guild` for more information.\n """ + guild_str ) diff --git a/aurora/utilities/moderate.py b/aurora/utilities/moderate.py index 1a8e085..7a0a7a2 100644 --- a/aurora/utilities/moderate.py +++ b/aurora/utilities/moderate.py @@ -28,13 +28,16 @@ async def moderate(ctx: Union[commands.Context, discord.Interaction], target: di ctx = await commands.Context.from_interaction(interaction) if isinstance(interaction.command, app_commands.ContextMenu): ctx.author = interaction.user - if not await check_moddable(target, ctx, permissions): + if not await check_moddable(target=target, ctx=ctx, permissions=permissions, moderation_type=moderation_type): return if silent is None: - silent = not await config.guild(ctx.guild).dm_users() + dm_users = await config.custom("types", ctx.guild.id, moderation_type.key).dm_users() + if dm_users is None: + dm_users = await config.guild(ctx.guild).dm_users() + silent = not dm_users return await moderation_type.handler( - ctx, - target, - silent, + ctx=ctx, + target=target, + silent=silent, **kwargs ) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 467d66f..9d7d508 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -9,6 +9,7 @@ from discord.errors import Forbidden from redbot.core import commands, data_manager from redbot.core.utils.chat_formatting import error +from ..models.type import Type from ..utilities.config import config from ..utilities.json import dumps from ..utilities.logger import logger @@ -43,10 +44,15 @@ def check_permissions( async def check_moddable( - target: Union[User, Member, TextChannel], ctx: commands.Context, permissions: Tuple[str] + target: Union[User, Member, TextChannel], ctx: commands.Context, permissions: Tuple[str], moderation_type: Type, ) -> bool: """Checks if a moderator can moderate a target.""" is_channel = isinstance(target, TextChannel) + + use_discord_permissions = await config.custom("types", ctx.guild.id, moderation_type.key).use_discord_permissions() + if use_discord_permissions is None: + use_discord_permissions = await config.guild(ctx.guild).use_discord_permissions() + if check_permissions(ctx.bot.user, permissions, guild=ctx.guild): await ctx.send( error( @@ -56,7 +62,7 @@ async def check_moddable( ) return False - if await config.guild(ctx.guild).use_discord_permissions() is True: + if use_discord_permissions is True: if check_permissions(ctx.author, permissions, guild=ctx.guild): await ctx.send( error( -- 2.45.3 From d546fb3371cd1369440fa8a4691bd52c3ab77fe7 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 18:15:15 -0400 Subject: [PATCH 252/376] misc(aurora): minor formatting fix --- aurora/utilities/factory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 55c8f47..95ea1ca 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -576,10 +576,10 @@ async def type_embed(ctx: commands.Context, moderation_type = Type) -> Embed: guild_str = "\n".join(guild_str) e = await _config(ctx) - e.title += f": {moderation_type.string} Configuration" + e.title += f": {moderation_type.string.title()} Configuration" e.description = ( f""" - Use the buttons below to manage Aurora's configuration for the {moderation_type.string} moderation type. + Use the buttons below to manage Aurora's configuration for the {bold(moderation_type.string)} moderation type. If an option has a question mark (\N{BLACK QUESTION MARK ORNAMENT}\N{VARIATION SELECTOR-16}) next to it, Aurora will default to the guild level setting instead. See `{ctx.prefix}aurora set guild` for more information.\n """ -- 2.45.3 From 8822d1714e270962349dda4e2061dae8b5dc0c8c Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 18:18:34 -0400 Subject: [PATCH 253/376] misc(aurora): make show_in_history default to True --- aurora/aurora.py | 2 +- aurora/utilities/config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 7a0f940..629f62e 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -662,7 +662,7 @@ class Aurora(commands.Cog): continue else: for t in registry_values: - if await config.custom("types", interaction.guild.id, t.key).show_in_history(): + if await config.custom("types", interaction.guild.id, t.key).show_in_history() is True: type_list.append(t) if target: diff --git a/aurora/utilities/config.py b/aurora/utilities/config.py index 4820ee7..14d5e04 100644 --- a/aurora/utilities/config.py +++ b/aurora/utilities/config.py @@ -29,7 +29,7 @@ def register_config(config_obj: Config): ) moderation_type = { - "show_in_history": None, + "show_in_history": True, "show_moderator": None, "use_discord_permissions": None, "dm_users": None, -- 2.45.3 From cbd82f8572c40ca79d1e701741e45fb8e5a41a94 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 18:50:07 -0400 Subject: [PATCH 254/376] fix(aurora): minor changes to the aurora importer and also fixed a bug in the Moderation.get_latest method --- aurora/aurora.py | 4 +++- aurora/importers/aurora.py | 10 ++++------ aurora/models/moderation.py | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 629f62e..3966949 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1187,12 +1187,14 @@ class Aurora(commands.Cog): and ctx.message.attachments[0].content_type == "application/json; charset=utf-8" ): + file = await ctx.message.attachments[0].read() + data: list[dict] = sorted(json.loads(file), key=lambda x: x["moderation_id"]) message = await ctx.send( warning( "Are you sure you want to import moderations from another bot?\n**This will overwrite any moderations that already exist in this guild's moderation table.**\n*The import process will block the rest of your bot until it is complete.*" ) ) - await message.edit(view=ImportAuroraView(60, ctx, message)) + await message.edit(view=ImportAuroraView(60, ctx, message, data)) else: await ctx.send(error("Please provide a valid Aurora export file.")) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 9bd4f4b..f34a7b3 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -2,7 +2,7 @@ import json import os from time import time -from typing import Dict +from typing import Dict, List from discord import ButtonStyle, File, Interaction, Message, ui from redbot.core import commands, data_manager @@ -15,10 +15,11 @@ from ..utilities.utils import create_guild_table, timedelta_from_string class ImportAuroraView(ui.View): - def __init__(self, timeout, ctx, message): + def __init__(self, timeout, ctx, message, data: List[Dict[str, any]]): super().__init__() self.ctx: commands.Context = ctx self.message: Message = message + self.data: List[Dict[str, any]] = data @ui.button(label="Yes", style=ButtonStyle.success) async def import_button_y( @@ -38,12 +39,9 @@ class ImportAuroraView(ui.View): await interaction.edit_original_response(content="Importing moderations...") - file = await self.ctx.message.attachments[0].read() - data: list[dict] = sorted(json.loads(file), key=lambda x: x["moderation_id"]) - failed_cases = [] - for case in data: + for case in self.data: if case["moderation_id"] == 0: continue diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index c586a66..e2217c4 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -331,10 +331,12 @@ class Moderation(AuroraGuildModel): if conditions: query += " WHERE " + " AND ".join(conditions) + query += " ORDER BY moderation_id DESC" + if limit: query += " LIMIT ? OFFSET ?" params.extend((limit, offset)) - query += " ORDER BY moderation_id DESC;" + query += ";" return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=tuple(params) if params else (), cursor=cursor) @classmethod -- 2.45.3 From 1bc6412b070bcdffc532bb34add73a36d254ba54 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 18:56:57 -0400 Subject: [PATCH 255/376] misc(aurora): version bump to 3.0.0-indev1 --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 3966949..249e678 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["SeaswimmerTheFsh"] - __version__ = "2.4.2" + __version__ = "3.0.0-indev1" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): -- 2.45.3 From 8bb92230549fbe8a6de429717ac78201d0a6d192 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 18:57:48 -0400 Subject: [PATCH 256/376] misc(aurora): updated my own name --- aurora/aurora.py | 2 +- aurora/info.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 249e678..7a27e24 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -45,7 +45,7 @@ class Aurora(commands.Cog): It is heavily inspired by GalacticBot, and is designed to be a more user-friendly alternative to Red's core Mod cogs. This cog stores all of its data in an SQLite database.""" - __author__ = ["SeaswimmerTheFsh"] + __author__ = ["Seaswimmer"] __version__ = "3.0.0-indev1" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" diff --git a/aurora/info.json b/aurora/info.json index 00d919d..fa80f99 100644 --- a/aurora/info.json +++ b/aurora/info.json @@ -1,5 +1,5 @@ { - "author" : ["SeaswimmerTheFsh (seasw.)"], + "author" : ["Seaswimmer (seasw.)"], "install_msg" : "Thank you for installing Aurora!\nMost of this cog's functionality requires enabling slash commands.\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).", "name" : "Aurora", "short" : "A full replacement for Red's core Mod cogs.", -- 2.45.3 From 85dbb6cc88755d27914e0e5a834d6fb757c1dc77 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 19:45:14 -0400 Subject: [PATCH 257/376] fix(aurora): export all moderation types --- aurora/aurora.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aurora/aurora.py b/aurora/aurora.py index 7a27e24..abc8e76 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -647,6 +647,9 @@ class Aurora(commands.Cog): ) return + if export and not types: + types = 'all' + type_list = [] registry_values = type_registry.values() if types: -- 2.45.3 From 818ff810eafa51dadac0b94c56fca8e62de3db65 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 19:52:35 -0400 Subject: [PATCH 258/376] misc(aurora): removed an old kwarg from the moderate function docstring --- aurora/utilities/moderate.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aurora/utilities/moderate.py b/aurora/utilities/moderate.py index 7a0a7a2..bd4f793 100644 --- a/aurora/utilities/moderate.py +++ b/aurora/utilities/moderate.py @@ -13,7 +13,6 @@ async def moderate(ctx: Union[commands.Context, discord.Interaction], target: di It checks if the target can be moderated, then calls the handler method of the moderation type specified. Args: - bot (Red): The bot instance. ctx (Union[commands.Context, discord.Interaction]): The context of the command. If this is a `discord.Interaction` object, it will be converted to a `commands.Context` object. Additionally, if the interaction orignated from a context menu, the `ctx.author` attribute will be overriden to `interaction.user`. target (discord.Member, discord.User, discord.abc.Messageable): The target user or channel to moderate. silent (bool | None): Whether to send the moderation action to the target. -- 2.45.3 From 10cfeeefcd4eeed50753e5f7ce2a2e46c68448c1 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 20:32:14 -0400 Subject: [PATCH 259/376] fix(aurora): awaited a coroutine --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index abc8e76..a5dc168 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -126,7 +126,7 @@ class Aurora(commands.Cog): """This method automatically adds roles to users when they join the server.""" if not await self.bot.cog_disabled_in_guild(self, member.guild): query = f"""SELECT moderation_id, role_id, reason FROM moderation_{member.guild.id} WHERE target_id = ? AND moderation_type = 'ADDROLE' AND expired = 0 AND resolved = 0;""" - results = Moderation.execute(query, (member.id,)) + results = await Moderation.execute(query, (member.id,)) for row in results: role = member.guild.get_role(row[1]) reason = row[2] -- 2.45.3 From c82aa6a0f50307d801f54b30e08699ca429a4723 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 20:33:37 -0400 Subject: [PATCH 260/376] fix(aurora): catch an attribute error --- aurora/aurora.py | 105 ++++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index a5dc168..6118b2c 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -113,7 +113,7 @@ class Aurora(commands.Cog): self.handle_expiry.cancel() @commands.Cog.listener("on_guild_join") - async def db_generate_guild_join(self, guild: discord.Guild): + async def db_generate_on_guild_join(self, guild: discord.Guild): """This method prepares the database schema whenever the bot joins a guild.""" if not await self.bot.cog_disabled_in_guild(self, guild): try: @@ -135,58 +135,61 @@ class Aurora(commands.Cog): @commands.Cog.listener("on_audit_log_entry_create") async def autologger(self, entry: discord.AuditLogEntry): """This method automatically logs moderations done by users manually ("right clicks").""" - if not await self.bot.cog_disabled_in_guild(self, entry.guild): - if await config.guild(entry.guild).ignore_other_bots() is True: - if entry.user.bot or entry.target.bot: - return - else: - if entry.user.id == self.bot.user.id: - return - - duration = None - - if entry.reason: - reason = entry.reason + " (This action was performed without the bot.)" - - else: - reason = "This action was performed without the bot." - - if entry.action == discord.AuditLogAction.kick: - moderation_type = "KICK" - - elif entry.action == discord.AuditLogAction.ban: - moderation_type = "BAN" - - elif entry.action == discord.AuditLogAction.unban: - moderation_type = "UNBAN" - - elif entry.action == discord.AuditLogAction.member_update: - if entry.after.timed_out_until is not None: - timed_out_until_aware = entry.after.timed_out_until.replace( - tzinfo=timezone.utc - ) - duration_datetime = timed_out_until_aware - datetime.now( - tz=timezone.utc - ) - minutes = round(duration_datetime.total_seconds() / 60) - duration = timedelta(minutes=minutes) - moderation_type = "MUTE" + try: + if not await self.bot.cog_disabled_in_guild(self, entry.guild): + if await config.guild(entry.guild).ignore_other_bots() is True: + if entry.user.bot or entry.target.bot: + return else: - moderation_type = "UNMUTE" - else: - return + if entry.user.id == self.bot.user.id: + return - await Moderation.log( - self.bot, - entry.guild.id, - entry.user.id, - moderation_type, - "USER", - entry.target.id, - None, - duration, - reason, - ) + duration = None + + if entry.reason: + reason = entry.reason + " (This action was performed without the bot.)" + + else: + reason = "This action was performed without the bot." + + if entry.action == discord.AuditLogAction.kick: + moderation_type = "KICK" + + elif entry.action == discord.AuditLogAction.ban: + moderation_type = "BAN" + + elif entry.action == discord.AuditLogAction.unban: + moderation_type = "UNBAN" + + elif entry.action == discord.AuditLogAction.member_update: + if entry.after.timed_out_until is not None: + timed_out_until_aware = entry.after.timed_out_until.replace( + tzinfo=timezone.utc + ) + duration_datetime = timed_out_until_aware - datetime.now( + tz=timezone.utc + ) + minutes = round(duration_datetime.total_seconds() / 60) + duration = timedelta(minutes=minutes) + moderation_type = "MUTE" + else: + moderation_type = "UNMUTE" + else: + return + + await Moderation.log( + self.bot, + entry.guild.id, + entry.user.id, + moderation_type, + "USER", + entry.target.id, + None, + duration, + reason, + ) + except AttributeError: + return ####################################################################################################################### ### COMMANDS -- 2.45.3 From 7c8aaba309a90b15c5f46006f21282b2b00ac9e8 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 20:33:47 -0400 Subject: [PATCH 261/376] misc(aurora): version bump --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 6118b2c..fe5c4ab 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev1" + __version__ = "3.0.0-indev2" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): -- 2.45.3 From 4ec065e43866e12cde1f8409b11343f969a5d808 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 20:40:10 -0400 Subject: [PATCH 262/376] fix(aurora): fixed a NotFound error being thrown to the console --- aurora/menus/addrole.py | 6 +++++- aurora/menus/guild.py | 6 +++++- aurora/menus/immune.py | 6 +++++- aurora/menus/overrides.py | 6 +++++- aurora/menus/types.py | 6 +++++- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/aurora/menus/addrole.py b/aurora/menus/addrole.py index 36c9056..ecf2941 100644 --- a/aurora/menus/addrole.py +++ b/aurora/menus/addrole.py @@ -1,4 +1,5 @@ from discord import ButtonStyle, Interaction, Message, ui +from discord.errors import NotFound from redbot.core import commands from redbot.core.utils.chat_formatting import error @@ -14,7 +15,10 @@ class Addrole(ui.View): self.timeout = timeout async def on_timeout(self): - await self.message.edit(view=None) + try: + await self.message.edit(view=None) + except NotFound: + pass @ui.select(cls=ui.RoleSelect, placeholder="Select a role", min_values=0, max_values=25) async def addrole_select(self, interaction: Interaction, select: ui.RoleSelect): diff --git a/aurora/menus/guild.py b/aurora/menus/guild.py index 71186b7..5f54e6a 100644 --- a/aurora/menus/guild.py +++ b/aurora/menus/guild.py @@ -1,4 +1,5 @@ from discord import ButtonStyle, Interaction, Message, ui +from discord.errors import NotFound from redbot.core import commands from ..utilities.config import config @@ -14,7 +15,10 @@ class Guild(ui.View): self.timeout = timeout async def on_timeout(self): - await self.message.edit(view=None) + try: + await self.message.edit(view=None) + except NotFound: + pass @ui.button(label="Show Moderator", style=ButtonStyle.green, row=0) async def show_moderator(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument diff --git a/aurora/menus/immune.py b/aurora/menus/immune.py index dd710b1..d6acc45 100644 --- a/aurora/menus/immune.py +++ b/aurora/menus/immune.py @@ -1,4 +1,5 @@ from discord import ButtonStyle, Interaction, Message, ui +from discord.errors import NotFound from redbot.core import commands from redbot.core.utils.chat_formatting import error @@ -14,7 +15,10 @@ class Immune(ui.View): self.timeout = timeout async def on_timeout(self): - await self.message.edit(view=None) + try: + await self.message.edit(view=None) + except NotFound: + pass @ui.select(cls=ui.RoleSelect, placeholder="Select a role", min_values=0, max_values=25) async def immune_select(self, interaction: Interaction, select: ui.RoleSelect): diff --git a/aurora/menus/overrides.py b/aurora/menus/overrides.py index 4327131..af2df00 100644 --- a/aurora/menus/overrides.py +++ b/aurora/menus/overrides.py @@ -1,4 +1,5 @@ from discord import ButtonStyle, Interaction, Message, ui +from discord.errors import NotFound from redbot.core import commands from ..utilities.config import config @@ -14,7 +15,10 @@ class Overrides(ui.View): self.timeout = timeout async def on_timeout(self): - await self.message.edit(view=None) + try: + await self.message.edit(view=None) + except NotFound: + pass @ui.button(label="Auto Evidence Format", style=ButtonStyle.green, row=0) async def auto_evidenceformat(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument diff --git a/aurora/menus/types.py b/aurora/menus/types.py index f943d90..52fc7e3 100644 --- a/aurora/menus/types.py +++ b/aurora/menus/types.py @@ -1,4 +1,5 @@ from discord import ButtonStyle, Interaction, Message, ui +from discord.errors import NotFound from redbot.core import commands from ..models.type import Type @@ -15,7 +16,10 @@ class Types(ui.View): self.timeout = timeout async def on_timeout(self): - await self.message.edit(view=None) + try: + await self.message.edit(view=None) + except NotFound: + pass @ui.button(label="Show in History", style=ButtonStyle.green, row=0) async def show_in_history(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument -- 2.45.3 From 9e2bcf9b00c6717c06a8414951a4b312700b2a27 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 20:44:12 -0400 Subject: [PATCH 263/376] feat(aurora): added datetime command --- aurora/aurora.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/aurora/aurora.py b/aurora/aurora.py index fe5c4ab..9b96ee7 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1224,6 +1224,25 @@ class Aurora(commands.Cog): error("Please provide a valid GalacticBot moderation export file.") ) + @aurora.command(aliases=["dtc", "dt", "datetimeconvert"]) + async def datetime(self, ctx: commands.Context, *, date: str) -> None: + """Convert a string to a datetime object. + + This command converts a date to a [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) Python object. + + **Example usage** + `[p]aurora datetime 08/20/2024` + **Output** + `2024-08-20 12:00:00`""" + try: + parsed_date = parse(date) + await ctx.send(f"`{parsed_date}`") + except (ParserError, OverflowError) as e: + if e == ParserError: + await ctx.send(error("Invalid date format!")) + if e == OverflowError: + await ctx.send(error("Date is too far in the future!")) + @aurora.command(aliases=["tdc", "td", "timedeltaconvert"]) async def timedelta(self, ctx: commands.Context, *, duration: str) -> None: """Convert a string to a timedelta. -- 2.45.3 From e559db9f10bc798fab1834f7ed50292ba9633754 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 20:46:40 -0400 Subject: [PATCH 264/376] feat(aurora): moved the converter commands to their own convert command group --- aurora/aurora.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 9b96ee7..12f0578 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1224,7 +1224,12 @@ class Aurora(commands.Cog): error("Please provide a valid GalacticBot moderation export file.") ) - @aurora.command(aliases=["dtc", "dt", "datetimeconvert"]) + @aurora.group(autohelp=True, name="convert") + async def aurora_convert(self, ctx: commands.Context): + """Convert strings to various Python objects.""" + pass + + @aurora_convert.command(aliases=["dt"]) async def datetime(self, ctx: commands.Context, *, date: str) -> None: """Convert a string to a datetime object. @@ -1243,7 +1248,7 @@ class Aurora(commands.Cog): if e == OverflowError: await ctx.send(error("Date is too far in the future!")) - @aurora.command(aliases=["tdc", "td", "timedeltaconvert"]) + @aurora_convert.command(aliases=["td"]) async def timedelta(self, ctx: commands.Context, *, duration: str) -> None: """Convert a string to a timedelta. @@ -1260,7 +1265,7 @@ class Aurora(commands.Cog): return await ctx.send(f"`{parsed_time}`") - @aurora.command(aliases=["rdc", "rd", "relativedeltaconvert"]) + @aurora_convert.command(aliases=["rd"]) async def relativedelta(self, ctx: commands.Context, *, duration: str) -> None: """Convert a string to a relativedelta. -- 2.45.3 From 830237938ad6ab44bbfc4985cead163a4fe90f8b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 00:41:25 -0400 Subject: [PATCH 265/376] fix(aurora): pylint fix --- aurora/aurora.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 12f0578..e7bf1bf 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1227,7 +1227,6 @@ class Aurora(commands.Cog): @aurora.group(autohelp=True, name="convert") async def aurora_convert(self, ctx: commands.Context): """Convert strings to various Python objects.""" - pass @aurora_convert.command(aliases=["dt"]) async def datetime(self, ctx: commands.Context, *, date: str) -> None: -- 2.45.3 From ad063062fb8213168a7a8213a151e6be0ebd3178 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 01:22:18 -0400 Subject: [PATCH 266/376] feat(aurora): add autocomplete to `/history`'s types argument --- aurora/aurora.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/aurora/aurora.py b/aurora/aurora.py index e7bf1bf..bf99150 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -11,6 +11,7 @@ import os import time from datetime import datetime, timedelta, timezone from math import ceil +from typing import List import discord from class_registry.registry import RegistryKeyError @@ -767,6 +768,21 @@ class Aurora(commands.Cog): await interaction.followup.send(embed=embed, ephemeral=ephemeral) + @history.autocomplete('types') + async def _history_types(self, interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]: + types: List[str] = sorted(self.type_registry.keys()) + choices = list() + if current.endswith(","): + for c in current.split(","): + if c in types: + types.remove(c) + for t in types: + choices.append(app_commands.Choice(name=current+t, value=current+t)) + else: + for t in types: + choices.append(app_commands.Choice(name=t, value=t)) + return choices[:25] + @app_commands.command(name="resolve") async def resolve( self, interaction: discord.Interaction, case: int, reason: str | None = None -- 2.45.3 From a6124dd9ca4a3dfd8ea03b185b28f7a9da65eae2 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 01:26:50 -0400 Subject: [PATCH 267/376] fix(aurora): fixed a TypeError whenever an expiry_handler function is called --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index bf99150..4523b9d 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1090,7 +1090,7 @@ class Aurora(commands.Cog): other_num = 0 for moderation in moderations: try: - num = await moderation.type.expiry_handler(self.bot, guild, moderation) + num = await moderation.type.expiry_handler(moderation) except NotImplementedError: logger.warning("Expiry handler not implemented for expirable moderation type %s", moderation.type.key) continue -- 2.45.3 From 009b406ff6d3203a34fc0dcc9cf30265a9ef62e1 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 01:30:47 -0400 Subject: [PATCH 268/376] fix(aurora): fixed some broken expiry handlers --- aurora/models/moderation_types.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 3b29bf4..0265145 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -241,7 +241,12 @@ class AddRole(Type): @classmethod async def expiry_handler(cls, moderation: Moderation) -> int: try: - target = await moderation.get_target() + target = moderation.bot.get_user(moderation.target_id) + if not target: + try: + await moderation.guild.fetch_member(moderation.target_id) + except NotFound: + return 0 await target.remove_roles( Object(moderation.role_id), reason=f"Automatic role removal from case #{moderation.id}" @@ -409,7 +414,12 @@ class RemoveRole(Type): @classmethod async def expiry_handler(cls, moderation: Moderation) -> int: try: - target = await moderation.get_target() + target = moderation.bot.get_user(moderation.target_id) + if not target: + try: + await moderation.guild.fetch_member(moderation.target_id) + except NotFound: + return 0 await target.add_roles( Object(moderation.role_id), reason=f"Automatic role addition from case #{moderation.id}" @@ -881,7 +891,12 @@ class Tempban(Ban): async def expiry_handler(cls, moderation: Moderation) -> int: reason = f"Automatic {Unban.string} from case #{moderation.id}" try: - target = await moderation.get_target() + target = moderation.bot.get_user(moderation.target_id) + if not target: + try: + await moderation.bot.fetch_user(moderation.target_id) + except NotFound: + return 0 await moderation.guild.unban(user=target, reason=reason) if await config.guild(moderation.guild).dm_users() is True: -- 2.45.3 From 448ac6792ecb8851a703410111f114199082e84b Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 14:18:25 -0400 Subject: [PATCH 269/376] fix(aurora): fixed some expiry_handler() methods fetching the user object but not putting it into a variable --- aurora/aurora.py | 2 +- aurora/models/moderation_types.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 4523b9d..94e9247 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -47,7 +47,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev2" + __version__ = "3.0.0-indev3" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 0265145..0adea3d 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -244,7 +244,7 @@ class AddRole(Type): target = moderation.bot.get_user(moderation.target_id) if not target: try: - await moderation.guild.fetch_member(moderation.target_id) + target = await moderation.guild.fetch_member(moderation.target_id) except NotFound: return 0 @@ -417,7 +417,7 @@ class RemoveRole(Type): target = moderation.bot.get_user(moderation.target_id) if not target: try: - await moderation.guild.fetch_member(moderation.target_id) + target = await moderation.guild.fetch_member(moderation.target_id) except NotFound: return 0 @@ -894,7 +894,7 @@ class Tempban(Ban): target = moderation.bot.get_user(moderation.target_id) if not target: try: - await moderation.bot.fetch_user(moderation.target_id) + target = await moderation.bot.fetch_user(moderation.target_id) except NotFound: return 0 await moderation.guild.unban(user=target, reason=reason) -- 2.45.3 From 233e6ac90844e0cae4122066c22486b37f0f94c7 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 14:25:03 -0400 Subject: [PATCH 270/376] feat(aurora): added `expired` argument to the `/history` command --- aurora/aurora.py | 13 ++++++++----- aurora/models/moderation.py | 17 ++++++++++++++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 94e9247..19a99c8 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -47,7 +47,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev3" + __version__ = "3.0.0-indev4" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -530,6 +530,7 @@ class Aurora(commands.Cog): on: str | None = None, before: str | None = None, after: str | None = None, + expired: bool | None = None, types: str | None = None, ephemeral: bool | None = None, inline: bool | None = None, @@ -553,7 +554,9 @@ class Aurora(commands.Cog): List infractions before a certain date after: str List infractions after a certain date - types: bool + expired: bool + List expired or unexpired infractions + types: str List infractions of specific types, comma separated ephemeral: bool Hide the command response @@ -674,13 +677,13 @@ class Aurora(commands.Cog): if target: filename = f"moderation_target_{str(target.id)}_{str(interaction.guild.id)}.json" - moderations = await Moderation.find_by_target(bot=interaction.client, guild_id=interaction.guild.id, target=target.id, before=before, after=after, types=type_list) + moderations = await Moderation.find_by_target(bot=interaction.client, guild_id=interaction.guild.id, target=target.id, before=before, after=after, types=type_list, expired=expired) elif moderator: filename = f"moderation_moderator_{str(moderator.id)}_{str(interaction.guild.id)}.json" - moderations = await Moderation.find_by_moderator(bot=interaction.client, guild_id=interaction.guild.id, moderator=moderator.id, before=before, after=after, types=type_list) + moderations = await Moderation.find_by_moderator(bot=interaction.client, guild_id=interaction.guild.id, moderator=moderator.id, before=before, after=after, types=type_list, expired=expired) else: filename = f"moderation_{str(interaction.guild.id)}.json" - moderations = await Moderation.get_latest(bot=interaction.client, guild_id=interaction.guild.id, before=before, after=after, types=type_list) + moderations = await Moderation.get_latest(bot=interaction.client, guild_id=interaction.guild.id, before=before, after=after, types=type_list, expired=expired) if export: try: diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index e2217c4..0014cda 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -312,7 +312,7 @@ class Moderation(AuroraGuildModel): return results @classmethod - async def get_latest(cls, bot: Red, guild_id: int, before: datetime = None, after: datetime = None, limit: int | None = None, offset: int = 0, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def get_latest(cls, bot: Red, guild_id: int, before: datetime | None = None, after: datetime | None = None, limit: int | None = None, offset: int = 0, types: Iterable[Type] | None = None, expired: bool | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: params = [] query = f"SELECT * FROM moderation_{guild_id}" conditions = [] @@ -327,6 +327,9 @@ class Moderation(AuroraGuildModel): if after: conditions.append("timestamp > ?") params.append(int(after.timestamp())) + if expired is not None: + conditions.append("expired = ?") + params.append(int(expired)) if conditions: query += " WHERE " + " AND ".join(conditions) @@ -353,7 +356,7 @@ class Moderation(AuroraGuildModel): raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") @classmethod - async def find_by_target(cls, bot: Red, guild_id: int, target: int, before: datetime = None, after: datetime = None, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def find_by_target(cls, bot: Red, guild_id: int, target: int, before: datetime = None, after: datetime = None, types: Iterable[Type] | None = None, expired: bool | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE target_id = ?" params = [target] if types: @@ -366,12 +369,16 @@ class Moderation(AuroraGuildModel): if after: query += " AND timestamp > ?" params.append(int(after.timestamp())) + if expired is not None: + query += " AND expired = ?" + params.append(int(expired)) + query += " ORDER BY moderation_id DESC;" return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=params, cursor=cursor) @classmethod - async def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, before: datetime = None, after: datetime = None, types: Iterable[Type] | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: + async def find_by_moderator(cls, bot: Red, guild_id: int, moderator: int, before: datetime = None, after: datetime = None, types: Iterable[Type] | None = None, expired: bool | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]: query = f"SELECT * FROM moderation_{guild_id} WHERE moderator_id = ?" params = [moderator] if types: @@ -384,6 +391,10 @@ class Moderation(AuroraGuildModel): if after: query += " AND timestamp > ?" params.append(int(after.timestamp())) + if expired is not None: + query += " AND expired = ?" + params.append(int(expired)) + query += " ORDER BY moderation_id DESC;" return await cls.execute(bot=bot, guild_id=guild_id, query=query, parameters=params, cursor=cursor) -- 2.45.3 From 48259df18fa18b1d4a455749cd8cdcd90c8a38fa Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 15:09:49 -0400 Subject: [PATCH 271/376] misc(aurora): move moderate() into the Aurora cog class --- aurora/aurora.py | 66 +++++++++++++++++++++++++++--------- aurora/utilities/moderate.py | 42 ----------------------- 2 files changed, 50 insertions(+), 58 deletions(-) delete mode 100644 aurora/utilities/moderate.py diff --git a/aurora/aurora.py b/aurora/aurora.py index 19a99c8..be455ca 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -11,7 +11,7 @@ import os import time from datetime import datetime, timedelta, timezone from math import ceil -from typing import List +from typing import List, Union import discord from class_registry.registry import RegistryKeyError @@ -32,13 +32,12 @@ from .menus.overrides import Overrides from .menus.types import Types from .models.change import Change from .models.moderation import Moderation -from .models.type import type_registry +from .models.type import Type, type_registry from .utilities.config import config, register_config from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, overrides_embed, type_embed from .utilities.json import dump from .utilities.logger import logger -from .utilities.moderate import moderate -from .utilities.utils import check_permissions, create_guild_table, log +from .utilities.utils import check_moddable, check_permissions, create_guild_table, log class Aurora(commands.Cog): @@ -47,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev4" + __version__ = "3.0.0-indev5" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -113,6 +112,41 @@ class Aurora(commands.Cog): async def cog_unload(self): self.handle_expiry.cancel() + @staticmethod + async def moderate(ctx: Union[commands.Context, discord.Interaction], target: discord.Member | discord.User | discord.abc.Messageable, silent: bool | None, permissions: List[str], moderation_type: Type | str, **kwargs) -> None | Type: + """This function is used to moderate users. + It checks if the target can be moderated, then calls the handler method of the moderation type specified. + + Args: + ctx (Union[commands.Context, discord.Interaction]): The context of the command. If this is a `discord.Interaction` object, it will be converted to a `commands.Context` object. Additionally, if the interaction orignated from a context menu, the `ctx.author` attribute will be overriden to `interaction.user`. + target (discord.Member, discord.User, discord.abc.Messageable): The target user or channel to moderate. + silent (bool | None): Whether to send the moderation action to the target. + permissions (List[str]): The permissions required to moderate the target. + moderation_type (Type): The moderation type (handler) to use. See `aurora.models.moderation_types` for some examples. + **kwargs: The keyword arguments to pass to the handler method. + """ + if isinstance(moderation_type, str): + moderation_type = type_registry[str.lower(moderation_type)] + if isinstance(ctx, discord.Interaction): + interaction = ctx + ctx = await commands.Context.from_interaction(interaction) + if isinstance(interaction.command, app_commands.ContextMenu): + ctx.author = interaction.user + if not await check_moddable(target=target, ctx=ctx, permissions=permissions, moderation_type=moderation_type): + return + if silent is None: + dm_users = await config.custom("types", ctx.guild.id, moderation_type.key).dm_users() + if dm_users is None: + dm_users = await config.guild(ctx.guild).dm_users() + silent = not dm_users + return await moderation_type.handler( + ctx=ctx, + target=target, + silent=silent, + **kwargs + ) + + @commands.Cog.listener("on_guild_join") async def db_generate_on_guild_join(self, guild: discord.Guild): """This method prepares the database schema whenever the bot joins a guild.""" @@ -214,7 +248,7 @@ class Aurora(commands.Cog): Why are you noting this user? silent: bool Should the user be messaged?""" - await moderate( + await self.moderate( ctx=interaction, target=target, silent=silent, @@ -241,7 +275,7 @@ class Aurora(commands.Cog): Why are you warning this user? silent: bool Should the user be messaged?""" - await moderate( + await self.moderate( ctx=interaction, target=target, silent=silent, @@ -274,7 +308,7 @@ class Aurora(commands.Cog): How long are you adding this role for? silent: bool Should the user be messaged?""" - await moderate( + await self.moderate( ctx=interaction, target=target, silent=silent, @@ -309,7 +343,7 @@ class Aurora(commands.Cog): How long are you removing this role for? silent: bool Should the user be messaged?""" - await moderate( + await self.moderate( ctx=interaction, target=target, silent=silent, @@ -341,7 +375,7 @@ class Aurora(commands.Cog): Why are you unbanning this user? silent: bool Should the user be messaged?""" - await moderate( + await self.moderate( ctx=interaction, target=target, silent=silent, @@ -369,7 +403,7 @@ class Aurora(commands.Cog): Why are you unmuting this user? silent: bool Should the user be messaged?""" - await moderate( + await self.moderate( ctx=interaction, target=target, silent=silent, @@ -396,7 +430,7 @@ class Aurora(commands.Cog): Why are you kicking this user? silent: bool Should the user be messaged?""" - await moderate( + await self.moderate( ctx=interaction, target=target, silent=silent, @@ -440,7 +474,7 @@ class Aurora(commands.Cog): silent: bool Should the user be messaged?""" if duration: - await moderate( + await self.moderate( ctx=interaction, target=target, silent=silent, @@ -451,7 +485,7 @@ class Aurora(commands.Cog): delete_messages=delete_messages, ) else: - await moderate( + await self.moderate( ctx=interaction, target=target, silent=silent, @@ -479,7 +513,7 @@ class Aurora(commands.Cog): Why are you unbanning this user? silent: bool Should the user be messaged?""" - await moderate( + await self.moderate( ctx=interaction, target=target, silent=silent, @@ -509,7 +543,7 @@ class Aurora(commands.Cog): if channel is None: channel = interaction.channel - await moderate( + await self.moderate( ctx=interaction, target=channel, silent=True, diff --git a/aurora/utilities/moderate.py b/aurora/utilities/moderate.py deleted file mode 100644 index bd4f793..0000000 --- a/aurora/utilities/moderate.py +++ /dev/null @@ -1,42 +0,0 @@ -from typing import List, Union - -import discord -from redbot.core import app_commands, commands - -from ..models.type import Type, type_registry -from .config import config -from .utils import check_moddable - - -async def moderate(ctx: Union[commands.Context, discord.Interaction], target: discord.Member | discord.User | discord.abc.Messageable, silent: bool | None, permissions: List[str], moderation_type: Type | str, **kwargs) -> None | Type: - """This function is used to moderate users. - It checks if the target can be moderated, then calls the handler method of the moderation type specified. - - Args: - ctx (Union[commands.Context, discord.Interaction]): The context of the command. If this is a `discord.Interaction` object, it will be converted to a `commands.Context` object. Additionally, if the interaction orignated from a context menu, the `ctx.author` attribute will be overriden to `interaction.user`. - target (discord.Member, discord.User, discord.abc.Messageable): The target user or channel to moderate. - silent (bool | None): Whether to send the moderation action to the target. - permissions (List[str]): The permissions required to moderate the target. - moderation_type (Type): The moderation type (handler) to use. See `aurora.models.moderation_types` for some examples. - **kwargs: The keyword arguments to pass to the handler method. - """ - if isinstance(moderation_type, str): - moderation_type = type_registry[str.lower(moderation_type)] - if isinstance(ctx, discord.Interaction): - interaction = ctx - ctx = await commands.Context.from_interaction(interaction) - if isinstance(interaction.command, app_commands.ContextMenu): - ctx.author = interaction.user - if not await check_moddable(target=target, ctx=ctx, permissions=permissions, moderation_type=moderation_type): - return - if silent is None: - dm_users = await config.custom("types", ctx.guild.id, moderation_type.key).dm_users() - if dm_users is None: - dm_users = await config.guild(ctx.guild).dm_users() - silent = not dm_users - return await moderation_type.handler( - ctx=ctx, - target=target, - silent=silent, - **kwargs - ) -- 2.45.3 From a5e3a11479705cf5f53089fa27176cd95a39c88c Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 15:11:39 -0400 Subject: [PATCH 272/376] fix(aurora): set a default argument for the resolve command's string parameter --- aurora/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index be455ca..3e2afe2 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev5" + __version__ = "3.0.0-indev6" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -822,7 +822,7 @@ class Aurora(commands.Cog): @app_commands.command(name="resolve") async def resolve( - self, interaction: discord.Interaction, case: int, reason: str | None = None + self, interaction: discord.Interaction, case: int, reason: str = "No reason provided." ): """Resolve a specific case. -- 2.45.3 From 3d8050d3b9073961cc1c616f10566c54bb191aca Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 16:08:16 -0400 Subject: [PATCH 273/376] fix(aurora): fixed a minor bug with autocomplete --- aurora/aurora.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 3e2afe2..ccc345f 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -817,7 +817,8 @@ class Aurora(commands.Cog): choices.append(app_commands.Choice(name=current+t, value=current+t)) else: for t in types: - choices.append(app_commands.Choice(name=t, value=t)) + if t.startswith(current): + choices.append(app_commands.Choice(name=t, value=t)) return choices[:25] @app_commands.command(name="resolve") -- 2.45.3 From 1a20ae30dee13b797e949b1e28d6f3318525baa3 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 16:23:35 -0400 Subject: [PATCH 274/376] feat(aurora): add autocomplete entry for `all` --- aurora/aurora.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aurora/aurora.py b/aurora/aurora.py index ccc345f..304b38f 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -816,6 +816,7 @@ class Aurora(commands.Cog): for t in types: choices.append(app_commands.Choice(name=current+t, value=current+t)) else: + choices.append(app_commands.Choice(name="all", value="all")) for t in types: if t.startswith(current): choices.append(app_commands.Choice(name=t, value=t)) -- 2.45.3 From f5aa9f2b207ddac134f6a897aa1abea72cfda3cb Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 16:26:14 -0400 Subject: [PATCH 275/376] fix(aurora): fixed a programmingError when using `all` --- aurora/models/moderation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 0014cda..0e406d7 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -318,9 +318,11 @@ class Moderation(AuroraGuildModel): conditions = [] if types: + if 'all' in types: + types = type_registry.keys() conditions.append(f"moderation_type IN ({', '.join(['?' for _ in types])})") for t in types: - params.append(t.key) + params.append(t) if before: conditions.append("timestamp < ?") params.append(int(before.timestamp())) -- 2.45.3 From 71840cc14873c8c152e20b10b5370261541a72a8 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 16:31:00 -0400 Subject: [PATCH 276/376] misc(aurora): added a temporary logging call --- aurora/models/moderation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 0e406d7..b9e9127 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -320,9 +320,9 @@ class Moderation(AuroraGuildModel): if types: if 'all' in types: types = type_registry.keys() + logger.debug("Getting all types: %s", types) conditions.append(f"moderation_type IN ({', '.join(['?' for _ in types])})") - for t in types: - params.append(t) + params.extend([t.key for t in types]) if before: conditions.append("timestamp < ?") params.append(int(before.timestamp())) -- 2.45.3 From 1275b8e99a1c010ddb2d0b8168af966a5cb74b84 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 16:36:15 -0400 Subject: [PATCH 277/376] fix(aurora): revert a stupid change --- aurora/models/moderation.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index b9e9127..2fe5d61 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -318,9 +318,6 @@ class Moderation(AuroraGuildModel): conditions = [] if types: - if 'all' in types: - types = type_registry.keys() - logger.debug("Getting all types: %s", types) conditions.append(f"moderation_type IN ({', '.join(['?' for _ in types])})") params.extend([t.key for t in types]) if before: -- 2.45.3 From 6c7cdd4e5eb971ca56a6bd3bae18bb9061e0373e Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 16:38:20 -0400 Subject: [PATCH 278/376] fix(aurora): fixed `all` type --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 304b38f..db1cf89 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -698,7 +698,7 @@ class Aurora(commands.Cog): stripped = t.strip().lower() if stripped == "all": type_list.clear() - type_list = registry_values + type_list.extend((t.key for t in registry_values)) break try: type_list.append(type_registry[stripped]) -- 2.45.3 From 86c0cadd82d6a48b78e6e21a89741e087c997a22 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 16:39:36 -0400 Subject: [PATCH 279/376] fix(aurora): don't pass key --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index db1cf89..468c760 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -698,7 +698,7 @@ class Aurora(commands.Cog): stripped = t.strip().lower() if stripped == "all": type_list.clear() - type_list.extend((t.key for t in registry_values)) + type_list.extend((t for t in registry_values)) break try: type_list.append(type_registry[stripped]) -- 2.45.3 From 6aaef7d3b2e74fbd39c82a1a2d184271b823a10d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Tue, 13 Aug 2024 23:59:36 -0400 Subject: [PATCH 280/376] fix(aurora): fixed removerole and addrole being broken if used without a duration set --- aurora/aurora.py | 2 +- aurora/models/moderation_types.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 468c760..6539561 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev6" + __version__ = "3.0.0-indev7" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 0adea3d..5bf6341 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -158,7 +158,7 @@ class AddRole(Type): return None @classmethod - async def handler(cls, ctx: commands.Context, target: Member, role: Role, silent: bool, duration: str = None, reason: str = None): + async def handler(cls, ctx: commands.Context, target: Member, role: Role, silent: bool, duration: str | None = None, reason: str | None = None): addrole_whitelist = await config.guild(ctx.guild).addrole_whitelist() if not addrole_whitelist: @@ -192,7 +192,7 @@ class AddRole(Type): return response = await ctx.send( - content=f"{target.mention} has {cls.embed_desc}{role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" + content=f"{target.mention} has {cls.embed_desc}{role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time else ''}!\n**Reason** - `{reason}`" ) if silent is False: @@ -331,7 +331,7 @@ class RemoveRole(Type): return None @classmethod - async def handler(cls, ctx: commands.Context, target: Member, role: Role, silent: bool, duration: str | None = None, reason: str = None): + async def handler(cls, ctx: commands.Context, target: Member, role: Role, silent: bool, duration: str | None = None, reason: str | None = None): addrole_whitelist = await config.guild(ctx.guild).addrole_whitelist() if not addrole_whitelist: @@ -365,7 +365,7 @@ class RemoveRole(Type): return response = await ctx.send( - content=f"{target.mention} has {cls.embed_desc}{role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" + content=f"{target.mention} has {cls.embed_desc}{role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time else ''}!\n**Reason** - `{reason}`" ) if silent is False: -- 2.45.3 From 871cabfb716bf28e7fea689a2196e763102ab934 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 00:01:13 -0400 Subject: [PATCH 281/376] fix(aurora): fixed addrole and removerole again --- aurora/aurora.py | 2 +- aurora/models/moderation_types.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 6539561..ecd5b9d 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev7" + __version__ = "3.0.0-indev8" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 5bf6341..641f887 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -213,7 +213,7 @@ class AddRole(Type): await target.add_roles( role, - reason=f"Role added by {ctx.author.id}{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''} for: {reason}", + reason=f"Role added by {ctx.author.id}{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time else ''} for: {reason}", ) moderation = await Moderation.log( @@ -401,7 +401,7 @@ class RemoveRole(Type): reason=reason, ) await response.edit( - content=f"{target.mention} has {cls.embed_desc}{role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`", + content=f"{target.mention} has {cls.embed_desc}{role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`", ) await log(ctx=ctx, moderation_id=moderation.id) await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) -- 2.45.3 From 123cd188dc1a67be2c25f37cfe0c7ff23f213d1f Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 00:02:48 -0400 Subject: [PATCH 282/376] fix(aurora): fixed addrole and removerole *again* --- aurora/aurora.py | 2 +- aurora/models/moderation_types.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index ecd5b9d..dfc0a33 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev8" + __version__ = "3.0.0-indev9" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 641f887..446de08 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -228,7 +228,7 @@ class AddRole(Type): reason=reason, ) await response.edit( - content=f"{target.mention} has {cls.embed_desc}{role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`", + content=f"{target.mention} has {cls.embed_desc}{role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`", ) await log(ctx=ctx, moderation_id=moderation.id) await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) @@ -386,7 +386,7 @@ class RemoveRole(Type): await target.remove_roles( role, - reason=f"Role removed by {ctx.author.id}{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''} for: {reason}", + reason=f"Role removed by {ctx.author.id}{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time else ''} for: {reason}", ) moderation = await Moderation.log( -- 2.45.3 From fb92cdc08ca34d49e357eb071cdbc06630d02caa Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 00:04:25 -0400 Subject: [PATCH 283/376] fix(aurora): fixed a bug in removerole --- aurora/aurora.py | 2 +- aurora/models/moderation_types.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index dfc0a33..fab3e2e 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev9" + __version__ = "3.0.0-indev10" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 446de08..afc14d0 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -376,7 +376,7 @@ class RemoveRole(Type): guild=ctx.guild, moderator=ctx.author, reason=reason, - moderation_type="removerole", + moderation_type=cls(), response=response, duration=parsed_time, ) -- 2.45.3 From 001fccfe34780bf6d19bdd186cd4620a6b91cfcc Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 00:06:48 -0400 Subject: [PATCH 284/376] fix(aurora): pylint fixes --- aurora/aurora.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index fab3e2e..3771224 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev10" + __version__ = "3.0.0-indev11" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -806,9 +806,9 @@ class Aurora(commands.Cog): await interaction.followup.send(embed=embed, ephemeral=ephemeral) @history.autocomplete('types') - async def _history_types(self, interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]: + async def _history_types(self, interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]: # pylint: disable=unused-argument types: List[str] = sorted(self.type_registry.keys()) - choices = list() + choices = [] if current.endswith(","): for c in current.split(","): if c in types: -- 2.45.3 From 48d2f8b416fa160ad04e39f09e2b0edb7883fc4d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 14:37:32 -0400 Subject: [PATCH 285/376] fix(aurora): fixed debug logging --- aurora/models/moderation.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 2fe5d61..606df55 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -207,8 +207,12 @@ class Moderation(AuroraGuildModel): @classmethod async def from_result(cls, bot: Red, result: Iterable, guild_id: int) -> "Moderation": if result[7] is not None and result[7] != "NULL": - hours, minutes, seconds = map(int, result[7].split(':')) - duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) + try: + hours, minutes, seconds = map(int, result[7].split(':')) + duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) + except ValueError as e: + logger.error("Error parsing duration for case %s: %s", result[0], result[7]) + raise e else: duration = None -- 2.45.3 From 5fc6d0eb6ae9ca2ce26ba14799fbd95c5821ffbd Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 15:08:37 -0400 Subject: [PATCH 286/376] fix(aurora): fixed Moderation.update() not converting the duration timedelta to the correct kind of string --- aurora/models/moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 606df55..ca12edd 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -181,7 +181,7 @@ class Moderation(AuroraGuildModel): self.target_type, self.moderator_id, self.role_id, - str(self.duration) if self.duration else None, + timedelta_to_string(self.duration) if self.duration else None, self.end_timestamp.timestamp() if self.end_timestamp else None, self.reason, self.resolved, -- 2.45.3 From 51f165c480fd64a4e3c094c18be18daca19e9a85 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 15:14:22 -0400 Subject: [PATCH 287/376] fix(aurora): fixed `/edit` command not properly storing the data from the old moderation --- aurora/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 3771224..284b38a 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev11" + __version__ = "3.0.0-indev12" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -1030,7 +1030,7 @@ class Aurora(commands.Cog): try: moderation = await Moderation.find_by_id(interaction.client, case, interaction.guild.id) - old_moderation = moderation + old_moderation = moderation.model_copy(deep=True) except ValueError: await interaction.response.send_message( content=error(f"Case #{case:,} does not exist!"), ephemeral=True -- 2.45.3 From de4c789feaae8c90da5dd1435cbdf6e873f8f886 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 15:21:07 -0400 Subject: [PATCH 288/376] fix(aurora): don't use deepcopy --- aurora/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 284b38a..d262bec 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev12" + __version__ = "3.0.0-indev13" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -1030,7 +1030,7 @@ class Aurora(commands.Cog): try: moderation = await Moderation.find_by_id(interaction.client, case, interaction.guild.id) - old_moderation = moderation.model_copy(deep=True) + old_moderation = moderation.model_copy() except ValueError: await interaction.response.send_message( content=error(f"Case #{case:,} does not exist!"), ephemeral=True -- 2.45.3 From 7854af8ec0708c053af3f4b31f147f5a4135a1e9 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 15:23:05 -0400 Subject: [PATCH 289/376] fix(aurora): fixed the `/edit` command failing again --- aurora/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index d262bec..71aa18d 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev13" + __version__ = "3.0.0-indev14" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -1102,7 +1102,7 @@ class Aurora(commands.Cog): embed=embed, ephemeral=True, ) - await log(interaction, case) + await log(self.bot.get_context(interaction), case) return -- 2.45.3 From b0c96567584e41d21885065243674bf2590d09ca Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 15:23:40 -0400 Subject: [PATCH 290/376] fix(aurora): awaited a coroutine --- aurora/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 71aa18d..64b2784 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev14" + __version__ = "3.0.0-indev15" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -1102,7 +1102,7 @@ class Aurora(commands.Cog): embed=embed, ephemeral=True, ) - await log(self.bot.get_context(interaction), case) + await log(await self.bot.get_context(interaction), case) return -- 2.45.3 From 9ae76070152a81cd0f98b824b7938e88638ba716 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 15:26:55 -0400 Subject: [PATCH 291/376] fix(aurora): fixed the Moderation.update() method again --- aurora/aurora.py | 2 +- aurora/models/moderation.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 64b2784..c8c22fb 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev15" + __version__ = "3.0.0-indev16" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index ca12edd..18dffa2 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -161,7 +161,7 @@ class Moderation(AuroraGuildModel): self.target_type, self.moderator_id, self.role_id, - str(self.duration) if self.duration else None, + timedelta_to_string(self.duration) if self.duration else None, self.end_timestamp.timestamp() if self.end_timestamp else None, self.reason, self.resolved, -- 2.45.3 From 4a4f24bb8f85a66cf8e49aec68877b41e26c7046 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 15:46:27 -0400 Subject: [PATCH 292/376] fix(aurora): don't continue banning someone if they're already banned --- aurora/aurora.py | 2 +- aurora/models/moderation_types.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index c8c22fb..704f3f9 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev16" + __version__ = "3.0.0-indev17" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index afc14d0..272ec75 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -751,6 +751,7 @@ class Ban(Type): try: await ctx.guild.fetch_ban(target) await ctx.send(content=error(f"{target.mention} is already {cls.verb}!"), ephemeral=True) + return except NotFound: pass @@ -834,6 +835,7 @@ class Tempban(Ban): try: await ctx.guild.fetch_ban(target) await ctx.send(content=error(f"{target.mention} is already {Ban.verb}!"), ephemeral=True) + return except NotFound: pass -- 2.45.3 From ec508a92e35aca216418c7a2a7f413a96acb2302 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 15:57:53 -0400 Subject: [PATCH 293/376] fix(aurora): fixed a typeerror in `/edit` --- aurora/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 704f3f9..ae695de 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev17" + __version__ = "3.0.0-indev18" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -1052,7 +1052,7 @@ class Aurora(commands.Cog): error("Please provide a valid duration!"), ephemeral=True ) - moderation.end_timestamp = moderation.timestamp + moderation.duration.total_seconds() + moderation.end_timestamp = moderation.timestamp + timedelta(seconds=moderation.duration.total_seconds()) try: success = await moderation.type.duration_edit_handler(interaction=interaction.client, old_moderation=old_moderation, new_moderation=moderation) -- 2.45.3 From 8cbe9d94cfac81c92a12431c2e450440c81abe61 Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 15:59:09 -0400 Subject: [PATCH 294/376] fix(aurora): pass `interaction` instead of `interaction.client` to the `duration_edit_handler` --- aurora/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index ae695de..5b9d8f9 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev18" + __version__ = "3.0.0-indev19" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -1055,7 +1055,7 @@ class Aurora(commands.Cog): moderation.end_timestamp = moderation.timestamp + timedelta(seconds=moderation.duration.total_seconds()) try: - success = await moderation.type.duration_edit_handler(interaction=interaction.client, old_moderation=old_moderation, new_moderation=moderation) + success = await moderation.type.duration_edit_handler(interaction=interaction, old_moderation=old_moderation, new_moderation=moderation) except NotImplementedError: return await interaction.response.send_message( error("This case type does not support duration editing!"), ephemeral=True -- 2.45.3 From ac7d950aaab66e8e36a377464180bb118640b24a Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Wed, 14 Aug 2024 16:05:20 -0400 Subject: [PATCH 295/376] fix(aurora): added temporary debug logging --- aurora/aurora.py | 2 +- aurora/models/change.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 5b9d8f9..718a1f8 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev19" + __version__ = "3.0.0-indev20" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): diff --git a/aurora/models/change.py b/aurora/models/change.py index 22ac222..ca80336 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -4,6 +4,7 @@ from typing import Literal, Optional from redbot.core.bot import Red +from ..utilities.logger import logger from ..utilities.utils import timedelta_from_string from .base import AuroraBaseModel from .partials import PartialUser @@ -31,6 +32,8 @@ class Change(AuroraBaseModel): def from_dict(cls, bot: Red, data: dict) -> "Change": if isinstance(data, str): data = json.loads(data) + if data.get('duration'): + logger.debug(f"Duration: {data['duration']}") if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta) and not data["duration"] == "NULL": duration = timedelta_from_string(data["duration"]) elif "duration" in data and isinstance(data["duration"], timedelta): -- 2.45.3 From 7b3608e2641dab2a89478891eae58aecd2d2781d Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 03:55:08 -0400 Subject: [PATCH 296/376] fix(aurora): fixed a keyerror in the message_factory function and cleaned up some other problems --- aurora/models/moderation_types.py | 7 ++++++- aurora/models/type.py | 2 ++ aurora/utilities/factory.py | 7 +------ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 272ec75..2357922 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -651,7 +651,7 @@ class Unmute(Type): guild=ctx.guild, moderator=ctx.author, reason=reason, - moderation_type="unmuted", + moderation_type=cls(), response=response_message, ) await target.send(embed=embed, file=get_icon(ctx.bot)) @@ -679,6 +679,7 @@ class Kick(Type): key="kick" string="kick" verb="kicked" + removes_from_guild=True def void(self) -> None: return None @@ -740,6 +741,7 @@ class Ban(Type): key="ban" string="ban" verb="banned" + removes_from_guild=True def void(self) -> None: return None @@ -824,6 +826,7 @@ class Tempban(Ban): key="tempban" string="tempban" verb="tempbanned" + removes_from_guild=True def void(self) -> None: return None @@ -946,6 +949,7 @@ class Softban(Type): key="softban" string="softban" verb="softbanned" + removes_from_guild=True def void(self) -> None: return None @@ -1019,6 +1023,7 @@ class Unban(Type): key="unban" string="unban" verb="unbanned" + removes_from_guild=True def void(self) -> None: return None diff --git a/aurora/models/type.py b/aurora/models/type.py index d5cf568..6cc8092 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -17,6 +17,7 @@ class Type(metaclass=AutoRegister(type_registry)): verb (str): The verb to use for this type. embed_desc (str): The string to use for embed descriptions. channel (bool): Whether this type targets channels or users. If this is `true` in a subclass, its overriden handler methods should be typed with `discord.abc.Messageable` instead of `discord.Member | discord.User`. + removes_from_guild (bool): Whether this type's handler removes the target from the guild, or if the moderation is expected to occur whenever the user is not in the guild. This does not actually remove the target from the guild, the handler method is responsible for that. Properties: name (str): The string to display for this type. This is the same as the `string` attribute. @@ -27,6 +28,7 @@ class Type(metaclass=AutoRegister(type_registry)): verb = "typed" embed_desc = "been " channel = False + removes_from_guild = False @abstractmethod def void(self) -> Any: diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 95ea1ca..b45b68a 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -42,12 +42,7 @@ async def message_factory( Returns: embed: The message embed. """ - if response is not None and moderation_type.key not in [ - "kick", - "ban", - "tempban", - "unban", - ]: + if response is not None and not moderation_type.removes_from_guild: guild_name = f"[{guild.name}]({response.jump_url})" else: guild_name = guild.name -- 2.45.3 From 46c1cf53bf75cd2302743a02782bce013dc690ea Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 14:24:25 -0400 Subject: [PATCH 297/376] fix(aurora): fixed most of the moderation handlers having improper error handling for incorrect durations --- aurora/models/moderation_types.py | 68 ++++++++++++++++--------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 2357922..8205617 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -169,12 +169,14 @@ class AddRole(Type): return if duration is not None: - parsed_time = parse_timedelta(duration) - if parsed_time is None: - await ctx.send( - content=error("Please provide a valid duration!"), ephemeral=True - ) - return + try: + parsed_time = parse_relativedelta(argument=duration) + if parsed_time is None: + raise commands.BadArgument() + parsed_time = timedelta_from_relativedelta(relativedelta=parsed_time) + except (commands.BadArgument, ValueError): + await ctx.send(content=error(text="Please provide a valid duration!"), ephemeral=True) + return cls() else: parsed_time = None @@ -342,12 +344,14 @@ class RemoveRole(Type): return if duration is not None: - parsed_time = parse_timedelta(duration) - if parsed_time is None: - await ctx.send( - content=error("Please provide a valid duration!"), ephemeral=True - ) - return + try: + parsed_time = parse_relativedelta(argument=duration) + if parsed_time is None: + raise commands.BadArgument() + parsed_time = timedelta_from_relativedelta(relativedelta=parsed_time) + except (commands.BadArgument, ValueError): + await ctx.send(content=error(text="Please provide a valid duration!"), ephemeral=True) + return cls() else: parsed_time = None @@ -721,7 +725,7 @@ class Kick(Type): await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") await log(ctx=ctx, moderation_id=moderation.id) await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) - return cls + return cls() @classmethod async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: @@ -795,7 +799,7 @@ class Ban(Type): await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") await log(ctx=ctx, moderation_id=moderation.id) await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) - return cls + return cls() @classmethod async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: @@ -847,15 +851,14 @@ class Tempban(Ban): else: delete_messages_seconds = delete_messages.value - parsed_time = parse_relativedelta(duration) - if not parsed_time: - await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) - return cls try: - parsed_time = timedelta_from_relativedelta(parsed_time) - except ValueError: - await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True) - return cls + parsed_time = parse_relativedelta(argument=duration) + if parsed_time is None: + raise commands.BadArgument() + parsed_time = timedelta_from_relativedelta(relativedelta=parsed_time) + except (commands.BadArgument, ValueError): + await ctx.send(content=error(text="Please provide a valid duration!"), ephemeral=True) + return cls() response_message = await ctx.send(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(timedelta=parsed_time)}!\n{bold(text='Reason:')} {inline(text=reason)}") @@ -890,7 +893,7 @@ class Tempban(Ban): await response_message.edit(content=f"{target.mention} has been {cls.verb} for {humanize_timedelta(timedelta=parsed_time)}! (Case {inline(text=f'#{moderation.id}')})\n{bold(text='Reason:')} {inline(reason)}") await log(ctx, moderation.id) await send_evidenceformat(ctx, moderation.id) - return cls + return cls() @classmethod async def expiry_handler(cls, moderation: Moderation) -> int: @@ -1003,7 +1006,7 @@ class Softban(Type): await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") await log(ctx, moderation.id) await send_evidenceformat(ctx, moderation.id) - return cls + return cls() @classmethod async def resolve_handler(cls, moderation: Moderation, reason: str) -> Tuple[bool, str]: @@ -1071,7 +1074,7 @@ class Unban(Type): await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}") await log(ctx, moderation.id) await send_evidenceformat(ctx, moderation.id) - return cls + return cls() class Slowmode(Type): key="slowmode" @@ -1086,19 +1089,18 @@ class Slowmode(Type): async def handler(cls, ctx: commands.Context, target: Messageable, silent: bool, duration: str, reason: str) -> 'Slowmode': # pylint: disable=unused-argument """Set the slowmode in a channel.""" bot = ctx.bot - parsed_time = parse_relativedelta(argument=duration) - if not parsed_time: - await ctx.send(content=error(text="Please provide a valid duration!"), ephemeral=True) - return cls try: + parsed_time = parse_relativedelta(argument=duration) + if parsed_time is None: + raise commands.BadArgument() parsed_time = timedelta_from_relativedelta(relativedelta=parsed_time) - except ValueError: + except (commands.BadArgument, ValueError): await ctx.send(content=error(text="Please provide a valid duration!"), ephemeral=True) - return cls + return cls() if ceil(parsed_time.total_seconds()) > 21600: await ctx.send(content=error(text="The slowmode duration cannot exceed 6 hours!"), ephemeral=True) - return cls + return cls() if isinstance(target, TextChannel): await target.edit(slowmode_delay=ceil(parsed_time.total_seconds())) @@ -1115,7 +1117,7 @@ class Slowmode(Type): ) await ctx.send(content=f"{ctx.author.mention} has {cls.verb} {target.mention} to {humanize_timedelta(timedelta=parsed_time)}!\n{bold(text='Reason:')} {inline(text=reason)}") await log(ctx=ctx, moderation_id=moderation.id) - return cls + return cls() class Lockdown(Type): key="lockdown" -- 2.45.3 From 5cd0ef61cbb6b8488a9e9c3d8711c1a9dc4724d3 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 14:33:11 -0400 Subject: [PATCH 298/376] fix(aurora): fixed an error in the `/edit` command --- aurora/aurora.py | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 718a1f8..779667f 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -37,7 +37,7 @@ from .utilities.config import config, register_config from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, overrides_embed, type_embed from .utilities.json import dump from .utilities.logger import logger -from .utilities.utils import check_moddable, check_permissions, create_guild_table, log +from .utilities.utils import check_moddable, check_permissions, create_guild_table, log, timedelta_from_relativedelta class Aurora(commands.Cog): @@ -1002,7 +1002,7 @@ class Aurora(commands.Cog): self, interaction: discord.Interaction, case: int, - reason: str, + reason: str | None = None, duration: str | None = None, ): """Edit the reason of a specific case. @@ -1046,8 +1046,12 @@ class Aurora(commands.Cog): ) if duration: - moderation.duration = parse_timedelta(duration) - if moderation.duration is None: + try: + parsed_time = parse_relativedelta(argument=duration) + if parsed_time is None: + raise commands.BadArgument() + parsed_time = timedelta_from_relativedelta(relativedelta=parsed_time) + except (commands.BadArgument, ValueError): return await interaction.response.send_message( error("Please provide a valid duration!"), ephemeral=True ) @@ -1066,6 +1070,11 @@ class Aurora(commands.Cog): if reason: moderation.reason = reason + if not reason and not duration: + return await interaction.response.send_message( + error("Please provide a new reason or duration to edit this case!"), ephemeral=True + ) + if not moderation.changes: moderation.changes.append(Change.from_dict(interaction.client, { "type": "ORIGINAL", @@ -1075,24 +1084,14 @@ class Aurora(commands.Cog): "duration": old_moderation.duration, "end_timestamp": old_moderation.end_timestamp, })) - if duration: - moderation.changes.append(Change.from_dict(interaction.client, { - "type": "EDIT", - "timestamp": int(time.time()), - "reason": reason, - "user_id": interaction.user.id, - "duration": moderation.duration, - "end_timestamp": moderation.end_timestamp, - })) - else: - moderation.changes.append(Change.from_dict(interaction.client, { - "type": "EDIT", - "timestamp": int(time.time()), - "reason": reason, - "user_id": interaction.user.id, - "duration": moderation.duration, - "end_timestamp": moderation.end_timestamp, - })) + moderation.changes.append(Change.from_dict(interaction.client, { + "type": "EDIT", + "timestamp": int(time.time()), + "reason": moderation.reason, + "user_id": interaction.user.id, + "duration": moderation.duration, + "end_timestamp": moderation.end_timestamp, + })) await moderation.update() embed = await case_factory(interaction=interaction, moderation=moderation) -- 2.45.3 From 3e484e1ae510142d2cdddc3ba7f42c401f443d45 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 14:37:47 -0400 Subject: [PATCH 299/376] fix(aurora): fixed `/edit` command not setting the moderation's duration properly --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 779667f..95fb3b2 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1050,7 +1050,7 @@ class Aurora(commands.Cog): parsed_time = parse_relativedelta(argument=duration) if parsed_time is None: raise commands.BadArgument() - parsed_time = timedelta_from_relativedelta(relativedelta=parsed_time) + moderation.duration = timedelta_from_relativedelta(relativedelta=parsed_time) except (commands.BadArgument, ValueError): return await interaction.response.send_message( error("Please provide a valid duration!"), ephemeral=True -- 2.45.3 From 3d3036f9b6961a990400a97f13e406ac98a29169 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 14:46:08 -0400 Subject: [PATCH 300/376] fix(aurora): convert timedeltas to strings before creating changes from them --- aurora/aurora.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 95fb3b2..0acd3bd 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -37,7 +37,7 @@ from .utilities.config import config, register_config from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, overrides_embed, type_embed from .utilities.json import dump from .utilities.logger import logger -from .utilities.utils import check_moddable, check_permissions, create_guild_table, log, timedelta_from_relativedelta +from .utilities.utils import check_moddable, check_permissions, create_guild_table, log, timedelta_from_relativedelta, timedelta_to_string class Aurora(commands.Cog): @@ -1081,7 +1081,7 @@ class Aurora(commands.Cog): "timestamp": old_moderation.timestamp, "reason": old_moderation.reason, "user_id": old_moderation.moderator_id, - "duration": old_moderation.duration, + "duration": timedelta_to_string(old_moderation.duration), "end_timestamp": old_moderation.end_timestamp, })) moderation.changes.append(Change.from_dict(interaction.client, { @@ -1089,7 +1089,7 @@ class Aurora(commands.Cog): "timestamp": int(time.time()), "reason": moderation.reason, "user_id": interaction.user.id, - "duration": moderation.duration, + "duration": timedelta_to_string(old_moderation.duration), "end_timestamp": moderation.end_timestamp, })) -- 2.45.3 From dc407c1125abbf2749cbd960664270539a65d5e6 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 14:49:04 -0400 Subject: [PATCH 301/376] fix(aurora): fixed the jsonencoder converting timedeltas to strings using `str()` --- aurora/utilities/json.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aurora/utilities/json.py b/aurora/utilities/json.py index 3859bf4..b231b7b 100644 --- a/aurora/utilities/json.py +++ b/aurora/utilities/json.py @@ -14,7 +14,8 @@ class JSONEncoder(json.JSONEncoder): case datetime(): return int(o.timestamp()) case timedelta(): - return str(o) + from ..utilities.utils import timedelta_to_string + return timedelta_to_string(o) case AuroraBaseModel(): return o.dump() case Type(): -- 2.45.3 From 0c2cde1a785a99d02573e8e2d0bf1460d80320fb Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:19:01 -0400 Subject: [PATCH 302/376] fix(aurora): changed how moderation changes are added. only log the information that is actually changed, and not everything --- aurora/aurora.py | 6 +++--- aurora/models/change.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 0acd3bd..c43425f 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1087,10 +1087,10 @@ class Aurora(commands.Cog): moderation.changes.append(Change.from_dict(interaction.client, { "type": "EDIT", "timestamp": int(time.time()), - "reason": moderation.reason, + "reason": reason if reason else None, "user_id": interaction.user.id, - "duration": timedelta_to_string(old_moderation.duration), - "end_timestamp": moderation.end_timestamp, + "duration": timedelta_to_string(moderation.duration) if duration else None, + "end_timestamp": moderation.end_timestamp if duration else None, })) await moderation.update() diff --git a/aurora/models/change.py b/aurora/models/change.py index ca80336..b5c8ef8 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -14,7 +14,7 @@ class Change(AuroraBaseModel): type: Literal["ORIGINAL", "RESOLVE", "EDIT"] timestamp: datetime user_id: int - reason: Optional[str] = "No reason provided" + reason: Optional[str] = None duration: Optional[timedelta] = None end_timestamp: Optional[datetime] = None -- 2.45.3 From 29f393fa894830a8b7c6127752236bf950758761 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:21:33 -0400 Subject: [PATCH 303/376] fix(aurora): fix an attributeerror when editing a case type that doesn't use durations --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index c43425f..187d14a 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1081,7 +1081,7 @@ class Aurora(commands.Cog): "timestamp": old_moderation.timestamp, "reason": old_moderation.reason, "user_id": old_moderation.moderator_id, - "duration": timedelta_to_string(old_moderation.duration), + "duration": timedelta_to_string(old_moderation.duration) if old_moderation.duration else None, "end_timestamp": old_moderation.end_timestamp, })) moderation.changes.append(Change.from_dict(interaction.client, { -- 2.45.3 From b0509d748c8d04d4e8ab534f3f20b46c60b8bc26 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:23:53 -0400 Subject: [PATCH 304/376] fix(aurora): fixed a 403 forbidden error in some moderation type handlers when moderating someone with the administrator permission --- aurora/utilities/utils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 9d7d508..45c160d 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -84,6 +84,12 @@ async def check_moddable( ) return False + if target.guild_permissions.administrator: + await ctx.send( + content="You cannot moderate members with the Administrator permission!", ephemeral=True + ) + return False + if isinstance(target, Member): if ctx.author.top_role <= target.top_role and await config.guild(ctx.guild).respect_hierarchy() is True: await ctx.send( -- 2.45.3 From ec082b58adfb5876c8302fb5c944695eb27c294d Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:40:52 -0400 Subject: [PATCH 305/376] fix(aurora): make changes_factory support changes properly --- aurora/utilities/factory.py | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index b45b68a..ebb93d8 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -5,7 +5,7 @@ from typing import Union from discord import Color, Embed, Guild, Interaction, Member, Message, Role, User from redbot.core import commands from redbot.core.bot import Red -from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, warning +from redbot.core.utils.chat_formatting import bold, box, error, humanize_timedelta, inline, warning from ..models.moderation import Moderation from ..models.partials import PartialUser @@ -261,27 +261,22 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E user: PartialUser = memory_dict[str(change.user_id)] timestamp = f" | " + end_timestamp = f" | " if change.end_timestamp else None - if change.type == "ORIGINAL": - embed.add_field( - name="Original", - value=f"**User:** `{user.name}` ({user.id})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", - inline=False, - ) + change_str = [ + f"{bold("User:")} {inline(user.name)} ({user.id})", + f"{bold("Reason:")} {change.reason}" if change.reason else "", + f"{bold('Duration:')} {humanize_timedelta(timedelta=change.duration)}" if change.duration else "", + f"{bold('End Timestamp:')} {end_timestamp}" if end_timestamp else "", + f"{bold("Timestamp:")} {timestamp}", + ] + change_str.remove("") - elif change.type == "EDIT": - embed.add_field( - name="Edit", - value=f"**User:** `{user.name}` ({user.id})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", - inline=False, - ) - - elif change.type == "RESOLVE": - embed.add_field( - name="Resolve", - value=f"**User:** `{user.name}` ({user.id})\n**Reason:** {change.reason}\n**Timestamp:** {timestamp}", - inline=False, - ) + embed.add_field( + name=change.type.title(), + value=change_str.join("\n"), + inline=False, + ) else: embed.description = "*No changes have been made to this case.* 🙁" -- 2.45.3 From 9be187e4aaff06691e5b2b71a1c2c01480fc3b4c Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:41:41 -0400 Subject: [PATCH 306/376] fix(aurora): fixed a SyntaxError in changes_factory --- aurora/utilities/factory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index ebb93d8..f512456 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -264,8 +264,8 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E end_timestamp = f" | " if change.end_timestamp else None change_str = [ - f"{bold("User:")} {inline(user.name)} ({user.id})", - f"{bold("Reason:")} {change.reason}" if change.reason else "", + f"{bold('User:')} {inline(user.name)} ({user.id})", + f"{bold('Reason:')} {change.reason}" if change.reason else "", f"{bold('Duration:')} {humanize_timedelta(timedelta=change.duration)}" if change.duration else "", f"{bold('End Timestamp:')} {end_timestamp}" if end_timestamp else "", f"{bold("Timestamp:")} {timestamp}", -- 2.45.3 From 891b36ccaae6537c6c60fb8311e2cb1be1a938d3 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:42:25 -0400 Subject: [PATCH 307/376] fix(aurora): fixed another syntax error in changes_factory --- aurora/utilities/factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index f512456..732cf87 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -268,7 +268,7 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E f"{bold('Reason:')} {change.reason}" if change.reason else "", f"{bold('Duration:')} {humanize_timedelta(timedelta=change.duration)}" if change.duration else "", f"{bold('End Timestamp:')} {end_timestamp}" if end_timestamp else "", - f"{bold("Timestamp:")} {timestamp}", + f"{bold('Timestamp')} {timestamp}", ] change_str.remove("") -- 2.45.3 From 1c3b9377b5f0c93f55e1bcffcd13d9b90e6aeba5 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:45:02 -0400 Subject: [PATCH 308/376] fix(aurora): catch a ValueError in changes_factory --- aurora/utilities/factory.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 732cf87..3180a74 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -270,7 +270,10 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E f"{bold('End Timestamp:')} {end_timestamp}" if end_timestamp else "", f"{bold('Timestamp')} {timestamp}", ] - change_str.remove("") + try: + change_str.remove("") + except ValueError: + pass embed.add_field( name=change.type.title(), -- 2.45.3 From 709042f057cbd0407ea81681dfdc9c4b4de11eec Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:46:05 -0400 Subject: [PATCH 309/376] fix(aurora): fixed an AttributeError in changes_factory --- aurora/utilities/factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 3180a74..4abad0a 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -277,7 +277,7 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E embed.add_field( name=change.type.title(), - value=change_str.join("\n"), + value="\n".join(change_str), inline=False, ) -- 2.45.3 From edbc950741693ea32539fc86f28701da3a31955c Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:50:52 -0400 Subject: [PATCH 310/376] fix(aurora): remove empty lines in changes_factory and fix timestamp formatting --- aurora/models/change.py | 6 ++++++ aurora/utilities/factory.py | 15 +++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index b5c8ef8..c02fb00 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -22,6 +22,12 @@ class Change(AuroraBaseModel): def unix_timestamp(self) -> int: return int(self.timestamp.timestamp()) + @property + def unix_end_timestamp(self) -> Optional[int]: + if self.end_timestamp: + return int(self.end_timestamp.timestamp()) + return None + def __str__(self): return f"{self.type} {self.user_id} {self.reason}" diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 4abad0a..039e252 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -261,19 +261,18 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E user: PartialUser = memory_dict[str(change.user_id)] timestamp = f" | " - end_timestamp = f" | " if change.end_timestamp else None + end_timestamp = f" | " if change.end_timestamp else None change_str = [ f"{bold('User:')} {inline(user.name)} ({user.id})", - f"{bold('Reason:')} {change.reason}" if change.reason else "", - f"{bold('Duration:')} {humanize_timedelta(timedelta=change.duration)}" if change.duration else "", - f"{bold('End Timestamp:')} {end_timestamp}" if end_timestamp else "", + f"{bold('Reason:')} {change.reason}" if change.reason else None, + f"{bold('Duration:')} {humanize_timedelta(timedelta=change.duration)}" if change.duration else None, + f"{bold('End Timestamp:')} {end_timestamp}" if end_timestamp else None, f"{bold('Timestamp')} {timestamp}", ] - try: - change_str.remove("") - except ValueError: - pass + for string in change_str: + if string is None: + change_str.remove(string) embed.add_field( name=change.type.title(), -- 2.45.3 From 7c86d862cfa239a980e893283273a9491b7aa251 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:52:18 -0400 Subject: [PATCH 311/376] fix(aurora): fixed a TypeError --- aurora/utilities/factory.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 039e252..c5222d5 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -265,13 +265,13 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E change_str = [ f"{bold('User:')} {inline(user.name)} ({user.id})", - f"{bold('Reason:')} {change.reason}" if change.reason else None, - f"{bold('Duration:')} {humanize_timedelta(timedelta=change.duration)}" if change.duration else None, - f"{bold('End Timestamp:')} {end_timestamp}" if end_timestamp else None, + f"{bold('Reason:')} {change.reason}" if change.reason else "", + f"{bold('Duration:')} {humanize_timedelta(timedelta=change.duration)}" if change.duration else "", + f"{bold('End Timestamp:')} {end_timestamp}" if end_timestamp else "", f"{bold('Timestamp')} {timestamp}", ] for string in change_str: - if string is None: + if string == "": change_str.remove(string) embed.add_field( -- 2.45.3 From 5d22e67864aa082a6ebe205f6046bc68b23dcce1 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:53:15 -0400 Subject: [PATCH 312/376] fix(aurora): don't mutate a list while iterating through it --- aurora/utilities/factory.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index c5222d5..319de3f 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -270,13 +270,14 @@ async def changes_factory(interaction: Interaction, moderation: Moderation) -> E f"{bold('End Timestamp:')} {end_timestamp}" if end_timestamp else "", f"{bold('Timestamp')} {timestamp}", ] + copy = change_str.copy() for string in change_str: if string == "": - change_str.remove(string) + copy.remove(string) embed.add_field( name=change.type.title(), - value="\n".join(change_str), + value="\n".join(copy), inline=False, ) -- 2.45.3 From 797793b970293f27fde76c09b9857e5912e4c74c Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 19 Aug 2024 17:57:26 -0400 Subject: [PATCH 313/376] feat(aurora): add _obj to the partial models --- aurora/models/partials.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/aurora/models/partials.py b/aurora/models/partials.py index 68b0261..05c3cc8 100644 --- a/aurora/models/partials.py +++ b/aurora/models/partials.py @@ -1,4 +1,5 @@ -from discord import ChannelType, Forbidden, Guild, HTTPException, InvalidData, NotFound +from discord import ChannelType, Forbidden, Guild, HTTPException, InvalidData, NotFound, Role, User +from discord.abc import Messageable from redbot.core.bot import Red from .base import AuroraBaseModel, AuroraGuildModel @@ -8,6 +9,7 @@ class PartialUser(AuroraBaseModel): id: int username: str discriminator: int + _obj: User | None @property def name(self): @@ -22,16 +24,17 @@ class PartialUser(AuroraBaseModel): if not user: try: user = await bot.fetch_user(user_id) - return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator) + return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator, _obj=user) except NotFound: - return cls(bot=bot, id=user_id, username="Deleted User", discriminator=0) - return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator) + return cls(bot=bot, id=user_id, username="Deleted User", discriminator=0, _obj=None) + return cls(bot=bot, id=user.id, username=user.name, discriminator=user.discriminator, _obj=user) class PartialChannel(AuroraGuildModel): id: int name: str type: ChannelType + _obj: Messageable | None @property def mention(self): @@ -48,16 +51,17 @@ class PartialChannel(AuroraGuildModel): if not channel: try: channel = await bot.fetch_channel(channel_id) - return cls(bot=bot, guild_id=channel.guild.id, guild=guild, id=channel.id, name=channel.name, type=channel.type) + return cls(bot=bot, guild_id=channel.guild.id, guild=guild, id=channel.id, name=channel.name, type=channel.type, _obj=channel) except (NotFound, InvalidData, HTTPException, Forbidden) as e: if e == Forbidden: return cls(bot=bot, guild_id=0, id=channel_id, name="Forbidden Channel") - return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel", type=ChannelType.text) - return cls(bot=bot, guild_id=channel.guild.id, guild=guild, id=channel.id, name=channel.name, type=channel.type) + return cls(bot=bot, guild_id=0, id=channel_id, name="Deleted Channel", type=ChannelType.text, _obj=None) + return cls(bot=bot, guild_id=channel.guild.id, guild=guild, id=channel.id, name=channel.name, type=channel.type, _obj=channel) class PartialRole(AuroraGuildModel): id: int name: str + _obj: Role | None @property def mention(self): @@ -72,5 +76,5 @@ class PartialRole(AuroraGuildModel): async def from_id(cls, bot: Red, guild: Guild, role_id: int) -> "PartialRole": role = guild.get_role(role_id) if not role: - return cls(bot=bot, guild_id=guild.id, id=role_id, name="Deleted Role") - return cls(bot=bot, guild_id=guild.id, id=role.id, name=role.name) + return cls(bot=bot, guild_id=guild.id, id=role_id, name="Deleted Role", _obj=None) + return cls(bot=bot, guild_id=guild.id, id=role.id, name=role.name, _obj=role) -- 2.45.3 From 8479dcdd484ab4c60a4c0bc5df82b0bc52bbcf74 Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 21 Aug 2024 14:15:25 -0400 Subject: [PATCH 314/376] fix(aurora): fixed a bug in the Aurora importer that prevented new imports from being imported --- aurora/importers/aurora.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index f34a7b3..011cafb 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -63,9 +63,10 @@ class ImportAuroraView(ui.View): if "changes" not in case or not case["changes"]: changes = [] else: - changes = json.loads(case["changes"]) - if isinstance(changes, str): - changes: list[dict] = json.loads(changes) + if not isinstance(case["changes"], list): + changes = json.loads(case["changes"]) + if isinstance(changes, str): + changes: list[dict] = json.loads(changes) for change in changes: if change.get("bot"): @@ -74,7 +75,10 @@ class ImportAuroraView(ui.View): if "metadata" not in case: metadata = {} else: - metadata: Dict[str, any] = json.loads(case["metadata"]) + if isinstance(case["metadata"], str): + metadata: Dict[str, any] = json.loads(case["metadata"]) + else: + metadata = case["metadata"] if not metadata.get("imported_from"): metadata.update({"imported_from": "Aurora"}) metadata.update({"imported_timestamp": int(time())}) -- 2.45.3 From fce4001152fd5b89ea28026f705827f17e118a7b Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 21 Aug 2024 14:48:56 -0400 Subject: [PATCH 315/376] fix(aurora): hopefully fixed changes not being imported --- aurora/importers/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 011cafb..caff53c 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -60,7 +60,7 @@ class ImportAuroraView(ui.View): case["target_id"] = int(case["target_id"]) case["moderator_id"] = int(case["moderator_id"]) - if "changes" not in case or not case["changes"]: + if not case.get("changes", None): changes = [] else: if not isinstance(case["changes"], list): -- 2.45.3 From 64758686bb782352f8cb01ded501452bcb640490 Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 21 Aug 2024 14:49:47 -0400 Subject: [PATCH 316/376] misc(aurora): simplified AuroraGuildModel a bit --- aurora/models/base.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/aurora/models/base.py b/aurora/models/base.py index d3bc075..0e2ec5f 100644 --- a/aurora/models/base.py +++ b/aurora/models/base.py @@ -25,7 +25,3 @@ class AuroraGuildModel(AuroraBaseModel): def dump(self) -> dict: return self.model_dump(exclude={"bot", "guild_id", "guild"}) - - def to_json(self, indent: int | None = None, file: Any | None = None, **kwargs) -> str: - from ..utilities.json import dump, dumps # pylint: disable=cyclic-import - return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.dump(), indent=indent, **kwargs) -- 2.45.3 From a3ad38f33867a1dd9f706fda11ac6cf4d0f81a85 Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 21 Aug 2024 15:15:50 -0400 Subject: [PATCH 317/376] misc(aurora): improved `Change.from_dict()` --- aurora/models/change.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index c02fb00..e9f376f 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -40,16 +40,16 @@ class Change(AuroraBaseModel): data = json.loads(data) if data.get('duration'): logger.debug(f"Duration: {data['duration']}") - if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta) and not data["duration"] == "NULL": + if data.get('duration') and not isinstance(data["duration"], timedelta) and not data["duration"] == "NULL": duration = timedelta_from_string(data["duration"]) - elif "duration" in data and isinstance(data["duration"], timedelta): + elif data.get('duration') and isinstance(data["duration"], timedelta): duration = data["duration"] else: duration = None - if "end_timestamp" in data and data["end_timestamp"] and not isinstance(data["end_timestamp"], datetime): + if data.get('end_timestamp') and not isinstance(data["end_timestamp"], datetime): end_timestamp = datetime.fromtimestamp(data["end_timestamp"]) - elif "end_timestamp" in data and isinstance(data["end_timestamp"], datetime): + elif data.get('end_timestamp') and isinstance(data["end_timestamp"], datetime): end_timestamp = data["end_timestamp"] else: end_timestamp = None -- 2.45.3 From 4d2004ed93ea585239e2fe8de77480dfc4d43940 Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 21 Aug 2024 15:16:10 -0400 Subject: [PATCH 318/376] fix(aurora): fix changes not being imported --- aurora/importers/aurora.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index caff53c..9e4fdc2 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -60,16 +60,17 @@ class ImportAuroraView(ui.View): case["target_id"] = int(case["target_id"]) case["moderator_id"] = int(case["moderator_id"]) - if not case.get("changes", None): + changes = case.get("changes", None) + if not changes: changes = [] else: - if not isinstance(case["changes"], list): - changes = json.loads(case["changes"]) + if not isinstance(changes, list): + changes = json.loads(changes) if isinstance(changes, str): changes: list[dict] = json.loads(changes) for change in changes: - if change.get("bot"): + if "bot" in change: del change["bot"] if "metadata" not in case: -- 2.45.3 From cd3d3c77333acc9b6bc96250f962e266d64f704e Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 21 Aug 2024 15:16:40 -0400 Subject: [PATCH 319/376] fix(aurora): make sure the `bot` key does not exist in the `Change.from_dict()` data dictionary --- aurora/models/change.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aurora/models/change.py b/aurora/models/change.py index e9f376f..35a722f 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -69,4 +69,6 @@ class Change(AuroraBaseModel): "end_timestamp": end_timestamp, "duration": duration }) + if "bot" in data: + del data["bot"] return cls(bot=bot, **data) -- 2.45.3 From 101d364241d683b559c27b28117b4c94f4fbb008 Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 21 Aug 2024 17:21:54 -0400 Subject: [PATCH 320/376] misc(aurora): remove a useless logging call --- aurora/models/change.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index 35a722f..ff95a57 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -4,7 +4,6 @@ from typing import Literal, Optional from redbot.core.bot import Red -from ..utilities.logger import logger from ..utilities.utils import timedelta_from_string from .base import AuroraBaseModel from .partials import PartialUser @@ -38,8 +37,6 @@ class Change(AuroraBaseModel): def from_dict(cls, bot: Red, data: dict) -> "Change": if isinstance(data, str): data = json.loads(data) - if data.get('duration'): - logger.debug(f"Duration: {data['duration']}") if data.get('duration') and not isinstance(data["duration"], timedelta) and not data["duration"] == "NULL": duration = timedelta_from_string(data["duration"]) elif data.get('duration') and isinstance(data["duration"], timedelta): -- 2.45.3 From 064784c9d7cb3b4ea2e57daabe2bbb2c0ab3aa47 Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 22 Aug 2024 12:26:42 -0400 Subject: [PATCH 321/376] fix(aurora): fixed the `Note` moderation type handler using `cls.string` instead of `cls.verb` --- aurora/models/moderation_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 8205617..eb7d8db 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -37,7 +37,7 @@ class Note(Type): @classmethod async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str) -> 'Note': response = await ctx.send( - content=f"{target.mention} has {cls.embed_desc}{cls.string}!\n**Reason** - `{reason}`" + content=f"{target.mention} has {cls.embed_desc}{cls.verb}!\n**Reason** - `{reason}`" ) if silent is False: -- 2.45.3 From 794ce56040a3c445dfd38bfcf5f663808d64d607 Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 22 Aug 2024 12:33:30 -0400 Subject: [PATCH 322/376] misc(aurora): changed a docstring --- aurora/models/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/models/base.py b/aurora/models/base.py index 0e2ec5f..43c9d89 100644 --- a/aurora/models/base.py +++ b/aurora/models/base.py @@ -18,7 +18,7 @@ class AuroraBaseModel(BaseModel): return dump(self.dump(), file, indent=indent, **kwargs) if file else dumps(self.dump(), indent=indent, **kwargs) class AuroraGuildModel(AuroraBaseModel): - """Subclass of AuroraBaseModel that includes a guild_id attribute and a guild attribute, and a modified to_json() method to match.""" + """Subclass of AuroraBaseModel that includes a guild_id attribute and a guild attribute.""" model_config = ConfigDict(ignored_types=(Red, Guild), arbitrary_types_allowed=True) guild_id: int guild: Optional[Guild] = None -- 2.45.3 From fa27d12de5bcc324aaaa5075e23466a10651fb3f Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 22 Aug 2024 15:33:36 -0400 Subject: [PATCH 323/376] feat(aurora): make all models compatible with `repr` --- aurora/models/base.py | 3 +++ aurora/models/change.py | 12 ++++++++++++ aurora/models/moderation.py | 23 +++++++++++++++++++++++ aurora/models/partials.py | 9 +++++++++ aurora/models/type.py | 8 ++++++++ 5 files changed, 55 insertions(+) diff --git a/aurora/models/base.py b/aurora/models/base.py index 43c9d89..d94b635 100644 --- a/aurora/models/base.py +++ b/aurora/models/base.py @@ -25,3 +25,6 @@ class AuroraGuildModel(AuroraBaseModel): def dump(self) -> dict: return self.model_dump(exclude={"bot", "guild_id", "guild"}) + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} guild_id={self.guild_id}>" diff --git a/aurora/models/change.py b/aurora/models/change.py index ff95a57..f5e5f64 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -30,6 +30,18 @@ class Change(AuroraBaseModel): def __str__(self): return f"{self.type} {self.user_id} {self.reason}" + def __repr__(self) -> str: + attrs = [ + ('type', self.type), + ('timestamp', self.timestamp), + ('user_id', self.user_id), + ('reason', self.reason), + ('duration', self.duration), + ('end_timestamp', self.end_timestamp), + ] + joined = ' '.join('%s=%r' % t for t in attrs) + return f"<{self.__class__.__name__} {joined}>" + async def get_user(self) -> "PartialUser": return await PartialUser.from_id(self.bot, self.user_id) diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 18dffa2..616c426 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -122,6 +122,29 @@ class Moderation(AuroraGuildModel): def __int__(self) -> int: return self.moderation_id + def __repr__(self) -> str: + attrs = [ + ('guild_id', self.guild_id), + ('moderation_id', self.moderation_id), + ('timestamp', self.timestamp), + ('type', self.type), + ('target_type', self.target_type), + ('target_id', self.target_id), + ('moderator_id', self.moderator_id), + ('role_id', self.role_id), + ('duration', self.duration), + ('end_timestamp', self.end_timestamp), + ('reason', self.reason), + ('resolved', self.resolved), + ('resolved_by', self.resolved_by), + ('resolve_reason', self.resolve_reason), + ('expired', self.expired), + ('changes', self.changes), + ('metadata', self.metadata), + ] + joined = ' '.join('%s=%r' % t for t in attrs) + return f"<{self.__class__.__name__} {joined}>" + async def resolve(self, resolved_by: int, reason: str) -> Tuple[bool, str]: if self.resolved: raise ValueError("Case is already resolved!") diff --git a/aurora/models/partials.py b/aurora/models/partials.py index 05c3cc8..0aaa246 100644 --- a/aurora/models/partials.py +++ b/aurora/models/partials.py @@ -18,6 +18,9 @@ class PartialUser(AuroraBaseModel): def __str__(self): return self.name + def __repr__(self): + return f"<{self.__class__.__name__} id={self.id}>" + @classmethod async def from_id(cls, bot: Red, user_id: int) -> "PartialUser": user = bot.get_user(user_id) @@ -45,6 +48,9 @@ class PartialChannel(AuroraGuildModel): def __str__(self): return self.mention + def __repr__(self): + return f"<{self.__class__.__name__} id={self.id} guild_id={self.guild_id}>" + @classmethod async def from_id(cls, bot: Red, channel_id: int, guild: Guild) -> "PartialChannel": channel = bot.get_channel(channel_id) @@ -72,6 +78,9 @@ class PartialRole(AuroraGuildModel): def __str__(self): return self.mention + def __repr__(self) -> str: + return f"<{self.__class__.__name__} id={self.id} guild_id={self.guild_id}>" + @classmethod async def from_id(cls, bot: Red, guild: Guild, role_id: int) -> "PartialRole": role = guild.get_role(role_id) diff --git a/aurora/models/type.py b/aurora/models/type.py index 6cc8092..ba806a5 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -43,6 +43,14 @@ class Type(metaclass=AutoRegister(type_registry)): def __str__(self) -> str: return self.string + def __repr__(self) -> str: + attrs = [ + ('key', self.key), + ('channel', self.channel), + ] + joined = ' '.join('%s=%r' % t for t in attrs) + return f"<{self.__class__.__name__} {joined}>" + @classmethod async def handler(cls, ctx: commands.Context, target: Member | User | Messageable, silent: bool, **kwargs) -> 'Type': # pylint: disable=unused-argument """This method should be overridden by any child classes, but should retain the same starting keyword arguments. -- 2.45.3 From 320db1b6922e0412229ffae4f0450901b83f0ddd Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 22 Aug 2024 15:44:22 -0400 Subject: [PATCH 324/376] fix(aurora): make sure that bans with durations are imported as tempbans --- aurora/importers/aurora.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index 9e4fdc2..621d76f 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -86,6 +86,8 @@ class ImportAuroraView(ui.View): if case["duration"] != "NULL" and case["duration"] is not None: duration = timedelta_from_string(case["duration"]) + if moderation_type.key == "ban": + moderation_type = type_registry["tempban"] else: duration = None -- 2.45.3 From 43e82c9eb5ce7d51f3a27c79cdb4b1cbb64af6c1 Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 22 Aug 2024 15:59:23 -0400 Subject: [PATCH 325/376] feat(aurora): minify export json to reduce file sizes --- aurora/aurora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 187d14a..dee6152 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -728,7 +728,7 @@ class Aurora(commands.Cog): ) with open(filepath, "w", encoding="utf-8") as f: - dump(obj=moderations, fp=f, indent=2) + dump(obj=moderations, fp=f) await interaction.followup.send( file=discord.File( -- 2.45.3 From bc3ea67e1e74075498af7f4160883e3a369f6cad Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 22 Aug 2024 16:04:37 -0400 Subject: [PATCH 326/376] fix(aurora): pylint fixes --- aurora/models/change.py | 2 +- aurora/models/moderation.py | 2 +- aurora/models/type.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aurora/models/change.py b/aurora/models/change.py index f5e5f64..00358f9 100644 --- a/aurora/models/change.py +++ b/aurora/models/change.py @@ -39,7 +39,7 @@ class Change(AuroraBaseModel): ('duration', self.duration), ('end_timestamp', self.end_timestamp), ] - joined = ' '.join('%s=%r' % t for t in attrs) + joined = ' '.join(f'{key}={value!r}' for key, value in attrs) return f"<{self.__class__.__name__} {joined}>" async def get_user(self) -> "PartialUser": diff --git a/aurora/models/moderation.py b/aurora/models/moderation.py index 616c426..9153e24 100644 --- a/aurora/models/moderation.py +++ b/aurora/models/moderation.py @@ -142,7 +142,7 @@ class Moderation(AuroraGuildModel): ('changes', self.changes), ('metadata', self.metadata), ] - joined = ' '.join('%s=%r' % t for t in attrs) + joined = ' '.join(f'{key}={value!r}' for key, value in attrs) return f"<{self.__class__.__name__} {joined}>" async def resolve(self, resolved_by: int, reason: str) -> Tuple[bool, str]: diff --git a/aurora/models/type.py b/aurora/models/type.py index ba806a5..60a4815 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -48,7 +48,7 @@ class Type(metaclass=AutoRegister(type_registry)): ('key', self.key), ('channel', self.channel), ] - joined = ' '.join('%s=%r' % t for t in attrs) + joined = ' '.join(f'{key}={value!r}' for key, value in attrs) return f"<{self.__class__.__name__} {joined}>" @classmethod -- 2.45.3 From fadb3e1a9d0c2b29e0529afb77438b246ed82863 Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 22 Aug 2024 17:52:50 -0400 Subject: [PATCH 327/376] fix(aurora): make the `moderation_id` key in the moderation tables not nullable (`NOT NULL`) --- aurora/utilities/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 45c160d..9c97a3b 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -237,7 +237,7 @@ async def create_guild_table(guild: Guild) -> None: except aiosqlite.OperationalError: query = f""" CREATE TABLE `moderation_{guild.id}` ( - moderation_id INTEGER PRIMARY KEY, + moderation_id INTEGER PRIMARY KEY NOT NULL, timestamp INTEGER NOT NULL, moderation_type TEXT NOT NULL, target_type TEXT NOT NULL, -- 2.45.3 From fa8036291ca48c03c2188ecf7437543982c77d5f Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 22 Aug 2024 17:54:36 -0400 Subject: [PATCH 328/376] fix(aurora): bump version and change author key --- aurora/aurora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index dee6152..72b954b 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -45,8 +45,8 @@ class Aurora(commands.Cog): It is heavily inspired by GalacticBot, and is designed to be a more user-friendly alternative to Red's core Mod cogs. This cog stores all of its data in an SQLite database.""" - __author__ = ["Seaswimmer"] - __version__ = "3.0.0-indev20" + __author__ = ["cswimr"] + __version__ = "3.0.0-indev21" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): -- 2.45.3 From 6560f98aefe9315345b3ba15d1ce07ab8e97e432 Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 22 Aug 2024 18:47:17 -0400 Subject: [PATCH 329/376] feat(aurora): add `[p]aurora info` command --- aurora/aurora.py | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 72b954b..46d88e0 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -45,8 +45,9 @@ class Aurora(commands.Cog): It is heavily inspired by GalacticBot, and is designed to be a more user-friendly alternative to Red's core Mod cogs. This cog stores all of its data in an SQLite database.""" - __author__ = ["cswimr"] - __version__ = "3.0.0-indev21" + __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] + __version__ = "3.0.0-indev22" + __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -91,7 +92,7 @@ class Aurora(commands.Cog): n = "\n" if "\n\n" not in pre_processed else "" text = [ f"{pre_processed}{n}", - f"{bold('Cog Version:')} {self.__version__}", + f"{bold('Cog Version:')} [{self.__version__}]({self.__git__})", f"{bold('Author:')} {humanize_list(self.__author__)}", f"{bold('Documentation:')} {self.__documentation__}", ] @@ -1333,3 +1334,44 @@ class Aurora(commands.Cog): await ctx.send(error("Please provide a convertible value!")) return await ctx.send(f"`{parsed_time}`") + + @aurora.command(name="info") + async def aurora_info(self, ctx: commands.Context): + """Get information about Aurora.""" + embed = discord.Embed( + title="Aurora Information", + color=await self.bot.get_embed_color(ctx.channel), + timestamp=datetime.now(), + ) + embed.set_thumbnail(url=self.bot.user.avatar.url) + embed.add_field( + name="Version", + value=f"[{self.__version__}](https://www.coastalcommits.com/cswimr/SeaCogs)" + ) + embed.add_field( + name="Author", + value=', '.join(self.__author__) + ) + if ctx.author.id in self.bot.owner_ids: + results = await Moderation.execute(query="SELECT name FROM sqlite_master WHERE type='table';", return_obj=False) + tables = [table[0] for table in results] + table_count = len(tables) + row_count = 0 + + for table in tables: + count_query = f"SELECT COUNT() FROM {table}" + result = await Moderation.execute(query=count_query, return_obj=False) + row_count += result[0][0] + + filesize = os.path.getsize(str(data_manager.cog_data_path(cog_instance=self) / "aurora.db")) / 1024 + + embed.add_field( + name="Database Stats", + value=f"{bold('Table Count:')} {table_count:,}\n{bold('Row Count:')} {row_count:,}\n{bold('File Size:')} {filesize:,.0f} KB", + ) + embed.add_field( + name="Moderation Types", + value=f"{len(type_registry)} registered types\n{box(', '.join(type_registry.keys()))}", + inline=False + ) + await ctx.send(embed=embed) -- 2.45.3 From 5459392d7e95a8a495bee42a3dd51013e04e6774 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 23 Aug 2024 14:43:43 -0400 Subject: [PATCH 330/376] fix(aurora): update the autologger method to use the new type registry --- aurora/aurora.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 46d88e0..2e35ac7 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] - __version__ = "3.0.0-indev22" + __version__ = "3.0.0-indev23" __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" @@ -189,13 +189,13 @@ class Aurora(commands.Cog): reason = "This action was performed without the bot." if entry.action == discord.AuditLogAction.kick: - moderation_type = "KICK" + moderation_type = type_registry['kick'] elif entry.action == discord.AuditLogAction.ban: - moderation_type = "BAN" + moderation_type = type_registry['ban'] elif entry.action == discord.AuditLogAction.unban: - moderation_type = "UNBAN" + moderation_type = type_registry['unban'] elif entry.action == discord.AuditLogAction.member_update: if entry.after.timed_out_until is not None: @@ -207,22 +207,22 @@ class Aurora(commands.Cog): ) minutes = round(duration_datetime.total_seconds() / 60) duration = timedelta(minutes=minutes) - moderation_type = "MUTE" + moderation_type = type_registry['mute'] else: - moderation_type = "UNMUTE" + moderation_type = type_registry['unmute'] else: return await Moderation.log( - self.bot, - entry.guild.id, - entry.user.id, - moderation_type, - "USER", - entry.target.id, - None, - duration, - reason, + bot=self.bot, + guild_id=entry.guild.id, + moderator_id=entry.user.id, + moderation_type=moderation_type, + target_type="USER", + target_id=entry.target.id, + role_id=None, + duration=duration, + reason=reason, ) except AttributeError: return -- 2.45.3 From 5934506c8af7de87d35d483cd61988791af1c113 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 23 Aug 2024 14:54:06 -0400 Subject: [PATCH 331/376] fix(aurora): make `silent` an optional argument in `Aurora.moderate()` --- aurora/aurora.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 2e35ac7..1d13b98 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] - __version__ = "3.0.0-indev23" + __version__ = "3.0.0-indev24" __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" @@ -114,16 +114,16 @@ class Aurora(commands.Cog): self.handle_expiry.cancel() @staticmethod - async def moderate(ctx: Union[commands.Context, discord.Interaction], target: discord.Member | discord.User | discord.abc.Messageable, silent: bool | None, permissions: List[str], moderation_type: Type | str, **kwargs) -> None | Type: + async def moderate(ctx: Union[commands.Context, discord.Interaction], target: discord.Member | discord.User | discord.abc.Messageable, permissions: List[str], moderation_type: Type | str, silent: bool | None = None, **kwargs) -> None | Type: """This function is used to moderate users. It checks if the target can be moderated, then calls the handler method of the moderation type specified. Args: ctx (Union[commands.Context, discord.Interaction]): The context of the command. If this is a `discord.Interaction` object, it will be converted to a `commands.Context` object. Additionally, if the interaction orignated from a context menu, the `ctx.author` attribute will be overriden to `interaction.user`. target (discord.Member, discord.User, discord.abc.Messageable): The target user or channel to moderate. - silent (bool | None): Whether to send the moderation action to the target. permissions (List[str]): The permissions required to moderate the target. moderation_type (Type): The moderation type (handler) to use. See `aurora.models.moderation_types` for some examples. + silent (bool, optional): Whether or not to message the target. Defaults to None. **kwargs: The keyword arguments to pass to the handler method. """ if isinstance(moderation_type, str): -- 2.45.3 From d600a10729aa0f5ecd11e6709d90ff553a0b7a2b Mon Sep 17 00:00:00 2001 From: cswimr Date: Sat, 24 Aug 2024 19:13:01 -0400 Subject: [PATCH 332/376] fix(aurora): don't try and use the attribute of a Member object when the object is a User object --- aurora/aurora.py | 2 +- aurora/utilities/utils.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 1d13b98..0b5098c 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] - __version__ = "3.0.0-indev24" + __version__ = "3.0.0-indev25" __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 9c97a3b..c0cac6f 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -84,12 +84,6 @@ async def check_moddable( ) return False - if target.guild_permissions.administrator: - await ctx.send( - content="You cannot moderate members with the Administrator permission!", ephemeral=True - ) - return False - if isinstance(target, Member): if ctx.author.top_role <= target.top_role and await config.guild(ctx.guild).respect_hierarchy() is True: await ctx.send( @@ -100,6 +94,12 @@ async def check_moddable( ) return False + if target.guild_permissions.administrator: + await ctx.send( + content="You cannot moderate members with the Administrator permission!", ephemeral=True + ) + return False + if ( ctx.guild.get_member(ctx.bot.user.id).top_role <= target.top_role -- 2.45.3 From 9e21879a498651bb2ba6a6e7d638f4ec19e8e96d Mon Sep 17 00:00:00 2001 From: cswimr Date: Sat, 24 Aug 2024 19:21:49 -0400 Subject: [PATCH 333/376] fix(aurora): fixed note's handler using cls.string where it should have been using cls.verb --- aurora/aurora.py | 2 +- aurora/models/moderation_types.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 0b5098c..76a8950 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] - __version__ = "3.0.0-indev25" + __version__ = "3.0.0-indev26" __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index eb7d8db..4c0fcc7 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -67,7 +67,7 @@ class Note(Type): reason=reason, ) await response.edit( - content=f"{target.mention} has {cls.embed_desc}{cls.string}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" + content=f"{target.mention} has {cls.embed_desc}{cls.verb}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`" ) await log(ctx=ctx, moderation_id=moderation.id) await send_evidenceformat(ctx=ctx, moderation_id=moderation.id) -- 2.45.3 From d4fe97f24741bc6ea643d3e1cfdbd9b3915f46d4 Mon Sep 17 00:00:00 2001 From: seaswimmer Date: Sun, 8 Sep 2024 12:33:16 -0400 Subject: [PATCH 334/376] fix(aurora): fixed retrieving a User object instead of a Member object --- aurora/models/moderation_types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aurora/models/moderation_types.py b/aurora/models/moderation_types.py index 4c0fcc7..0dda5d6 100644 --- a/aurora/models/moderation_types.py +++ b/aurora/models/moderation_types.py @@ -243,7 +243,7 @@ class AddRole(Type): @classmethod async def expiry_handler(cls, moderation: Moderation) -> int: try: - target = moderation.bot.get_user(moderation.target_id) + target = moderation.guild.get_member(moderation.target_id) if not target: try: target = await moderation.guild.fetch_member(moderation.target_id) @@ -418,7 +418,7 @@ class RemoveRole(Type): @classmethod async def expiry_handler(cls, moderation: Moderation) -> int: try: - target = moderation.bot.get_user(moderation.target_id) + target = moderation.guild.get_member(moderation.target_id) if not target: try: target = await moderation.guild.fetch_member(moderation.target_id) -- 2.45.3 From b91946abeb06bed8a59ec34bf9c5eb1d9b13e9cc Mon Sep 17 00:00:00 2001 From: seaswimmer Date: Sun, 8 Sep 2024 12:40:38 -0400 Subject: [PATCH 335/376] fix(aurora): catch exceptions thrown inside of the expiry handler instead of just stopping the task --- aurora/aurora.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aurora/aurora.py b/aurora/aurora.py index 76a8950..616ab6a 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1133,6 +1133,9 @@ class Aurora(commands.Cog): except NotImplementedError: logger.warning("Expiry handler not implemented for expirable moderation type %s", moderation.type.key) continue + except Exception as e: # pylint: disable=broad-except + logger.exception("Expiry handler failed for moderation %s with the type %s", moderation.id, moderation.type.key, exc_info=e) + continue match moderation.type.key: case "tempban": unban_num += num -- 2.45.3 From 1c941462dfbdd5ea48bea862bc20d838f26b82f5 Mon Sep 17 00:00:00 2001 From: seaswimmer Date: Sun, 8 Sep 2024 12:47:01 -0400 Subject: [PATCH 336/376] feat(aurora): log how many errors occured in the handle_expiry task --- aurora/aurora.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 616ab6a..aa08b5d 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -1114,6 +1114,7 @@ class Aurora(commands.Cog): global_addrole_num = 0 global_removerole_num = 0 global_other_num = 0 + global_err_num = 0 guilds: list[discord.Guild] = self.bot.guilds for guild in guilds: @@ -1127,6 +1128,7 @@ class Aurora(commands.Cog): removerole_num = 0 addrole_num = 0 other_num = 0 + error_num = 0 for moderation in moderations: try: num = await moderation.type.expiry_handler(moderation) @@ -1135,6 +1137,7 @@ class Aurora(commands.Cog): continue except Exception as e: # pylint: disable=broad-except logger.exception("Expiry handler failed for moderation %s with the type %s", moderation.id, moderation.type.key, exc_info=e) + error_num += 1 continue match moderation.type.key: case "tempban": @@ -1151,10 +1154,11 @@ class Aurora(commands.Cog): per_guild_completion_time = (time.time() - time_per_guild) * 1000 logger.debug( - "Completed expiry loop for %s (%s) in %sms with %s users unbanned, %s roles added, and %s roles removed (%s other cases expired)", + "Completed expiry loop for %s (%s) in %sms with %s errors, %s users unbanned, %s roles added, and %s roles removed (%s other cases expired)", guild.name, guild.id, f"{per_guild_completion_time:.6f}", + error_num, unban_num, addrole_num, removerole_num, @@ -1164,12 +1168,14 @@ class Aurora(commands.Cog): global_addrole_num = global_addrole_num + addrole_num global_removerole_num = global_removerole_num + removerole_num global_other_num = global_other_num + other_num + global_err_num = global_err_num + error_num completion_time = (time.time() - current_time) * 1000 logger.debug( - "Completed expiry loop in %sms with %s users unbanned, %s roles added, and %s roles removed (%s other cases expired)", + "Completed expiry loop in %sms with %s errors, %s users unbanned, %s roles added, and %s roles removed (%s other cases expired)", f"{completion_time:.6f}", + global_err_num, global_unban_num, global_addrole_num, global_removerole_num, -- 2.45.3 From 405729f37de491affa9e896fb474a7d2f3e80559 Mon Sep 17 00:00:00 2001 From: seaswimmer Date: Fri, 20 Sep 2024 10:38:49 -0400 Subject: [PATCH 337/376] force downgrade of phx-class-registry Signed-off-by: seaswimmer --- aurora/info.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/info.json b/aurora/info.json index fa80f99..dc724e0 100644 --- a/aurora/info.json +++ b/aurora/info.json @@ -9,7 +9,7 @@ "disabled": false, "min_bot_version": "3.5.0", "min_python_version": [3, 10, 0], - "requirements": ["pydantic", "aiosqlite", "phx-class-registry"], + "requirements": ["pydantic", "aiosqlite", "phx-class-registry==4.1.0"], "tags": [ "mod", "moderate", -- 2.45.3 From 97406e7bac36e74b6f93510cd94e2782462834d2 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 20 Sep 2024 14:49:28 -0400 Subject: [PATCH 338/376] feat(aurora): updated phx-class-registry to ^5.0.0 and fixed some typos --- aurora/aurora.py | 10 +- aurora/info.json | 4 +- aurora/models/type.py | 9 +- poetry.lock | 1316 +++++++++++++++++++++-------------------- pyproject.toml | 2 +- 5 files changed, 694 insertions(+), 647 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index aa08b5d..84c2252 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -46,7 +46,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] - __version__ = "3.0.0-indev26" + __version__ = "3.0.0-indev27" __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" @@ -119,7 +119,7 @@ class Aurora(commands.Cog): It checks if the target can be moderated, then calls the handler method of the moderation type specified. Args: - ctx (Union[commands.Context, discord.Interaction]): The context of the command. If this is a `discord.Interaction` object, it will be converted to a `commands.Context` object. Additionally, if the interaction orignated from a context menu, the `ctx.author` attribute will be overriden to `interaction.user`. + ctx (Union[commands.Context, discord.Interaction]): The context of the command. If this is a `discord.Interaction` object, it will be converted to a `commands.Context` object. Additionally, if the interaction originated from a context menu the `ctx.author` attribute will be overridden to `interaction.user`. target (discord.Member, discord.User, discord.abc.Messageable): The target user or channel to moderate. permissions (List[str]): The permissions required to moderate the target. moderation_type (Type): The moderation type (handler) to use. See `aurora.models.moderation_types` for some examples. @@ -742,7 +742,7 @@ class Aurora(commands.Cog): except json.JSONDecodeError as e: await interaction.followup.send( content=error( - "An error occured while exporting the moderation history.\nError:\n" + "An error occurred while exporting the moderation history.\nError:\n" ) + box(text=e, lang="py"), ephemeral=ephemeral, @@ -1196,7 +1196,7 @@ class Aurora(commands.Cog): @aurora_settings.command(name="overrides", aliases=["override", "user"]) async def aurora_settings_overrides(self, ctx: commands.Context): - """Manage Aurora's user overriddable settings.""" + """Manage Aurora's user overridable settings.""" msg = await ctx.send(embed=await overrides_embed(ctx)) await msg.edit(view=Overrides(ctx, msg, 60)) @@ -1355,7 +1355,7 @@ class Aurora(commands.Cog): embed.set_thumbnail(url=self.bot.user.avatar.url) embed.add_field( name="Version", - value=f"[{self.__version__}](https://www.coastalcommits.com/cswimr/SeaCogs)" + value=f"[{self.__version__}]({self.__git__})" ) embed.add_field( name="Author", diff --git a/aurora/info.json b/aurora/info.json index dc724e0..2db0794 100644 --- a/aurora/info.json +++ b/aurora/info.json @@ -1,5 +1,5 @@ { - "author" : ["Seaswimmer (seasw.)"], + "author" : ["Seaswimmer (cswimr)"], "install_msg" : "Thank you for installing Aurora!\nMost of this cog's functionality requires enabling slash commands.\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).", "name" : "Aurora", "short" : "A full replacement for Red's core Mod cogs.", @@ -9,7 +9,7 @@ "disabled": false, "min_bot_version": "3.5.0", "min_python_version": [3, 10, 0], - "requirements": ["pydantic", "aiosqlite", "phx-class-registry==4.1.0"], + "requirements": ["pydantic", "aiosqlite", "phx-class-registry==5.0.0"], "tags": [ "mod", "moderate", diff --git a/aurora/models/type.py b/aurora/models/type.py index 60a4815..1df3887 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -1,14 +1,15 @@ -from abc import abstractmethod +from abc import ABC, abstractmethod from typing import Any, Dict, Tuple -from class_registry import AutoRegister, ClassRegistry +from class_registry import ClassRegistry +from class_registry.base import AutoRegister from discord import Interaction, Member, User from discord.abc import Messageable from redbot.core import commands type_registry: Dict['str', 'Type'] = ClassRegistry(attr_name='key', unique=True) -class Type(metaclass=AutoRegister(type_registry)): +class Type(AutoRegister(type_registry), ABC): """This is a base class for moderation types. Attributes: @@ -16,7 +17,7 @@ class Type(metaclass=AutoRegister(type_registry)): string (str): The string to display for this type. verb (str): The verb to use for this type. embed_desc (str): The string to use for embed descriptions. - channel (bool): Whether this type targets channels or users. If this is `true` in a subclass, its overriden handler methods should be typed with `discord.abc.Messageable` instead of `discord.Member | discord.User`. + channel (bool): Whether this type targets channels or users. If this is `true` in a subclass, its overridden handler methods should be typed with `discord.abc.Messageable` instead of `discord.Member | discord.User`. removes_from_guild (bool): Whether this type's handler removes the target from the guild, or if the moderation is expected to occur whenever the user is not in the guild. This does not actually remove the target from the guild, the handler method is responsible for that. Properties: diff --git a/poetry.lock b/poetry.lock index 8387385..627a8a8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -154,58 +154,72 @@ files = [ [[package]] name = "apsw" -version = "3.46.0.1" +version = "3.46.1.0" description = "Another Python SQLite Wrapper" optional = false python-versions = ">=3.8" files = [ - {file = "apsw-3.46.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376252c7549f655cb5247a4f35bca32e02201e7b06e168d757be079343ca3e51"}, - {file = "apsw-3.46.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:77c58fc2bb63cc89dd109aa260eddb0e21c7ee018ae5a63305b67e8c2503879d"}, - {file = "apsw-3.46.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e765a23679fe41e5466839288afdf70b874af06862d4f893c986a6aa6605caf4"}, - {file = "apsw-3.46.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d74cf3e9a8d2df9fedc84d88b602e2a4d5ea6e6eb206e1a98d1bbc7120fa2cd2"}, - {file = "apsw-3.46.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af24db1431f07f8a52347bc5eb67cd2c8abff3c4ba9119516920bd337ccaaea5"}, - {file = "apsw-3.46.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c647d8adf270329fda0a47f6b3ddbbd37e11c54e61e7f37238b543fe859692"}, - {file = "apsw-3.46.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1d2c1e53ed2525c3ed97abfba83a685adc289cc8939230f771db2365c8193b2c"}, - {file = "apsw-3.46.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b28b8b6f83dfe1721a08913542660c56afefb29c29c2c8a4e6c798e070c776f0"}, - {file = "apsw-3.46.0.1-cp310-cp310-win32.whl", hash = "sha256:ef67d20a617e9d3b560a4d40278beffac432222df2d2b3e411231a839a6c9b8b"}, - {file = "apsw-3.46.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:88fd8f33a4fc33cb2dd2fafd195763234525b15b3743a39f40fb26c6594f0d40"}, - {file = "apsw-3.46.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f6c752b27aef5ae6c3435bbb8d008aaf4b651667ac30f6e27663d48bb9e77248"}, - {file = "apsw-3.46.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:603ea29d13daf5aabd79886c35128e91ad78d372942c6f60478e2f9327c8f36d"}, - {file = "apsw-3.46.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d7c15e02765013fcd316e3014ee2684ac5ea41b1edee14b49af33de3f57c429"}, - {file = "apsw-3.46.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50ae2f38ed5285cc472be2ccff7235e69354e55b0b679e95b53839e61cdc669a"}, - {file = "apsw-3.46.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:697424946533c8a869e619994895f79e9f7edfbe53fa7985ee43447cde508a7b"}, - {file = "apsw-3.46.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c123e9c20fcb43720c8e3fbaa8e2d0c3cfbd7b90925d4ff58c6caa660d619a83"}, - {file = "apsw-3.46.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:96f9c2d3c47ed0a8517422168f02c75061a566a7a49f9751d77be08a49fb78c5"}, - {file = "apsw-3.46.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dd6b96c795a2feea57db1e2bfb32349dfea12db9e7682d80028c395c78bb6038"}, - {file = "apsw-3.46.0.1-cp311-cp311-win32.whl", hash = "sha256:894eac8b6eadd892a203d026d557b1e1f4033b2a0d3c5ad36ded58d31957e732"}, - {file = "apsw-3.46.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:92f5c8ddf11ba4203bacd8fcba3d5d4bc79142a67b405046d7f9db85fe2aba41"}, - {file = "apsw-3.46.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9c68414281a08a94b8b5c311da59d038bf99217fea5436f9527a0655a4409496"}, - {file = "apsw-3.46.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50434559a7f2c06ffe48ba8f07d8b330c47674e651b0f32449fa23bef168e516"}, - {file = "apsw-3.46.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:354e2f3ad37d8ca3afdeac7dcaf5cae9340cf70a819ccf86d6300114b970ff61"}, - {file = "apsw-3.46.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:347d039d7f6ebe05111516465057007a86aa60ced1122f98f5e2a14bb40febeb"}, - {file = "apsw-3.46.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd382205968bede44d074742c8e99efdb10138fdab1c584f4fb810b6543bed16"}, - {file = "apsw-3.46.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6c5c2115e5b45d5ad7c0e6f19a0ee571d256f0d12937182625ce7028ddb73eae"}, - {file = "apsw-3.46.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:12fe2fca3525431dbb459a4a6aa3bde11d65f47665c76a56b5fced850a7a421e"}, - {file = "apsw-3.46.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:469366689ec6cbf526260d0aa241090b876e55cbf7615a3c6e79715cb789bfdd"}, - {file = "apsw-3.46.0.1-cp312-cp312-win32.whl", hash = "sha256:7ae47a7de0ca9eeee462580a1d1b7e30097ebfac4bd8d69f3b049d11095ca72f"}, - {file = "apsw-3.46.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:347774ee0388ee14cdf54849b2983a9959740457c36a213d3b63e828af3d4c3a"}, - {file = "apsw-3.46.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:64f82d7529387980c427b209a9e556ca238f1f76f838ab823e739e95a2b23984"}, - {file = "apsw-3.46.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8a461f767d829db7ddf8297ab0b4aacbc880186f33f110ac15a6541c30843824"}, - {file = "apsw-3.46.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf62c7f9758a8d61a0d9fcd6ca9a6823319be41700cf0ffda427234d754d00c9"}, - {file = "apsw-3.46.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92c196ccd45c0d51849e2dee4b7b53010e054f4b4720e786d9e9d5fbd1466505"}, - {file = "apsw-3.46.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:e98a1c48a9376a50377f94edd645f18b7edc5e50714754627ecf51a516ec88b3"}, - {file = "apsw-3.46.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:544e71870b1337fd00420092b6bb51478609d07cd58aca22da9c4f054d949280"}, - {file = "apsw-3.46.0.1-cp38-cp38-win32.whl", hash = "sha256:6c9a9ae7b0cdf8d9f84853799b75d9f16d5770448300c755e5f71dd3cc3bf605"}, - {file = "apsw-3.46.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:bec83c29578135d4f9473b05c1ec3ad5c17c15f38dd9efb3e87dbfa0c9372e19"}, - {file = "apsw-3.46.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6a1d636c4ef230b86d2a26cffb626732fd3fd300f9781396bd24283e1ef393e6"}, - {file = "apsw-3.46.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8085c0536b93a0fd5f1158568e85a4e3d33dfaea066ac403c449b0bd53fe0470"}, - {file = "apsw-3.46.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9517fb5e4f7d5c9acfa338e0c5475d7fbf1582a76092fc3c4876e8577a352dd2"}, - {file = "apsw-3.46.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0538051b1db2a7fdfe3c9184abd2b242c5020ecc62c3ba277f39164e3bfb4ac"}, - {file = "apsw-3.46.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9b95d67b553ce672a560e60df584a0197f063096c5a54814de2c49d5399f2571"}, - {file = "apsw-3.46.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d4541eb2c0bd78d833545a25aea00d98338ea3537aa70328cbbaea48d811aa17"}, - {file = "apsw-3.46.0.1-cp39-cp39-win32.whl", hash = "sha256:259d0555a8077ece645fe2aea745938018e4d816a1eee4e0a661078bfc9c2461"}, - {file = "apsw-3.46.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:ea0a32cbcfc3a57f7b0fa4000a1b6a813c1080a1fbefd56d0b90f468742fdd02"}, - {file = "apsw-3.46.0.1.tar.gz", hash = "sha256:a36d1e80180d1dc9c079f766dead8204dfeb1c80707676f9b75c1705800fe7d0"}, + {file = "apsw-3.46.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ebfaf4d84bc61ecf79587acf31a31f732be72cb8fc8c999ce9453147a2e57dc"}, + {file = "apsw-3.46.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2545b9c885f98d7dedf9c0f9c485f84d39c5a40352b8a3c3f05f99e1e1d2ae73"}, + {file = "apsw-3.46.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5b83967c1b68877976a06bb8a2eb314b1f8923d787f6d7cd41b48776847bfe6"}, + {file = "apsw-3.46.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:110dae383750f75fc57d63ea14a759e4309886e1dd5243993db7eaa8f9d06d90"}, + {file = "apsw-3.46.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e403aab2b5653152e85341218a49d73eed66319f0deccce5db21f7a89def394a"}, + {file = "apsw-3.46.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3382459357f0819b631087b32818a502da47c84ddea76132d76ec02aa473af45"}, + {file = "apsw-3.46.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d43d80bbd497ddb86fa5774bd80df1825253a3765e01e707cbcc6242f06f21eb"}, + {file = "apsw-3.46.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:402233ed77b7bd99f81c5b68bd8201dd1c4c1dedc40d12871f709b922842d5c6"}, + {file = "apsw-3.46.1.0-cp310-cp310-win32.whl", hash = "sha256:c17dab34c487ee562f81672f6bf3c067493e017d1a8c816485e6de06ce25f620"}, + {file = "apsw-3.46.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:9484b47e792ad54b36fced07b9ff91b9ab32f0d7de44da3a9b5fa9d78e28ddae"}, + {file = "apsw-3.46.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8acacf3a0187cbd4c82c9eaa2c7e2704c13997a351efdffbdfa69ea1778bda1f"}, + {file = "apsw-3.46.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2fcc5fd76a4a21fb1cc1694495e221206a46d932c675ba5dda8f070262347e0b"}, + {file = "apsw-3.46.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca319360995762fbed9e7d252c3ae4ea84af2d7bc1aef21adbcb4e088a416373"}, + {file = "apsw-3.46.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42036093f8b7dd66bbb18b717ef6dfa62c4a2acd9bcdf05fdf5caedf77a47c01"}, + {file = "apsw-3.46.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4d54efc7d7d58b782dc84f29c5d25d190984dec20d8233484d3b092ded1241e1"}, + {file = "apsw-3.46.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3864151c23edd3a232e059925bd37044e2c1b90f20ba1d0b46005d0e5d97d10d"}, + {file = "apsw-3.46.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3e42ebb5997fcd6234cdb888f641ca37a7e9d03c13c4f2e1e0ac66151a182e79"}, + {file = "apsw-3.46.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7ea887719b60d48ac569eb42594f7dd772ab2b2287aaae9c9a007789467aa26a"}, + {file = "apsw-3.46.1.0-cp311-cp311-win32.whl", hash = "sha256:67754bc4c0b2dda1a112f0adfdd6d25c2f724d8c086decb9690349056f799eed"}, + {file = "apsw-3.46.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fef6891bc388d92ac8208db2e6f5cd90bd75a64930147f515f2e28526a278c81"}, + {file = "apsw-3.46.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a892c3dccbb2f96611a0707fb4cf1573c88a4a2898b45f013a202557f602faa8"}, + {file = "apsw-3.46.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e01e2cf7faae0d86540e9c638778c98cdd14b365136d9b11d2a0a7dfe4893f3"}, + {file = "apsw-3.46.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf96999557f5ccc5c8424b0c8637447652994e26b4fe87b72626def24c53dcf1"}, + {file = "apsw-3.46.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925c01733c0de8adf7f3cbf299e4bcb38961b62de4436f8704e5ff9800523a7c"}, + {file = "apsw-3.46.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:979f1fca9ec09c1e8bd466ad17fde25dffb06ea621bd8b7c08e404d042c4d362"}, + {file = "apsw-3.46.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e02c614ca3afceb6c80349485dd2d49fea584a885794ca732513d8aa746781d7"}, + {file = "apsw-3.46.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c9c130253eba2f70547253f54db05d0e6aa41962d9d712b9e1b8efba1ea2990b"}, + {file = "apsw-3.46.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:999f8fc2607a98ecfddb9d266bd746ae9a08dfa67841700ccfb0108a9cfe9104"}, + {file = "apsw-3.46.1.0-cp312-cp312-win32.whl", hash = "sha256:0f864580269c5cfe7aed899057a6e76f06940d2bc4134c2e32d36aadad0b3e29"}, + {file = "apsw-3.46.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:fb770bbe185d3cd6609bb245e22108490c81a025e3be82cd278116b5e21cbbee"}, + {file = "apsw-3.46.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8113139847f1ad7023a2b8ab8cee15ceec2406c9fbc6709c64a029947485bc23"}, + {file = "apsw-3.46.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:038e9550dc24413a12fde36492ab275410c35982e97d33cc5fd7c18325bbc9e1"}, + {file = "apsw-3.46.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1779f6d512d07b1fa914d268c42ac47170fd41aeae3352c3ce1c5c9f410496b9"}, + {file = "apsw-3.46.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b2497696ccb5ac928ba3bbae988a82e00d0be3242b7bdd0553ce4447bdcc73b"}, + {file = "apsw-3.46.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b182bafe729822f7a934d081d9190b76e0dae1f5f098efa7430fcdd38e3a315"}, + {file = "apsw-3.46.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d08cf0df8f58b4bdf8c0b7a4c8e70f2a8840be631f40dae848b384636a22fe0d"}, + {file = "apsw-3.46.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7d37e2f6e1a22bb1a82905237b4d433124ccc53a62f918b9cf7c42c6e49241d0"}, + {file = "apsw-3.46.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3d49e1996c13661011505cd53502e580c63062eafeebaebcd80ec34b435475c4"}, + {file = "apsw-3.46.1.0-cp313-cp313-win32.whl", hash = "sha256:42039f5d650ef1bb12e1304aebe47338c20bead38b41bae0f22f98e78cc6855c"}, + {file = "apsw-3.46.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c37abd9f344aefa11c3fe213738c1db4fe49bacef1aee360087fa1ac840b1c4"}, + {file = "apsw-3.46.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a8cd20bff7e1294d8b779153f2ff0fbd7821c4b479b31caef4b1427f3b443307"}, + {file = "apsw-3.46.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9b7e6395b8b20681a9b4a5f9621c9b1800e32a332cf75010bc8fde1d43465610"}, + {file = "apsw-3.46.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:348c88254bf05527909494a690d846cae5a95dd87e2359788b4ccb4d4a56c64a"}, + {file = "apsw-3.46.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d508bcbf81d0f8339572e8e9775cc45991d2548f19605a5445d8dc05f23910f4"}, + {file = "apsw-3.46.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7bf2ca987fcb136bdb23c241e0b18469a2c45255bee80d7884ff56bc6d5461"}, + {file = "apsw-3.46.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:81f7c3ca9267a290922ddef73293c86bc373afc128867412d6f844a4a271a381"}, + {file = "apsw-3.46.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:63278cee066c2365327d5d5976570834a559b9f64068186038af29b08063ba5a"}, + {file = "apsw-3.46.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f53f489ebb024464e9223de9d8a139a2e206d33de1ab0538a01962dfe40c6526"}, + {file = "apsw-3.46.1.0-cp38-cp38-win32.whl", hash = "sha256:fc60738ad5594f72eb611178f161869dc7ff02789468c963296c4da743415e55"}, + {file = "apsw-3.46.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:d4f48ef4f7d061b819cc35878ac661835e84debe17886abbefa7b0f935a24b85"}, + {file = "apsw-3.46.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:85552b0696342e601420e02beba02ef8b1544eeb92895d771d795c1e5e696285"}, + {file = "apsw-3.46.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b0b71f1f76200907782c6bd17b6b623b4ccc95f6d4187f0361c8f5c1a3e9fd81"}, + {file = "apsw-3.46.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:755f0cd2a3b70436e69b347ffb0774cca32db96ca7cf9b8660f29226d8eec2b1"}, + {file = "apsw-3.46.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c95adc014380489b37c97a70ab6ead31a1774d35f921e309407241a035d1485"}, + {file = "apsw-3.46.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:029f03385379882a6ce5df9713ebed86dde1cdf0435181431c264d1333719d13"}, + {file = "apsw-3.46.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fed308f151dab9ca3052ee9c35beedfb5fd788734b24514e6bedf58f6f86f5d"}, + {file = "apsw-3.46.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:66773bc9b0428a4178bb5dd0dbbca00104e184252832ec1bcd81712a29ef65ed"}, + {file = "apsw-3.46.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:55d248a9d55d39d366f532f4ae70bdf7f2b8269f5e75b71742e1bdf039853151"}, + {file = "apsw-3.46.1.0-cp39-cp39-win32.whl", hash = "sha256:4739482e35f5da3cc694959c43c813433b444ce865b60d5d78ba0734eb4a3840"}, + {file = "apsw-3.46.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:2bffff5cbfcd84ce7409d3ecb885b4707a264effbaa950f0ba5c68eaaca1ad5d"}, + {file = "apsw-3.46.1.0.tar.gz", hash = "sha256:96e3dfad1fd0cc77a778aa6b27468292041a8e9cb1f2dcf06bd773762c9b0c0c"}, ] [[package]] @@ -224,24 +238,24 @@ test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] [[package]] name = "astroid" -version = "3.2.4" +version = "3.3.3" description = "An abstract syntax tree for Python with inference support." optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" files = [ - {file = "astroid-3.2.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, - {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, + {file = "astroid-3.3.3-py3-none-any.whl", hash = "sha256:2d79acfd3c594b6a2d4141fea98a1d62ab4a52e54332b1f1ddcf07b652cc5c0f"}, + {file = "astroid-3.3.3.tar.gz", hash = "sha256:63f8c5370d9bad8294163c87b2d440a7fdf546be6c72bbeac0549c93244dbd72"}, ] [[package]] name = "attrs" -version = "24.1.0" +version = "24.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-24.1.0-py3-none-any.whl", hash = "sha256:377b47448cb61fea38533f671fba0d0f8a96fd58facd4dc518e3dac9dbea0905"}, - {file = "attrs-24.1.0.tar.gz", hash = "sha256:adbdec84af72d38be7628e353a09b6a6790d15cd71819f6e9d7b0faa8a125745"}, + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, ] [package.extras] @@ -254,13 +268,13 @@ tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "babel" -version = "2.15.0" +version = "2.16.0" description = "Internationalization utilities" optional = false python-versions = ">=3.8" files = [ - {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, - {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, + {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, + {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, ] [package.extras] @@ -433,89 +447,89 @@ test = ["flake8", "isort", "pytest"] [[package]] name = "certifi" -version = "2024.7.4" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, - {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] [[package]] name = "cffi" -version = "1.17.0" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, - {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, - {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, - {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, - {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, - {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, - {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, - {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, - {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, - {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, - {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, - {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, - {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, - {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, - {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, - {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] @@ -894,13 +908,13 @@ test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", [[package]] name = "griffe" -version = "1.1.1" +version = "1.3.1" description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." optional = false python-versions = ">=3.8" files = [ - {file = "griffe-1.1.1-py3-none-any.whl", hash = "sha256:0c469411e8d671a545725f5c0851a746da8bd99d354a79fdc4abd45219252efb"}, - {file = "griffe-1.1.1.tar.gz", hash = "sha256:faeb78764c0b2bd010719d6e015d07709b0f260258b5d4dd6c88343d9702aa30"}, + {file = "griffe-1.3.1-py3-none-any.whl", hash = "sha256:940aeb630bc3054b4369567f150b6365be6f11eef46b0ed8623aea96e6d17b19"}, + {file = "griffe-1.3.1.tar.gz", hash = "sha256:3f86a716b631a4c0f96a43cb75d05d3c85975003c20540426c0eba3b0581c56a"}, ] [package.dependencies] @@ -908,13 +922,13 @@ colorama = ">=0.4" [[package]] name = "idna" -version = "3.7" +version = "3.8" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, + {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, + {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, ] [[package]] @@ -961,13 +975,13 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "markdown" -version = "3.6" +version = "3.7" description = "Python implementation of John Gruber's Markdown." optional = false python-versions = ">=3.8" files = [ - {file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"}, - {file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"}, + {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"}, + {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"}, ] [package.extras] @@ -1147,13 +1161,13 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-imp [[package]] name = "mkdocs-autorefs" -version = "1.1.0" +version = "1.2.0" description = "Automatically link across pages in MkDocs." optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_autorefs-1.1.0-py3-none-any.whl", hash = "sha256:492ac42f50214e81565e968f8cb0df9aba9d981542b9e7121b8f8ae9407fe6eb"}, - {file = "mkdocs_autorefs-1.1.0.tar.gz", hash = "sha256:f2fd43b11f66284bd014f9b542a05c8ecbfaad4e0d7b30b68584788217b6c656"}, + {file = "mkdocs_autorefs-1.2.0-py3-none-any.whl", hash = "sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f"}, + {file = "mkdocs_autorefs-1.2.0.tar.gz", hash = "sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f"}, ] [package.dependencies] @@ -1441,64 +1455,68 @@ files = [ [[package]] name = "orjson" -version = "3.10.6" +version = "3.10.7" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" files = [ - {file = "orjson-3.10.6-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:fb0ee33124db6eaa517d00890fc1a55c3bfe1cf78ba4a8899d71a06f2d6ff5c7"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c1c4b53b24a4c06547ce43e5fee6ec4e0d8fe2d597f4647fc033fd205707365"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eadc8fd310edb4bdbd333374f2c8fec6794bbbae99b592f448d8214a5e4050c0"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61272a5aec2b2661f4fa2b37c907ce9701e821b2c1285d5c3ab0207ebd358d38"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57985ee7e91d6214c837936dc1608f40f330a6b88bb13f5a57ce5257807da143"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:633a3b31d9d7c9f02d49c4ab4d0a86065c4a6f6adc297d63d272e043472acab5"}, - {file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1c680b269d33ec444afe2bdc647c9eb73166fa47a16d9a75ee56a374f4a45f43"}, - {file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f759503a97a6ace19e55461395ab0d618b5a117e8d0fbb20e70cfd68a47327f2"}, - {file = "orjson-3.10.6-cp310-none-win32.whl", hash = "sha256:95a0cce17f969fb5391762e5719575217bd10ac5a189d1979442ee54456393f3"}, - {file = "orjson-3.10.6-cp310-none-win_amd64.whl", hash = "sha256:df25d9271270ba2133cc88ee83c318372bdc0f2cd6f32e7a450809a111efc45c"}, - {file = "orjson-3.10.6-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b1ec490e10d2a77c345def52599311849fc063ae0e67cf4f84528073152bb2ba"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d43d3feb8f19d07e9f01e5b9be4f28801cf7c60d0fa0d279951b18fae1932b"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3045267e98fe749408eee1593a142e02357c5c99be0802185ef2170086a863"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c27bc6a28ae95923350ab382c57113abd38f3928af3c80be6f2ba7eb8d8db0b0"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d27456491ca79532d11e507cadca37fb8c9324a3976294f68fb1eff2dc6ced5a"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05ac3d3916023745aa3b3b388e91b9166be1ca02b7c7e41045da6d12985685f0"}, - {file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1335d4ef59ab85cab66fe73fd7a4e881c298ee7f63ede918b7faa1b27cbe5212"}, - {file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4bbc6d0af24c1575edc79994c20e1b29e6fb3c6a570371306db0993ecf144dc5"}, - {file = "orjson-3.10.6-cp311-none-win32.whl", hash = "sha256:450e39ab1f7694465060a0550b3f6d328d20297bf2e06aa947b97c21e5241fbd"}, - {file = "orjson-3.10.6-cp311-none-win_amd64.whl", hash = "sha256:227df19441372610b20e05bdb906e1742ec2ad7a66ac8350dcfd29a63014a83b"}, - {file = "orjson-3.10.6-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ea2977b21f8d5d9b758bb3f344a75e55ca78e3ff85595d248eee813ae23ecdfb"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6f3d167d13a16ed263b52dbfedff52c962bfd3d270b46b7518365bcc2121eed"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f710f346e4c44a4e8bdf23daa974faede58f83334289df80bc9cd12fe82573c7"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7275664f84e027dcb1ad5200b8b18373e9c669b2a9ec33d410c40f5ccf4b257e"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0943e4c701196b23c240b3d10ed8ecd674f03089198cf503105b474a4f77f21f"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:446dee5a491b5bc7d8f825d80d9637e7af43f86a331207b9c9610e2f93fee22a"}, - {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:64c81456d2a050d380786413786b057983892db105516639cb5d3ee3c7fd5148"}, - {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:960db0e31c4e52fa0fc3ecbaea5b2d3b58f379e32a95ae6b0ebeaa25b93dfd34"}, - {file = "orjson-3.10.6-cp312-none-win32.whl", hash = "sha256:a6ea7afb5b30b2317e0bee03c8d34c8181bc5a36f2afd4d0952f378972c4efd5"}, - {file = "orjson-3.10.6-cp312-none-win_amd64.whl", hash = "sha256:874ce88264b7e655dde4aeaacdc8fd772a7962faadfb41abe63e2a4861abc3dc"}, - {file = "orjson-3.10.6-cp313-none-win32.whl", hash = "sha256:efdf2c5cde290ae6b83095f03119bdc00303d7a03b42b16c54517baa3c4ca3d0"}, - {file = "orjson-3.10.6-cp313-none-win_amd64.whl", hash = "sha256:8e190fe7888e2e4392f52cafb9626113ba135ef53aacc65cd13109eb9746c43e"}, - {file = "orjson-3.10.6-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:66680eae4c4e7fc193d91cfc1353ad6d01b4801ae9b5314f17e11ba55e934183"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caff75b425db5ef8e8f23af93c80f072f97b4fb3afd4af44482905c9f588da28"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3722fddb821b6036fd2a3c814f6bd9b57a89dc6337b9924ecd614ebce3271394"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2c116072a8533f2fec435fde4d134610f806bdac20188c7bd2081f3e9e0133f"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6eeb13218c8cf34c61912e9df2de2853f1d009de0e46ea09ccdf3d757896af0a"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:965a916373382674e323c957d560b953d81d7a8603fbeee26f7b8248638bd48b"}, - {file = "orjson-3.10.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:03c95484d53ed8e479cade8628c9cea00fd9d67f5554764a1110e0d5aa2de96e"}, - {file = "orjson-3.10.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e060748a04cccf1e0a6f2358dffea9c080b849a4a68c28b1b907f272b5127e9b"}, - {file = "orjson-3.10.6-cp38-none-win32.whl", hash = "sha256:738dbe3ef909c4b019d69afc19caf6b5ed0e2f1c786b5d6215fbb7539246e4c6"}, - {file = "orjson-3.10.6-cp38-none-win_amd64.whl", hash = "sha256:d40f839dddf6a7d77114fe6b8a70218556408c71d4d6e29413bb5f150a692ff7"}, - {file = "orjson-3.10.6-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:697a35a083c4f834807a6232b3e62c8b280f7a44ad0b759fd4dce748951e70db"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd502f96bf5ea9a61cbc0b2b5900d0dd68aa0da197179042bdd2be67e51a1e4b"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f215789fb1667cdc874c1b8af6a84dc939fd802bf293a8334fce185c79cd359b"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2debd8ddce948a8c0938c8c93ade191d2f4ba4649a54302a7da905a81f00b56"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5410111d7b6681d4b0d65e0f58a13be588d01b473822483f77f513c7f93bd3b2"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb1f28a137337fdc18384079fa5726810681055b32b92253fa15ae5656e1dddb"}, - {file = "orjson-3.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bf2fbbce5fe7cd1aa177ea3eab2b8e6a6bc6e8592e4279ed3db2d62e57c0e1b2"}, - {file = "orjson-3.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:79b9b9e33bd4c517445a62b90ca0cc279b0f1f3970655c3df9e608bc3f91741a"}, - {file = "orjson-3.10.6-cp39-none-win32.whl", hash = "sha256:30b0a09a2014e621b1adf66a4f705f0809358350a757508ee80209b2d8dae219"}, - {file = "orjson-3.10.6-cp39-none-win_amd64.whl", hash = "sha256:49e3bc615652617d463069f91b867a4458114c5b104e13b7ae6872e5f79d0844"}, - {file = "orjson-3.10.6.tar.gz", hash = "sha256:e54b63d0a7c6c54a5f5f726bc93a2078111ef060fec4ecbf34c5db800ca3b3a7"}, + {file = "orjson-3.10.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:74f4544f5a6405b90da8ea724d15ac9c36da4d72a738c64685003337401f5c12"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34a566f22c28222b08875b18b0dfbf8a947e69df21a9ed5c51a6bf91cfb944ac"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf6ba8ebc8ef5792e2337fb0419f8009729335bb400ece005606336b7fd7bab7"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac7cf6222b29fbda9e3a472b41e6a5538b48f2c8f99261eecd60aafbdb60690c"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de817e2f5fc75a9e7dd350c4b0f54617b280e26d1631811a43e7e968fa71e3e9"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:348bdd16b32556cf8d7257b17cf2bdb7ab7976af4af41ebe79f9796c218f7e91"}, + {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:479fd0844ddc3ca77e0fd99644c7fe2de8e8be1efcd57705b5c92e5186e8a250"}, + {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fdf5197a21dd660cf19dfd2a3ce79574588f8f5e2dbf21bda9ee2d2b46924d84"}, + {file = "orjson-3.10.7-cp310-none-win32.whl", hash = "sha256:d374d36726746c81a49f3ff8daa2898dccab6596864ebe43d50733275c629175"}, + {file = "orjson-3.10.7-cp310-none-win_amd64.whl", hash = "sha256:cb61938aec8b0ffb6eef484d480188a1777e67b05d58e41b435c74b9d84e0b9c"}, + {file = "orjson-3.10.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7db8539039698ddfb9a524b4dd19508256107568cdad24f3682d5773e60504a2"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:480f455222cb7a1dea35c57a67578848537d2602b46c464472c995297117fa09"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a9c9b168b3a19e37fe2778c0003359f07822c90fdff8f98d9d2a91b3144d8e0"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8de062de550f63185e4c1c54151bdddfc5625e37daf0aa1e75d2a1293e3b7d9a"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6b0dd04483499d1de9c8f6203f8975caf17a6000b9c0c54630cef02e44ee624e"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b58d3795dafa334fc8fd46f7c5dc013e6ad06fd5b9a4cc98cb1456e7d3558bd6"}, + {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33cfb96c24034a878d83d1a9415799a73dc77480e6c40417e5dda0710d559ee6"}, + {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e724cebe1fadc2b23c6f7415bad5ee6239e00a69f30ee423f319c6af70e2a5c0"}, + {file = "orjson-3.10.7-cp311-none-win32.whl", hash = "sha256:82763b46053727a7168d29c772ed5c870fdae2f61aa8a25994c7984a19b1021f"}, + {file = "orjson-3.10.7-cp311-none-win_amd64.whl", hash = "sha256:eb8d384a24778abf29afb8e41d68fdd9a156cf6e5390c04cc07bbc24b89e98b5"}, + {file = "orjson-3.10.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44a96f2d4c3af51bfac6bc4ef7b182aa33f2f054fd7f34cc0ee9a320d051d41f"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ac14cd57df0572453543f8f2575e2d01ae9e790c21f57627803f5e79b0d3c3"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bdbb61dcc365dd9be94e8f7df91975edc9364d6a78c8f7adb69c1cdff318ec93"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b48b3db6bb6e0a08fa8c83b47bc169623f801e5cc4f24442ab2b6617da3b5313"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23820a1563a1d386414fef15c249040042b8e5d07b40ab3fe3efbfbbcbcb8864"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0c6a008e91d10a2564edbb6ee5069a9e66df3fbe11c9a005cb411f441fd2c09"}, + {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d352ee8ac1926d6193f602cbe36b1643bbd1bbcb25e3c1a657a4390f3000c9a5"}, + {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d2d9f990623f15c0ae7ac608103c33dfe1486d2ed974ac3f40b693bad1a22a7b"}, + {file = "orjson-3.10.7-cp312-none-win32.whl", hash = "sha256:7c4c17f8157bd520cdb7195f75ddbd31671997cbe10aee559c2d613592e7d7eb"}, + {file = "orjson-3.10.7-cp312-none-win_amd64.whl", hash = "sha256:1d9c0e733e02ada3ed6098a10a8ee0052dd55774de3d9110d29868d24b17faa1"}, + {file = "orjson-3.10.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:77d325ed866876c0fa6492598ec01fe30e803272a6e8b10e992288b009cbe149"}, + {file = "orjson-3.10.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ea2c232deedcb605e853ae1db2cc94f7390ac776743b699b50b071b02bea6fe"}, + {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3dcfbede6737fdbef3ce9c37af3fb6142e8e1ebc10336daa05872bfb1d87839c"}, + {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11748c135f281203f4ee695b7f80bb1358a82a63905f9f0b794769483ea854ad"}, + {file = "orjson-3.10.7-cp313-none-win32.whl", hash = "sha256:a7e19150d215c7a13f39eb787d84db274298d3f83d85463e61d277bbd7f401d2"}, + {file = "orjson-3.10.7-cp313-none-win_amd64.whl", hash = "sha256:eef44224729e9525d5261cc8d28d6b11cafc90e6bd0be2157bde69a52ec83024"}, + {file = "orjson-3.10.7-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6ea2b2258eff652c82652d5e0f02bd5e0463a6a52abb78e49ac288827aaa1469"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:430ee4d85841e1483d487e7b81401785a5dfd69db5de01314538f31f8fbf7ee1"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4b6146e439af4c2472c56f8540d799a67a81226e11992008cb47e1267a9b3225"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:084e537806b458911137f76097e53ce7bf5806dda33ddf6aaa66a028f8d43a23"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4829cf2195838e3f93b70fd3b4292156fc5e097aac3739859ac0dcc722b27ac0"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1193b2416cbad1a769f868b1749535d5da47626ac29445803dae7cc64b3f5c98"}, + {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4e6c3da13e5a57e4b3dca2de059f243ebec705857522f188f0180ae88badd354"}, + {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c31008598424dfbe52ce8c5b47e0752dca918a4fdc4a2a32004efd9fab41d866"}, + {file = "orjson-3.10.7-cp38-none-win32.whl", hash = "sha256:7122a99831f9e7fe977dc45784d3b2edc821c172d545e6420c375e5a935f5a1c"}, + {file = "orjson-3.10.7-cp38-none-win_amd64.whl", hash = "sha256:a763bc0e58504cc803739e7df040685816145a6f3c8a589787084b54ebc9f16e"}, + {file = "orjson-3.10.7-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e76be12658a6fa376fcd331b1ea4e58f5a06fd0220653450f0d415b8fd0fbe20"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed350d6978d28b92939bfeb1a0570c523f6170efc3f0a0ef1f1df287cd4f4960"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:144888c76f8520e39bfa121b31fd637e18d4cc2f115727865fdf9fa325b10412"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09b2d92fd95ad2402188cf51573acde57eb269eddabaa60f69ea0d733e789fe9"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b24a579123fa884f3a3caadaed7b75eb5715ee2b17ab5c66ac97d29b18fe57f"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591bcfe7512353bd609875ab38050efe3d55e18934e2f18950c108334b4ff"}, + {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f4db56635b58cd1a200b0a23744ff44206ee6aa428185e2b6c4a65b3197abdcd"}, + {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0fa5886854673222618638c6df7718ea7fe2f3f2384c452c9ccedc70b4a510a5"}, + {file = "orjson-3.10.7-cp39-none-win32.whl", hash = "sha256:8272527d08450ab16eb405f47e0f4ef0e5ff5981c3d82afe0efd25dcbef2bcd2"}, + {file = "orjson-3.10.7-cp39-none-win_amd64.whl", hash = "sha256:974683d4618c0c7dbf4f69c95a979734bf183d0658611760017f6e70a145af58"}, + {file = "orjson-3.10.7.tar.gz", hash = "sha256:75ef0640403f945f3a1f9f6400686560dbfb0fb5b16589ad62cd477043c4eee3"}, ] [[package]] @@ -1514,14 +1532,19 @@ files = [ [[package]] name = "paginate" -version = "0.5.6" +version = "0.5.7" description = "Divides large result sets into pages for easier browsing" optional = false python-versions = "*" files = [ - {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"}, + {file = "paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591"}, + {file = "paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945"}, ] +[package.extras] +dev = ["pytest", "tox"] +lint = ["black"] + [[package]] name = "pathspec" version = "0.12.1" @@ -1545,20 +1568,15 @@ files = [ [[package]] name = "phx-class-registry" -version = "4.1.0" +version = "5.0.0" description = "Factory+Registry pattern for Python classes" optional = false -python-versions = ">=3.10" +python-versions = "<4.0,>=3.10" files = [ - {file = "phx-class-registry-4.1.0.tar.gz", hash = "sha256:6a7fe8568f9000ad1f90c9a81c5cb65ec20ee3b89b2aaab7a67e14dbb67e11d1"}, - {file = "phx_class_registry-4.1.0-py3-none-any.whl", hash = "sha256:1cad15897473d5bcd2ed7640423e68b7fa20745e4e25c0457f5474afa50bc8bb"}, + {file = "phx_class_registry-5.0.0-py3-none-any.whl", hash = "sha256:6e0644f779c7d793a96090d938fe4c396f3274dd57563dc1c57ea245b5c07f89"}, + {file = "phx_class_registry-5.0.0.tar.gz", hash = "sha256:a57ab8c2eca03e0daf06e0dd840ea26b72e2e51b7b7509015b3df7c0d537ee73"}, ] -[package.extras] -build-system = ["build", "twine"] -docs-builder = ["sphinx", "sphinx-rtd-theme"] -test-runner = ["tox"] - [[package]] name = "pillow" version = "10.4.0" @@ -1658,13 +1676,13 @@ xmp = ["defusedxml"] [[package]] name = "pipx" -version = "1.6.0" +version = "1.7.1" description = "Install and Run Python Applications in Isolated Environments" optional = false python-versions = ">=3.8" files = [ - {file = "pipx-1.6.0-py3-none-any.whl", hash = "sha256:760889dc3aeed7bf4024973bf22ca0c2a891003f52389159ab5cb0c57d9ebff4"}, - {file = "pipx-1.6.0.tar.gz", hash = "sha256:840610e00103e3d49ae24b6b51804b60988851a5dd65468adb71e5a97e2699b2"}, + {file = "pipx-1.7.1-py3-none-any.whl", hash = "sha256:3933c43bb344e649cb28e10d357e0967ce8572f1c19caf90cf39ae95c2a0afaf"}, + {file = "pipx-1.7.1.tar.gz", hash = "sha256:762de134e16a462be92645166d225ecef446afaef534917f5f70008d63584360"}, ] [package.dependencies] @@ -1746,119 +1764,120 @@ files = [ [[package]] name = "pydantic" -version = "2.8.2" +version = "2.9.2" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, - {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, + {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"}, + {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"}, ] [package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.20.1" +annotated-types = ">=0.6.0" +pydantic-core = "2.23.4" typing-extensions = {version = ">=4.6.1", markers = "python_version < \"3.13\""} [package.extras] email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.20.1" +version = "2.23.4" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, - {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, - {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, - {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, - {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, - {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, - {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, - {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, - {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, - {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, - {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, - {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, - {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, - {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, + {file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"}, + {file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"}, + {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"}, + {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"}, + {file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"}, + {file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"}, + {file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"}, + {file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"}, + {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"}, + {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"}, + {file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"}, + {file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"}, + {file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"}, + {file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"}, + {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"}, + {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"}, + {file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"}, + {file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"}, + {file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"}, + {file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"}, + {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"}, + {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"}, + {file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"}, + {file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"}, + {file = "pydantic_core-2.23.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555"}, + {file = "pydantic_core-2.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12"}, + {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2"}, + {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb"}, + {file = "pydantic_core-2.23.4-cp38-none-win32.whl", hash = "sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6"}, + {file = "pydantic_core-2.23.4-cp38-none-win_amd64.whl", hash = "sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556"}, + {file = "pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a"}, + {file = "pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55"}, + {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040"}, + {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605"}, + {file = "pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6"}, + {file = "pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e"}, + {file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"}, ] [package.dependencies] @@ -1880,17 +1899,17 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" -version = "3.2.6" +version = "3.3.0" description = "python code static checker" optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" files = [ - {file = "pylint-3.2.6-py3-none-any.whl", hash = "sha256:03c8e3baa1d9fb995b12c1dbe00aa6c4bcef210c2a2634374aedeb22fb4a8f8f"}, - {file = "pylint-3.2.6.tar.gz", hash = "sha256:a5d01678349454806cff6d886fb072294f56a58c4761278c97fb557d708e1eb3"}, + {file = "pylint-3.3.0-py3-none-any.whl", hash = "sha256:02dce1845f68974b9b03045894eb3bf05a8b3c7da9fd10af4de3c91e69eb92f1"}, + {file = "pylint-3.3.0.tar.gz", hash = "sha256:c685fe3c061ee5fb0ce7c29436174ab84a2f525fce2a268b1986e921e083fe22"}, ] [package.dependencies] -astroid = ">=3.2.4,<=3.3.0-dev0" +astroid = ">=3.3.3,<=3.4.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = {version = ">=0.3.6", markers = "python_version >= \"3.11\""} isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" @@ -1936,73 +1955,75 @@ six = ">=1.5" [[package]] name = "pytz" -version = "2024.1" +version = "2024.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, - {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, + {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, + {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, ] [[package]] name = "pyyaml" -version = "6.0.1" +version = "6.0.2" description = "YAML parser and emitter for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] @@ -2021,104 +2042,119 @@ pyyaml = "*" [[package]] name = "rapidfuzz" -version = "3.9.5" +version = "3.9.6" description = "rapid fuzzy string matching" optional = false python-versions = ">=3.8" files = [ - {file = "rapidfuzz-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7659058863d84a2c36c5a76c28bc8713d33eab03e677e67260d9e1cca43fc3bb"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:802a018776bd3cb7c5d23ba38ebbb1663a9f742be1d58e73b62d8c7cace6e607"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da71e8fdb0d1a21f4b58b2c84bcbc2b89a472c073c5f7bdb9339f4cb3122c0e3"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9433cb12731167b358fbcff9828d2294429986a03222031f6d14308eb643c77"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e33e1d185206730b916b3e7d9bce1941c65b2a1488cdd0457ae21be385a7912"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:758719e9613c47a274768f1926460955223fe0a03e7eda264f2b78b1b97a4743"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7981cc6240d01d4480795d758ea2ee748257771f68127d630045e58fe1b5545a"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b6cdca86120c3f9aa069f8d4e1c5422e92f833d705d719a2ba7082412f4c933b"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ffa533acb1a9dcb6e26c4467fdc1347995fb168ec9f794b97545f6b72dee733c"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:13eeaeb0d5fe00fa99336f73fb5ab65c46109c7121cf87659b9601908b8b6178"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:d7b1922b1403ccb3583218e8cd931b08e04c5442ca03dbaf6ea4fcf574ee2b24"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b0189f691cea4dc9fe074ea6b97da30a91d0882fa69724b4b34b51d2c1983473"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-win32.whl", hash = "sha256:72e466e5de12a327a09ed6d0116f024759b5146b335645c32241da84134a7f34"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:345011cfcafaa3674c46673baad67d2394eb58285530d8333e65c3c9a143b4f4"}, - {file = "rapidfuzz-3.9.5-cp310-cp310-win_arm64.whl", hash = "sha256:5dc19c8222475e4f7f528b94d2fa28e7979355c5cf7c6e73902d2abb2be96522"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6c741972d64031535cfd76d89cf47259e590e822353be57ec2f5d56758c98296"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7452d079800cf70a7314f73044f03cbcbd90a651d9dec39443d2a8a2b63ab53"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f06f163a0341bad162e972590b73e17f9cea2ed8ee27b193875ccbc3dd6eca2f"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:529e2cf441746bd492f6c36a38bf9fa6a418df95b9c003f8e92a55d8a979bd9c"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9811a741aa1350ad36689d675ded8b34e423e68b396bd30bff751a9c582f586e"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e36c4640a789b8c922b69a548968939d1c0433fa7aac83cb08e1334d4e5d7de"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53fb2f32f14c921d2f673c5b7cd58d4cc626c574a28c0791f283880d8e57022c"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:031806eb035a6f09f4ff23b9d971d50b30b5e93aa3ee620c920bee1dc32827e7"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f6dbe1df0b9334e3cf07445d810c81734ae23d137b5efc69e1d676ff55691351"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:24345826b50aafcea26e2e4be5c103d96fe9d7fc549ac9190641300290958f3b"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bfd3b66ee1f0ebb40c672a7a7e5bda00fb763fa9bca082058084175151f8e685"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a6f1df5b0e602e94199cccb5e241bbc2319644003e34f077741ebf48aea7ed1a"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-win32.whl", hash = "sha256:f080d6709f51a8335e73826b96af9b4e3657631eca6c69e1ac501868dcc84b7f"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:bf9ed6988da6a2c1f8df367cb5d6be26a3d8543646c8eba79741ac9e764fbc59"}, - {file = "rapidfuzz-3.9.5-cp311-cp311-win_arm64.whl", hash = "sha256:599714790dfac0a23a473134e6677d0a103690a4e21ba189cfc826e322cdc8d5"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9729852038fb2de096e249899f8a9bee90fb1f92e10b6ccc539d5bb798c703bc"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9dc39435476fb3b3b3c24ab2c08c726056b2b487aa7ee450aee698b808c808ac"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6ceea632b0eb97dac54411c29feb190054e91fd0571f585b56e4a9159c55ab0"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cadd66e6ef9901909dc1b11db91048f1bf4613ba7d773386f922e28b1e1df4da"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63e34fb3586431589a5e1cd7fc61c6f057576c6c6804c1c673bac3de0516dee7"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:181073256faec68e6b8ab3329a36cfa1360f7906aa70d9aee4a39cb70889f73f"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8419c18bbbd67058ca1312f35acda2e4e4592650f105cfd166569a2ebccd01f1"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:191d1057cca56641f7b919fe712cb7e48cd226342e097a78136127f8bde32caa"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fe5a11eefd0ae90d32d9ff706a894498b4efb4b0c263ad9d1e6401050863504d"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e1b024d9d69bb83e125adee4162991f2764f16acc3fb1ed0f0fc1ad5aeb7e394"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7d5a34b8388ae99bdbd5a3646f45ac318f4c870105bdbe42a2f4c85e5b347761"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0e09abc0d397019bba61c8e6dfe2ec863d4dfb1762f51c9197ce0af5d5fd9adb"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-win32.whl", hash = "sha256:e3c4be3057472c79ba6f4eab35daa9f12908cb697c472d05fbbd47949a87aec6"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:0d9fdb74df87018dd4146f3d00df9fca2c27f060936a9e8d3015e7bfb9cb69e4"}, - {file = "rapidfuzz-3.9.5-cp312-cp312-win_arm64.whl", hash = "sha256:491d3d425b5fe3f61f3b9a70abfd498ce9139d94956db7a8551e537e017c0e57"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:518dec750a30f115ba1299ef2547cf468a69f310581a030c8a875257de747c5f"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:252dc3d1c3d613b8db1b59d13381937e420c99f8a351ffa0e78c2f54746e107f"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd17688b75b6fa983e8586cad30f36eb9736b860946cc8b633b9442c9481831"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8032492021b0aa55a623d6f6e739a5d4aaabc32af379c2a5656bf1e9e178bf1"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73362eb1c3d02f32e4c7f0d77eb284e9a13f278cff224f71e8f60e2aff5b6a5d"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a42d1f7b8988f50013e703ed27b5e216ef8a725b2f4ac53754ad0476020b26f4"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4f2e985172bb76c9179e11fb67d9c9ecbee4933740eca2977797094df02498d"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8e943c5cbd10e15369be1f371ef303cb413c1008f64d93bd13762ea06ca84d59"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:0d34b0e8e29f80cb2ac8afe8fb7b01a542b136ffbf7e2b9983d11bce49398f68"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:62b8f9f58e9dffaa86fef84db2705457a58e191a962124f2b815026ba79d9aba"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:ebf682bdb0f01b6b1f9a9ffe918aa3ac84fbdadb998ffbfcd5f9b12bd280170f"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3ed0c17e5b6fdd2ac3230bdefa908579971377c36aa4a2f132700fa8145040db"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-win32.whl", hash = "sha256:ac460d89b9759e37eef23fed05184179654882a241f6b2363df194f8940cc55f"}, - {file = "rapidfuzz-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:cf9aceb4227fd09f9a20e505f78487b2089d6420ce232d288522ea0a78b986b9"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:14587df847d0d50bd10cde0a198b5d64eedb7484c72b825f5c2ead6e6ff16eee"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fd94d952299ec73ea63a0fa4b699a2750785b6bb82aa56fd886d9023b86f90ab"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:733bf3d7876bf6d8167e6436f99d6ea16a218ec2c8eb9da6048f20b9cc8733e2"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb28f2b7173ed3678b4630b0c8b21503087d1cd082bae200dc2519ca38b26686"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80a4c8a2c5ae4b133fec6b5db1af9a4126ffa6eca18a558fe5b6ab8e330d3d78"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5feb75e905281e5c669e21c98d594acc3b222a8694d9342f17df988766d83748"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d047b01637a31d9bf776b66438f574fd1db856ad14cf296c1f48bb6bef8a5aff"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d9e0a656274ac75ec24499a06c0bc5eee67bcd8276c6061da7c05d549f1b1a61"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:16c982dd3cdd33cf4aac91027a263a081d1a8050dc33a27470367a391a8d1576"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:9a0c878d0980508e90e973a9cbfb591acc370085f2301c6aacadbd8362d52a36"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:1d9bcfec5efd55b6268328cccd12956d833582d8da6385231a5c6c6201a1156a"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8171fc6e4645e636161a9ef5b44b20605adbefe23cd990b68d72cae0b9c12509"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-win32.whl", hash = "sha256:35088e759b083398ab3c4154517476e116653b7403604677af9a894179f1042f"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:6d8cc7e6e5c6fbcacdfe3cf7a86b60dcaf216216d86e6879ff52d488e5b11e27"}, - {file = "rapidfuzz-3.9.5-cp39-cp39-win_arm64.whl", hash = "sha256:506547889f18db0acca787ffb9f287757cbfe9f0fadddd4e07c64ce0bd924e13"}, - {file = "rapidfuzz-3.9.5-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f4e0122603af2119579e9f94e172c6e460860fdcdb713164332c1951c13df999"}, - {file = "rapidfuzz-3.9.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:e46cd486289d1d8e3dab779c725f5dde77b286185d32e7b874bfc3d161e3a927"}, - {file = "rapidfuzz-3.9.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e2c0c8bbe4f4525009e3ad9b94a39cdff5d6378233e754d0b13c29cdfaa75fc"}, - {file = "rapidfuzz-3.9.5-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfb47513a17c935f6ee606dcae0ea9d20a3fb0fe9ca597758472ea08be62dc54"}, - {file = "rapidfuzz-3.9.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:976ed1105a76935b6a4d2bbc7d577be1b97b43997bcec2f29a0ab48ff6f5d6b1"}, - {file = "rapidfuzz-3.9.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9cf2028edb9ccd21d1d5aaacef2fe3e14bee4343df1c2c0f7373ef6e81013bef"}, - {file = "rapidfuzz-3.9.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:926701c8e61319ee2e4888619143f58ddcc0e3e886668269b8e053f2d68c1e92"}, - {file = "rapidfuzz-3.9.5-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:99eaa8dd8a44664813e0bef014775993ef75a134a863bc54cd855a60622203fd"}, - {file = "rapidfuzz-3.9.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7508ef727ef4891141dd3ac7a39a2327384ece070521ac9c58f06c27d57c72d5"}, - {file = "rapidfuzz-3.9.5-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f33d05db5bba1d076446c51347a6d93ff24d8f9d01b0b8b15ca8ec8b1ef382"}, - {file = "rapidfuzz-3.9.5-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7252666b85c931d51a59d5308bb6827a67434917ef510747d3ce7e88ec17e7f2"}, - {file = "rapidfuzz-3.9.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d26f7299e2872d18fb7df1bc043e53aa94fc5a4a2a6a9537ad8707579fcb1668"}, - {file = "rapidfuzz-3.9.5-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2b17ecc17322b659962234799e90054e420911b8ca510a7869c2f4419f9f3ecb"}, - {file = "rapidfuzz-3.9.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f3e037b9ec621dec0157d81566e7d47a91405e379335cf8f4ed3c20d61db91d8"}, - {file = "rapidfuzz-3.9.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42c4d1ba2647c8d2a82313c4dde332de750c936b94f016308339e762c2e5e53d"}, - {file = "rapidfuzz-3.9.5-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:876e663b11d9067e1096ea76a2de87227c7b513aff2b60667b20417da74183e4"}, - {file = "rapidfuzz-3.9.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adee55488490375c1604b878fbc1eb1a51fe5e6f5bd05047df2f8c6505a48728"}, - {file = "rapidfuzz-3.9.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:abb1ac683671000bd4ec215a494aba687d75a198db72188408154a19ea313ff4"}, - {file = "rapidfuzz-3.9.5.tar.gz", hash = "sha256:257f2406a671371bafd99a2a2c57f991783446bc2176b93a83d1d833e35d36df"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7ed0d0b9c85720f0ae33ac5efc8dc3f60c1489dad5c29d735fbdf2f66f0431f"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f3deff6ab7017ed21b9aec5874a07ad13e6b2a688af055837f88b743c7bfd947"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3f9fc060160507b2704f7d1491bd58453d69689b580cbc85289335b14fe8ca"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e86c2b3827fa6169ad6e7d4b790ce02a20acefb8b78d92fa4249589bbc7a2c"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f982e1aafb4bd8207a5e073b1efef9e68a984e91330e1bbf364f9ed157ed83f0"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9196a51d0ec5eaaaf5bca54a85b7b1e666fc944c332f68e6427503af9fb8c49e"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb5a514064e02585b1cc09da2fe406a6dc1a7e5f3e92dd4f27c53e5f1465ec81"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e3a4244f65dbc3580b1275480118c3763f9dc29fc3dd96610560cb5e140a4d4a"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f6ebb910a702e41641e1e1dada3843bc11ba9107a33c98daef6945a885a40a07"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:624fbe96115fb39addafa288d583b5493bc76dab1d34d0ebba9987d6871afdf9"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1c59f1c1507b7a557cf3c410c76e91f097460da7d97e51c985343798e9df7a3c"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f6f0256cb27b6a0fb2e1918477d1b56473cd04acfa245376a342e7c15806a396"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-win32.whl", hash = "sha256:24d473d00d23a30a85802b502b417a7f5126019c3beec91a6739fe7b95388b24"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-win_amd64.whl", hash = "sha256:248f6d2612e661e2b5f9a22bbd5862a1600e720da7bb6ad8a55bb1548cdfa423"}, + {file = "rapidfuzz-3.9.6-cp310-cp310-win_arm64.whl", hash = "sha256:e03fdf0e74f346ed7e798135df5f2a0fb8d6b96582b00ebef202dcf2171e1d1d"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:52e4675f642fbc85632f691b67115a243cd4d2a47bdcc4a3d9a79e784518ff97"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1f93a2f13038700bd245b927c46a2017db3dcd4d4ff94687d74b5123689b873b"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b70500bca460264b8141d8040caee22e9cf0418c5388104ff0c73fb69ee28f"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1e037fb89f714a220f68f902fc6300ab7a33349f3ce8ffae668c3b3a40b0b06"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6792f66d59b86ccfad5e247f2912e255c85c575789acdbad8e7f561412ffed8a"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68d9cffe710b67f1969cf996983608cee4490521d96ea91d16bd7ea5dc80ea98"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63daaeeea76da17fa0bbe7fb05cba8ed8064bb1a0edf8360636557f8b6511961"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d214e063bffa13e3b771520b74f674b22d309b5720d4df9918ff3e0c0f037720"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ed443a2062460f44c0346cb9d269b586496b808c2419bbd6057f54061c9b9c75"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:5b0c9b227ee0076fb2d58301c505bb837a290ae99ee628beacdb719f0626d749"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:82c9722b7dfaa71e8b61f8c89fed0482567fb69178e139fe4151fc71ed7df782"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c18897c95c0a288347e29537b63608a8f63a5c3cb6da258ac46fcf89155e723e"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-win32.whl", hash = "sha256:3e910cf08944da381159587709daaad9e59d8ff7bca1f788d15928f3c3d49c2a"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-win_amd64.whl", hash = "sha256:59c4a61fab676d37329fc3a671618a461bfeef53a4d0b8b12e3bc24a14e166f8"}, + {file = "rapidfuzz-3.9.6-cp311-cp311-win_arm64.whl", hash = "sha256:8b4afea244102332973377fddbe54ce844d0916e1c67a5123432291717f32ffa"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:70591b28b218fff351b88cdd7f2359a01a71f9f7f5a2e465ce3715ed4b3c422b"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee2d8355c7343c631a03e57540ea06e8717c19ecf5ff64ea07e0498f7f161457"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:708fb675de0f47b9635d1cc6fbbf80d52cb710d0a1abbfae5c84c46e3abbddc3"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d66c247c2d3bb7a9b60567c395a15a929d0ebcc5f4ceedb55bfa202c38c6e0c"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15146301b32e6e3d2b7e8146db1a26747919d8b13690c7f83a4cb5dc111b3a08"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7a03da59b6c7c97e657dd5cd4bcaab5fe4a2affd8193958d6f4d938bee36679"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d2c2fe19e392dbc22695b6c3b2510527e2b774647e79936bbde49db7742d6f1"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:91aaee4c94cb45930684f583ffc4e7c01a52b46610971cede33586cf8a04a12e"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3f5702828c10768f9281180a7ff8597da1e5002803e1304e9519dd0f06d79a85"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ccd1763b608fb4629a0b08f00b3c099d6395e67c14e619f6341b2c8429c2f310"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc7a0d4b2cb166bc46d02c8c9f7551cde8e2f3c9789df3827309433ee9771163"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7496f53d40560a58964207b52586783633f371683834a8f719d6d965d223a2eb"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-win32.whl", hash = "sha256:5eb1a9272ca71bc72be5415c2fa8448a6302ea4578e181bb7da9db855b367df0"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-win_amd64.whl", hash = "sha256:0d21fc3c0ca507a1180152a6dbd129ebaef48facde3f943db5c1055b6e6be56a"}, + {file = "rapidfuzz-3.9.6-cp312-cp312-win_arm64.whl", hash = "sha256:43bb27a57c29dc5fa754496ba6a1a508480d21ae99ac0d19597646c16407e9f3"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:83a5ac6547a9d6eedaa212975cb8f2ce2aa07e6e30833b40e54a52b9f9999aa4"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:10f06139142ecde67078ebc9a745965446132b998f9feebffd71acdf218acfcc"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74720c3f24597f76c7c3e2c4abdff55f1664f4766ff5b28aeaa689f8ffba5fab"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2bce52b5c150878e558a0418c2b637fb3dbb6eb38e4eb27d24aa839920483e"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1611199f178793ca9a060c99b284e11f6d7d124998191f1cace9a0245334d219"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0308b2ad161daf502908a6e21a57c78ded0258eba9a8f5e2545e2dafca312507"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eda91832201b86e3b70835f91522587725bec329ec68f2f7faf5124091e5ca7"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ece873c093aedd87fc07c2a7e333d52e458dc177016afa1edaf157e82b6914d8"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d97d3c9d209d5c30172baea5966f2129e8a198fec4a1aeb2f92abb6e82a2edb1"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6c4550d0db4931f5ebe9f0678916d1b06f06f5a99ba0b8a48b9457fd8959a7d4"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b6b8dd4af6324fc325d9483bec75ecf9be33e590928c9202d408e4eafff6a0a6"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:16122ae448bc89e2bea9d81ce6cb0f751e4e07da39bd1e70b95cae2493857853"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-win32.whl", hash = "sha256:71cc168c305a4445109cd0d4925406f6e66bcb48fde99a1835387c58af4ecfe9"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-win_amd64.whl", hash = "sha256:59ee78f2ecd53fef8454909cda7400fe2cfcd820f62b8a5d4dfe930102268054"}, + {file = "rapidfuzz-3.9.6-cp313-cp313-win_arm64.whl", hash = "sha256:58b4ce83f223605c358ae37e7a2d19a41b96aa65b1fede99cc664c9053af89ac"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9f469dbc9c4aeaac7dd005992af74b7dff94aa56a3ea063ce64e4b3e6736dd2f"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a9ed7ad9adb68d0fe63a156fe752bbf5f1403ed66961551e749641af2874da92"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39ffe48ffbeedf78d120ddfb9d583f2ca906712159a4e9c3c743c9f33e7b1775"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8502ccdea9084d54b6f737d96a3b60a84e3afed9d016686dc979b49cdac71613"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6a4bec4956e06b170ca896ba055d08d4c457dac745548172443982956a80e118"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c0488b1c273be39e109ff885ccac0448b2fa74dea4c4dc676bcf756c15f16d6"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0542c036cb6acf24edd2c9e0411a67d7ba71e29e4d3001a082466b86fc34ff30"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0a96b52c9f26857bf009e270dcd829381e7a634f7ddd585fa29b87d4c82146d9"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:6edd3cd7c4aa8c68c716d349f531bd5011f2ca49ddade216bb4429460151559f"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:50b2fb55d7ed58c66d49c9f954acd8fc4a3f0e9fd0ff708299bd8abb68238d0e"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:32848dfe54391636b84cda1823fd23e5a6b1dbb8be0e9a1d80e4ee9903820994"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:29146cb7a1bf69c87e928b31bffa54f066cb65639d073b36e1425f98cccdebc6"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-win32.whl", hash = "sha256:aed13e5edacb0ecadcc304cc66e93e7e77ff24f059c9792ee602c0381808e10c"}, + {file = "rapidfuzz-3.9.6-cp38-cp38-win_amd64.whl", hash = "sha256:af440e36b828922256d0b4d79443bf2cbe5515fc4b0e9e96017ec789b36bb9fc"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:efa674b407424553024522159296690d99d6e6b1192cafe99ca84592faff16b4"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0b40ff76ee19b03ebf10a0a87938f86814996a822786c41c3312d251b7927849"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16a6c7997cb5927ced6f617122eb116ba514ec6b6f60f4803e7925ef55158891"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3f42504bdc8d770987fc3d99964766d42b2a03e4d5b0f891decdd256236bae0"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9462aa2be9f60b540c19a083471fdf28e7cf6434f068b631525b5e6251b35e"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1629698e68f47609a73bf9e73a6da3a4cac20bc710529215cbdf111ab603665b"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68bc7621843d8e9a7fd1b1a32729465bf94b47b6fb307d906da168413331f8d6"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c6254c50f15bc2fcc33cb93a95a81b702d9e6590f432a7f7822b8c7aba9ae288"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:7e535a114fa575bc143e175e4ca386a467ec8c42909eff500f5f0f13dc84e3e0"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d50acc0e9d67e4ba7a004a14c42d1b1e8b6ca1c515692746f4f8e7948c673167"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fa742ec60bec53c5a211632cf1d31b9eb5a3c80f1371a46a23ac25a1fa2ab209"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c256fa95d29cbe5aa717db790b231a9a5b49e5983d50dc9df29d364a1db5e35b"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-win32.whl", hash = "sha256:89acbf728b764421036c173a10ada436ecca22999851cdc01d0aa904c70d362d"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-win_amd64.whl", hash = "sha256:c608fcba8b14d86c04cb56b203fed31a96e8a1ebb4ce99e7b70313c5bf8cf497"}, + {file = "rapidfuzz-3.9.6-cp39-cp39-win_arm64.whl", hash = "sha256:d41c00ded0e22e9dba88ff23ebe0dc9d2a5f21ba2f88e185ea7374461e61daa9"}, + {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a65c2f63218ea2dedd56fc56361035e189ca123bd9c9ce63a9bef6f99540d681"}, + {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:680dc78a5f889d3b89f74824b89fe357f49f88ad10d2c121e9c3ad37bac1e4eb"}, + {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8ca862927a0b05bd825e46ddf82d0724ea44b07d898ef639386530bf9b40f15"}, + {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2116fa1fbff21fa52cd46f3cfcb1e193ba1d65d81f8b6e123193451cd3d6c15e"}, + {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dcb7d9afd740370a897c15da61d3d57a8d54738d7c764a99cedb5f746d6a003"}, + {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1a5bd6401bb489e14cbb5981c378d53ede850b7cc84b2464cad606149cc4e17d"}, + {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:29fda70b9d03e29df6fc45cc27cbcc235534b1b0b2900e0a3ae0b43022aaeef5"}, + {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:88144f5f52ae977df9352029488326afadd7a7f42c6779d486d1f82d43b2b1f2"}, + {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:715aeaabafba2709b9dd91acb2a44bad59d60b4616ef90c08f4d4402a3bbca60"}, + {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af26ebd3714224fbf9bebbc27bdbac14f334c15f5d7043699cd694635050d6ca"}, + {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101bd2df438861a005ed47c032631b7857dfcdb17b82beeeb410307983aac61d"}, + {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2185e8e29809b97ad22a7f99281d1669a89bdf5fa1ef4ef1feca36924e675367"}, + {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9e53c72d08f0e9c6e4a369e52df5971f311305b4487690c62e8dd0846770260c"}, + {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a0cb157162f0cdd62e538c7bd298ff669847fc43a96422811d5ab933f4c16c3a"}, + {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bb5ff2bd48132ed5e7fbb8f619885facb2e023759f2519a448b2c18afe07e5d"}, + {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6dc37f601865e8407e3a8037ffbc3afe0b0f837b2146f7632bd29d087385babe"}, + {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a657eee4b94668faf1fa2703bdd803654303f7e468eb9ba10a664d867ed9e779"}, + {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:51be6ab5b1d5bb32abd39718f2a5e3835502e026a8272d139ead295c224a6f5e"}, + {file = "rapidfuzz-3.9.6.tar.gz", hash = "sha256:5cf2a7d621e4515fee84722e93563bf77ff2cbe832a77a48b81f88f9e23b9e8d"}, ] [package.extras] @@ -2140,57 +2176,57 @@ dev = ["black (==22.1.0)", "flake8 (==4.0.1)", "isort (==5.10.1)"] [[package]] name = "red-discordbot" -version = "3.5.12" +version = "3.5.13" description = "A highly customisable Discord bot" optional = false python-versions = "<3.12,>=3.8.1" files = [ - {file = "Red_DiscordBot-3.5.12-py3-none-any.whl", hash = "sha256:884fc4d928b34b99f556bcb62f8b626cb645a1971c4c7acd8566e3096159e9bc"}, - {file = "red_discordbot-3.5.12.tar.gz", hash = "sha256:5f8b12dd003ebd35bf0896a788e6f1d064aae226583fca438fddb690ca31491b"}, + {file = "Red_DiscordBot-3.5.13-py3-none-any.whl", hash = "sha256:bd598a91c7504503b03b0d10f8ad1f230403fbab981a78f00461be61d458c285"}, + {file = "red_discordbot-3.5.13.tar.gz", hash = "sha256:7708dcc8203f2487616e95eba2aa1a6e5d78fbb03975c0b96587b0548c0f5d5b"}, ] [package.dependencies] aiohttp = "3.9.5" aiohttp-json-rpc = "0.13.3" aiosignal = "1.3.1" -apsw = "3.46.0.1" -attrs = "24.1.0" -babel = "2.15.0" +apsw = "3.46.1.0" +attrs = "24.2.0" +babel = "2.16.0" brotli = "1.1.0" click = "8.1.7" colorama = {version = "0.4.6", markers = "sys_platform == \"win32\""} discord-py = "2.4.0" distro = {version = "1.9.0", markers = "sys_platform == \"linux\""} frozenlist = "1.4.1" -idna = "3.7" -markdown = "3.6" +idna = "3.8" +markdown = "3.7" markdown-it-py = "3.0.0" mdurl = "0.1.2" multidict = "6.0.5" -orjson = "3.10.6" +orjson = "3.10.7" packaging = "24.1" platformdirs = "4.2.2" psutil = "6.0.0" pygments = "2.18.0" python-dateutil = "2.9.0.post0" -pyyaml = "6.0.1" -rapidfuzz = "3.9.5" +pyyaml = "6.0.2" +rapidfuzz = "3.9.6" red-commons = "1.0.0" red-lavalink = "0.11.0" -rich = "13.7.1" +rich = "13.8.0" schema = "0.7.7" six = "1.16.0" typing-extensions = "4.12.2" -uvloop = {version = "0.19.0", markers = "sys_platform != \"win32\" and platform_python_implementation == \"CPython\""} +uvloop = {version = "0.20.0", markers = "sys_platform != \"win32\" and platform_python_implementation == \"CPython\""} yarl = "1.9.4" [package.extras] all = ["async-timeout (==4.0.3)", "asyncpg (==0.29.0)"] -dev = ["alabaster (==0.7.13)", "astroid (==3.2.4)", "async-timeout (==4.0.3)", "asyncpg (==0.29.0)", "black (==23.12.1)", "certifi (==2024.7.4)", "charset-normalizer (==3.3.2)", "dill (==0.3.8)", "docutils (==0.20.1)", "exceptiongroup (==1.2.2)", "imagesize (==1.4.1)", "importlib-metadata (==8.2.0)", "iniconfig (==2.0.0)", "isort (==5.13.2)", "jinja2 (==3.1.4)", "markupsafe (==2.1.5)", "mccabe (==0.7.0)", "mypy-extensions (==1.0.0)", "pathspec (==0.12.1)", "pluggy (==1.5.0)", "pylint (==3.2.6)", "pytest (==7.4.4)", "pytest-asyncio (==0.21.2)", "pytest-mock (==3.14.0)", "pytz (==2024.1)", "requests (==2.32.3)", "snowballstemmer (==2.2.0)", "sphinx (==7.1.2)", "sphinx-prompt (==1.7.0)", "sphinx-rtd-theme (==2.0.0)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jquery (==4.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "tomli (==2.0.1)", "tomli (==2.0.1)", "tomlkit (==0.13.0)", "urllib3 (==2.2.2)", "zipp (==3.19.2)"] -doc = ["alabaster (==0.7.13)", "certifi (==2024.7.4)", "charset-normalizer (==3.3.2)", "docutils (==0.20.1)", "imagesize (==1.4.1)", "importlib-metadata (==8.2.0)", "jinja2 (==3.1.4)", "markupsafe (==2.1.5)", "pytz (==2024.1)", "requests (==2.32.3)", "snowballstemmer (==2.2.0)", "sphinx (==7.1.2)", "sphinx-prompt (==1.7.0)", "sphinx-rtd-theme (==2.0.0)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jquery (==4.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "urllib3 (==2.2.2)", "zipp (==3.19.2)"] +dev = ["alabaster (==0.7.13)", "astroid (==3.2.4)", "async-timeout (==4.0.3)", "asyncpg (==0.29.0)", "black (==23.12.1)", "certifi (==2024.7.4)", "charset-normalizer (==3.3.2)", "dill (==0.3.8)", "docutils (==0.20.1)", "exceptiongroup (==1.2.2)", "imagesize (==1.4.1)", "importlib-metadata (==8.4.0)", "iniconfig (==2.0.0)", "isort (==5.13.2)", "jinja2 (==3.1.4)", "markupsafe (==2.1.5)", "mccabe (==0.7.0)", "mypy-extensions (==1.0.0)", "pathspec (==0.12.1)", "pluggy (==1.5.0)", "pylint (==3.2.6)", "pytest (==7.4.4)", "pytest-asyncio (==0.21.2)", "pytest-mock (==3.14.0)", "pytz (==2024.1)", "requests (==2.32.3)", "snowballstemmer (==2.2.0)", "sphinx (==7.1.2)", "sphinx-prompt (==1.7.0)", "sphinx-rtd-theme (==2.0.0)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jquery (==4.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "tomli (==2.0.1)", "tomli (==2.0.1)", "tomlkit (==0.13.2)", "urllib3 (==2.2.2)", "zipp (==3.20.1)"] +doc = ["alabaster (==0.7.13)", "certifi (==2024.7.4)", "charset-normalizer (==3.3.2)", "docutils (==0.20.1)", "imagesize (==1.4.1)", "importlib-metadata (==8.4.0)", "jinja2 (==3.1.4)", "markupsafe (==2.1.5)", "pytz (==2024.1)", "requests (==2.32.3)", "snowballstemmer (==2.2.0)", "sphinx (==7.1.2)", "sphinx-prompt (==1.7.0)", "sphinx-rtd-theme (==2.0.0)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jquery (==4.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "urllib3 (==2.2.2)", "zipp (==3.20.1)"] postgres = ["async-timeout (==4.0.3)", "asyncpg (==0.29.0)"] style = ["black (==23.12.1)", "mypy-extensions (==1.0.0)", "pathspec (==0.12.1)", "tomli (==2.0.1)"] -test = ["astroid (==3.2.4)", "dill (==0.3.8)", "exceptiongroup (==1.2.2)", "iniconfig (==2.0.0)", "isort (==5.13.2)", "mccabe (==0.7.0)", "pluggy (==1.5.0)", "pylint (==3.2.6)", "pytest (==7.4.4)", "pytest-asyncio (==0.21.2)", "pytest-mock (==3.14.0)", "tomli (==2.0.1)", "tomlkit (==0.13.0)"] +test = ["astroid (==3.2.4)", "dill (==0.3.8)", "exceptiongroup (==1.2.2)", "iniconfig (==2.0.0)", "isort (==5.13.2)", "mccabe (==0.7.0)", "pluggy (==1.5.0)", "pylint (==3.2.6)", "pytest (==7.4.4)", "pytest-asyncio (==0.21.2)", "pytest-mock (==3.14.0)", "tomli (==2.0.1)", "tomlkit (==0.13.2)"] [[package]] name = "red-lavalink" @@ -2214,90 +2250,105 @@ test = ["pytest (>=7)", "pytest-asyncio (>=0.19)"] [[package]] name = "regex" -version = "2024.7.24" +version = "2024.9.11" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" files = [ - {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b0d3f567fafa0633aee87f08b9276c7062da9616931382993c03808bb68ce"}, - {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3426de3b91d1bc73249042742f45c2148803c111d1175b283270177fdf669024"}, - {file = "regex-2024.7.24-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f273674b445bcb6e4409bf8d1be67bc4b58e8b46fd0d560055d515b8830063cd"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23acc72f0f4e1a9e6e9843d6328177ae3074b4182167e34119ec7233dfeccf53"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65fd3d2e228cae024c411c5ccdffae4c315271eee4a8b839291f84f796b34eca"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c414cbda77dbf13c3bc88b073a1a9f375c7b0cb5e115e15d4b73ec3a2fbc6f59"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf7a89eef64b5455835f5ed30254ec19bf41f7541cd94f266ab7cbd463f00c41"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19c65b00d42804e3fbea9708f0937d157e53429a39b7c61253ff15670ff62cb5"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7a5486ca56c8869070a966321d5ab416ff0f83f30e0e2da1ab48815c8d165d46"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6f51f9556785e5a203713f5efd9c085b4a45aecd2a42573e2b5041881b588d1f"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a4997716674d36a82eab3e86f8fa77080a5d8d96a389a61ea1d0e3a94a582cf7"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c0abb5e4e8ce71a61d9446040c1e86d4e6d23f9097275c5bd49ed978755ff0fe"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:18300a1d78cf1290fa583cd8b7cde26ecb73e9f5916690cf9d42de569c89b1ce"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:416c0e4f56308f34cdb18c3f59849479dde5b19febdcd6e6fa4d04b6c31c9faa"}, - {file = "regex-2024.7.24-cp310-cp310-win32.whl", hash = "sha256:fb168b5924bef397b5ba13aabd8cf5df7d3d93f10218d7b925e360d436863f66"}, - {file = "regex-2024.7.24-cp310-cp310-win_amd64.whl", hash = "sha256:6b9fc7e9cc983e75e2518496ba1afc524227c163e43d706688a6bb9eca41617e"}, - {file = "regex-2024.7.24-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:382281306e3adaaa7b8b9ebbb3ffb43358a7bbf585fa93821300a418bb975281"}, - {file = "regex-2024.7.24-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4fdd1384619f406ad9037fe6b6eaa3de2749e2e12084abc80169e8e075377d3b"}, - {file = "regex-2024.7.24-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3d974d24edb231446f708c455fd08f94c41c1ff4f04bcf06e5f36df5ef50b95a"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2ec4419a3fe6cf8a4795752596dfe0adb4aea40d3683a132bae9c30b81e8d73"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb563dd3aea54c797adf513eeec819c4213d7dbfc311874eb4fd28d10f2ff0f2"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:45104baae8b9f67569f0f1dca5e1f1ed77a54ae1cd8b0b07aba89272710db61e"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:994448ee01864501912abf2bad9203bffc34158e80fe8bfb5b031f4f8e16da51"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fac296f99283ac232d8125be932c5cd7644084a30748fda013028c815ba3364"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7e37e809b9303ec3a179085415cb5f418ecf65ec98cdfe34f6a078b46ef823ee"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:01b689e887f612610c869421241e075c02f2e3d1ae93a037cb14f88ab6a8934c"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f6442f0f0ff81775eaa5b05af8a0ffa1dda36e9cf6ec1e0d3d245e8564b684ce"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:871e3ab2838fbcb4e0865a6e01233975df3a15e6fce93b6f99d75cacbd9862d1"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c918b7a1e26b4ab40409820ddccc5d49871a82329640f5005f73572d5eaa9b5e"}, - {file = "regex-2024.7.24-cp311-cp311-win32.whl", hash = "sha256:2dfbb8baf8ba2c2b9aa2807f44ed272f0913eeeba002478c4577b8d29cde215c"}, - {file = "regex-2024.7.24-cp311-cp311-win_amd64.whl", hash = "sha256:538d30cd96ed7d1416d3956f94d54e426a8daf7c14527f6e0d6d425fcb4cca52"}, - {file = "regex-2024.7.24-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fe4ebef608553aff8deb845c7f4f1d0740ff76fa672c011cc0bacb2a00fbde86"}, - {file = "regex-2024.7.24-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:74007a5b25b7a678459f06559504f1eec2f0f17bca218c9d56f6a0a12bfffdad"}, - {file = "regex-2024.7.24-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7df9ea48641da022c2a3c9c641650cd09f0cd15e8908bf931ad538f5ca7919c9"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a1141a1dcc32904c47f6846b040275c6e5de0bf73f17d7a409035d55b76f289"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80c811cfcb5c331237d9bad3bea2c391114588cf4131707e84d9493064d267f9"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7214477bf9bd195894cf24005b1e7b496f46833337b5dedb7b2a6e33f66d962c"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d55588cba7553f0b6ec33130bc3e114b355570b45785cebdc9daed8c637dd440"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558a57cfc32adcf19d3f791f62b5ff564922942e389e3cfdb538a23d65a6b610"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a512eed9dfd4117110b1881ba9a59b31433caed0c4101b361f768e7bcbaf93c5"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:86b17ba823ea76256b1885652e3a141a99a5c4422f4a869189db328321b73799"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5eefee9bfe23f6df09ffb6dfb23809f4d74a78acef004aa904dc7c88b9944b05"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:731fcd76bbdbf225e2eb85b7c38da9633ad3073822f5ab32379381e8c3c12e94"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eaef80eac3b4cfbdd6de53c6e108b4c534c21ae055d1dbea2de6b3b8ff3def38"}, - {file = "regex-2024.7.24-cp312-cp312-win32.whl", hash = "sha256:185e029368d6f89f36e526764cf12bf8d6f0e3a2a7737da625a76f594bdfcbfc"}, - {file = "regex-2024.7.24-cp312-cp312-win_amd64.whl", hash = "sha256:2f1baff13cc2521bea83ab2528e7a80cbe0ebb2c6f0bfad15be7da3aed443908"}, - {file = "regex-2024.7.24-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:66b4c0731a5c81921e938dcf1a88e978264e26e6ac4ec96a4d21ae0354581ae0"}, - {file = "regex-2024.7.24-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:88ecc3afd7e776967fa16c80f974cb79399ee8dc6c96423321d6f7d4b881c92b"}, - {file = "regex-2024.7.24-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:64bd50cf16bcc54b274e20235bf8edbb64184a30e1e53873ff8d444e7ac656b2"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb462f0e346fcf41a901a126b50f8781e9a474d3927930f3490f38a6e73b6950"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a82465ebbc9b1c5c50738536fdfa7cab639a261a99b469c9d4c7dcbb2b3f1e57"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68a8f8c046c6466ac61a36b65bb2395c74451df2ffb8458492ef49900efed293"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac8e84fff5d27420f3c1e879ce9929108e873667ec87e0c8eeb413a5311adfe"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba2537ef2163db9e6ccdbeb6f6424282ae4dea43177402152c67ef869cf3978b"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:43affe33137fcd679bdae93fb25924979517e011f9dea99163f80b82eadc7e53"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:c9bb87fdf2ab2370f21e4d5636e5317775e5d51ff32ebff2cf389f71b9b13750"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:945352286a541406f99b2655c973852da7911b3f4264e010218bbc1cc73168f2"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:8bc593dcce679206b60a538c302d03c29b18e3d862609317cb560e18b66d10cf"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3f3b6ca8eae6d6c75a6cff525c8530c60e909a71a15e1b731723233331de4169"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c51edc3541e11fbe83f0c4d9412ef6c79f664a3745fab261457e84465ec9d5a8"}, - {file = "regex-2024.7.24-cp38-cp38-win32.whl", hash = "sha256:d0a07763776188b4db4c9c7fb1b8c494049f84659bb387b71c73bbc07f189e96"}, - {file = "regex-2024.7.24-cp38-cp38-win_amd64.whl", hash = "sha256:8fd5afd101dcf86a270d254364e0e8dddedebe6bd1ab9d5f732f274fa00499a5"}, - {file = "regex-2024.7.24-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0ffe3f9d430cd37d8fa5632ff6fb36d5b24818c5c986893063b4e5bdb84cdf24"}, - {file = "regex-2024.7.24-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:25419b70ba00a16abc90ee5fce061228206173231f004437730b67ac77323f0d"}, - {file = "regex-2024.7.24-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33e2614a7ce627f0cdf2ad104797d1f68342d967de3695678c0cb84f530709f8"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d33a0021893ede5969876052796165bab6006559ab845fd7b515a30abdd990dc"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04ce29e2c5fedf296b1a1b0acc1724ba93a36fb14031f3abfb7abda2806c1535"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b16582783f44fbca6fcf46f61347340c787d7530d88b4d590a397a47583f31dd"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:836d3cc225b3e8a943d0b02633fb2f28a66e281290302a79df0e1eaa984ff7c1"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:438d9f0f4bc64e8dea78274caa5af971ceff0f8771e1a2333620969936ba10be"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:973335b1624859cb0e52f96062a28aa18f3a5fc77a96e4a3d6d76e29811a0e6e"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c5e69fd3eb0b409432b537fe3c6f44ac089c458ab6b78dcec14478422879ec5f"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fbf8c2f00904eaf63ff37718eb13acf8e178cb940520e47b2f05027f5bb34ce3"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2757ace61bc4061b69af19e4689fa4416e1a04840f33b441034202b5cd02d4"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:44fc61b99035fd9b3b9453f1713234e5a7c92a04f3577252b45feefe1b327759"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:84c312cdf839e8b579f504afcd7b65f35d60b6285d892b19adea16355e8343c9"}, - {file = "regex-2024.7.24-cp39-cp39-win32.whl", hash = "sha256:ca5b2028c2f7af4e13fb9fc29b28d0ce767c38c7facdf64f6c2cd040413055f1"}, - {file = "regex-2024.7.24-cp39-cp39-win_amd64.whl", hash = "sha256:7c479f5ae937ec9985ecaf42e2e10631551d909f203e31308c12d703922742f9"}, - {file = "regex-2024.7.24.tar.gz", hash = "sha256:9cfd009eed1a46b27c14039ad5bbc5e71b6367c5b2e6d5f5da0ea91600817506"}, + {file = "regex-2024.9.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1494fa8725c285a81d01dc8c06b55287a1ee5e0e382d8413adc0a9197aac6408"}, + {file = "regex-2024.9.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0e12c481ad92d129c78f13a2a3662317e46ee7ef96c94fd332e1c29131875b7d"}, + {file = "regex-2024.9.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16e13a7929791ac1216afde26f712802e3df7bf0360b32e4914dca3ab8baeea5"}, + {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46989629904bad940bbec2106528140a218b4a36bb3042d8406980be1941429c"}, + {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a906ed5e47a0ce5f04b2c981af1c9acf9e8696066900bf03b9d7879a6f679fc8"}, + {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a091b0550b3b0207784a7d6d0f1a00d1d1c8a11699c1a4d93db3fbefc3ad35"}, + {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ddcd9a179c0a6fa8add279a4444015acddcd7f232a49071ae57fa6e278f1f71"}, + {file = "regex-2024.9.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b41e1adc61fa347662b09398e31ad446afadff932a24807d3ceb955ed865cc8"}, + {file = "regex-2024.9.11-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ced479f601cd2f8ca1fd7b23925a7e0ad512a56d6e9476f79b8f381d9d37090a"}, + {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:635a1d96665f84b292e401c3d62775851aedc31d4f8784117b3c68c4fcd4118d"}, + {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c0256beda696edcf7d97ef16b2a33a8e5a875affd6fa6567b54f7c577b30a137"}, + {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3ce4f1185db3fbde8ed8aa223fc9620f276c58de8b0d4f8cc86fd1360829edb6"}, + {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:09d77559e80dcc9d24570da3745ab859a9cf91953062e4ab126ba9d5993688ca"}, + {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a22ccefd4db3f12b526eccb129390942fe874a3a9fdbdd24cf55773a1faab1a"}, + {file = "regex-2024.9.11-cp310-cp310-win32.whl", hash = "sha256:f745ec09bc1b0bd15cfc73df6fa4f726dcc26bb16c23a03f9e3367d357eeedd0"}, + {file = "regex-2024.9.11-cp310-cp310-win_amd64.whl", hash = "sha256:01c2acb51f8a7d6494c8c5eafe3d8e06d76563d8a8a4643b37e9b2dd8a2ff623"}, + {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df"}, + {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268"}, + {file = "regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad"}, + {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679"}, + {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4"}, + {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664"}, + {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50"}, + {file = "regex-2024.9.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199"}, + {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4"}, + {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd"}, + {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f"}, + {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96"}, + {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1"}, + {file = "regex-2024.9.11-cp311-cp311-win32.whl", hash = "sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9"}, + {file = "regex-2024.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf"}, + {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7"}, + {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231"}, + {file = "regex-2024.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d"}, + {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64"}, + {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42"}, + {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766"}, + {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a"}, + {file = "regex-2024.9.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9"}, + {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d"}, + {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822"}, + {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0"}, + {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a"}, + {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a"}, + {file = "regex-2024.9.11-cp312-cp312-win32.whl", hash = "sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776"}, + {file = "regex-2024.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009"}, + {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784"}, + {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36"}, + {file = "regex-2024.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92"}, + {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86"}, + {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85"}, + {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963"}, + {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6"}, + {file = "regex-2024.9.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802"}, + {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29"}, + {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8"}, + {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84"}, + {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554"}, + {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8"}, + {file = "regex-2024.9.11-cp313-cp313-win32.whl", hash = "sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8"}, + {file = "regex-2024.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f"}, + {file = "regex-2024.9.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:35f4a6f96aa6cb3f2f7247027b07b15a374f0d5b912c0001418d1d55024d5cb4"}, + {file = "regex-2024.9.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:55b96e7ce3a69a8449a66984c268062fbaa0d8ae437b285428e12797baefce7e"}, + {file = "regex-2024.9.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb130fccd1a37ed894824b8c046321540263013da72745d755f2d35114b81a60"}, + {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:323c1f04be6b2968944d730e5c2091c8c89767903ecaa135203eec4565ed2b2b"}, + {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be1c8ed48c4c4065ecb19d882a0ce1afe0745dfad8ce48c49586b90a55f02366"}, + {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5b029322e6e7b94fff16cd120ab35a253236a5f99a79fb04fda7ae71ca20ae8"}, + {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6fff13ef6b5f29221d6904aa816c34701462956aa72a77f1f151a8ec4f56aeb"}, + {file = "regex-2024.9.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:587d4af3979376652010e400accc30404e6c16b7df574048ab1f581af82065e4"}, + {file = "regex-2024.9.11-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:079400a8269544b955ffa9e31f186f01d96829110a3bf79dc338e9910f794fca"}, + {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f9268774428ec173654985ce55fc6caf4c6d11ade0f6f914d48ef4719eb05ebb"}, + {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:23f9985c8784e544d53fc2930fc1ac1a7319f5d5332d228437acc9f418f2f168"}, + {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2941333154baff9838e88aa71c1d84f4438189ecc6021a12c7573728b5838e"}, + {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e93f1c331ca8e86fe877a48ad64e77882c0c4da0097f2212873a69bbfea95d0c"}, + {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:846bc79ee753acf93aef4184c040d709940c9d001029ceb7b7a52747b80ed2dd"}, + {file = "regex-2024.9.11-cp38-cp38-win32.whl", hash = "sha256:c94bb0a9f1db10a1d16c00880bdebd5f9faf267273b8f5bd1878126e0fbde771"}, + {file = "regex-2024.9.11-cp38-cp38-win_amd64.whl", hash = "sha256:2b08fce89fbd45664d3df6ad93e554b6c16933ffa9d55cb7e01182baaf971508"}, + {file = "regex-2024.9.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:07f45f287469039ffc2c53caf6803cd506eb5f5f637f1d4acb37a738f71dd066"}, + {file = "regex-2024.9.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4838e24ee015101d9f901988001038f7f0d90dc0c3b115541a1365fb439add62"}, + {file = "regex-2024.9.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6edd623bae6a737f10ce853ea076f56f507fd7726bee96a41ee3d68d347e4d16"}, + {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c69ada171c2d0e97a4b5aa78fbb835e0ffbb6b13fc5da968c09811346564f0d3"}, + {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02087ea0a03b4af1ed6ebab2c54d7118127fee8d71b26398e8e4b05b78963199"}, + {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69dee6a020693d12a3cf892aba4808fe168d2a4cef368eb9bf74f5398bfd4ee8"}, + {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:297f54910247508e6e5cae669f2bc308985c60540a4edd1c77203ef19bfa63ca"}, + {file = "regex-2024.9.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ecea58b43a67b1b79805f1a0255730edaf5191ecef84dbc4cc85eb30bc8b63b9"}, + {file = "regex-2024.9.11-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:eab4bb380f15e189d1313195b062a6aa908f5bd687a0ceccd47c8211e9cf0d4a"}, + {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0cbff728659ce4bbf4c30b2a1be040faafaa9eca6ecde40aaff86f7889f4ab39"}, + {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:54c4a097b8bc5bb0dfc83ae498061d53ad7b5762e00f4adaa23bee22b012e6ba"}, + {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:73d6d2f64f4d894c96626a75578b0bf7d9e56dcda8c3d037a2118fdfe9b1c664"}, + {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:e53b5fbab5d675aec9f0c501274c467c0f9a5d23696cfc94247e1fb56501ed89"}, + {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ffbcf9221e04502fc35e54d1ce9567541979c3fdfb93d2c554f0ca583a19b35"}, + {file = "regex-2024.9.11-cp39-cp39-win32.whl", hash = "sha256:e4c22e1ac1f1ec1e09f72e6c44d8f2244173db7eb9629cc3a346a8d7ccc31142"}, + {file = "regex-2024.9.11-cp39-cp39-win_amd64.whl", hash = "sha256:faa3c142464efec496967359ca99696c896c591c56c53506bac1ad465f66e919"}, + {file = "regex-2024.9.11.tar.gz", hash = "sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd"}, ] [[package]] @@ -2323,13 +2374,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rich" -version = "13.7.1" +version = "13.8.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.7.0" files = [ - {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, - {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, + {file = "rich-13.8.0-py3-none-any.whl", hash = "sha256:2e85306a063b9492dffc86278197a60cbece75bcb766022f3436f567cae11bdc"}, + {file = "rich-13.8.0.tar.gz", hash = "sha256:a5ac1f1cd448ade0d59cc3356f7db7a7ccda2c8cbae9c7a90c28ff463d3e91f4"}, ] [package.dependencies] @@ -2466,13 +2517,13 @@ files = [ [[package]] name = "urllib3" -version = "2.2.2" +version = "2.2.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, - {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, ] [package.extras] @@ -2497,42 +2548,42 @@ click = "*" [[package]] name = "uvloop" -version = "0.19.0" +version = "0.20.0" description = "Fast implementation of asyncio event loop on top of libuv" optional = false python-versions = ">=3.8.0" files = [ - {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"}, - {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"}, - {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"}, - {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"}, - {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"}, - {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"}, - {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"}, - {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"}, - {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"}, - {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"}, - {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"}, - {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"}, - {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"}, - {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"}, - {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"}, - {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"}, - {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"}, - {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"}, - {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"}, - {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"}, - {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"}, - {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"}, - {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"}, - {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"}, - {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"}, - {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"}, - {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"}, - {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"}, - {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"}, - {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"}, - {file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"}, + {file = "uvloop-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9ebafa0b96c62881d5cafa02d9da2e44c23f9f0cd829f3a32a6aff771449c996"}, + {file = "uvloop-0.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:35968fc697b0527a06e134999eef859b4034b37aebca537daeb598b9d45a137b"}, + {file = "uvloop-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b16696f10e59d7580979b420eedf6650010a4a9c3bd8113f24a103dfdb770b10"}, + {file = "uvloop-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b04d96188d365151d1af41fa2d23257b674e7ead68cfd61c725a422764062ae"}, + {file = "uvloop-0.20.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:94707205efbe809dfa3a0d09c08bef1352f5d3d6612a506f10a319933757c006"}, + {file = "uvloop-0.20.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:89e8d33bb88d7263f74dc57d69f0063e06b5a5ce50bb9a6b32f5fcbe655f9e73"}, + {file = "uvloop-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e50289c101495e0d1bb0bfcb4a60adde56e32f4449a67216a1ab2750aa84f037"}, + {file = "uvloop-0.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e237f9c1e8a00e7d9ddaa288e535dc337a39bcbf679f290aee9d26df9e72bce9"}, + {file = "uvloop-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:746242cd703dc2b37f9d8b9f173749c15e9a918ddb021575a0205ec29a38d31e"}, + {file = "uvloop-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82edbfd3df39fb3d108fc079ebc461330f7c2e33dbd002d146bf7c445ba6e756"}, + {file = "uvloop-0.20.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:80dc1b139516be2077b3e57ce1cb65bfed09149e1d175e0478e7a987863b68f0"}, + {file = "uvloop-0.20.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f44af67bf39af25db4c1ac27e82e9665717f9c26af2369c404be865c8818dcf"}, + {file = "uvloop-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4b75f2950ddb6feed85336412b9a0c310a2edbcf4cf931aa5cfe29034829676d"}, + {file = "uvloop-0.20.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:77fbc69c287596880ecec2d4c7a62346bef08b6209749bf6ce8c22bbaca0239e"}, + {file = "uvloop-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6462c95f48e2d8d4c993a2950cd3d31ab061864d1c226bbf0ee2f1a8f36674b9"}, + {file = "uvloop-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:649c33034979273fa71aa25d0fe120ad1777c551d8c4cd2c0c9851d88fcb13ab"}, + {file = "uvloop-0.20.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a609780e942d43a275a617c0839d85f95c334bad29c4c0918252085113285b5"}, + {file = "uvloop-0.20.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aea15c78e0d9ad6555ed201344ae36db5c63d428818b4b2a42842b3870127c00"}, + {file = "uvloop-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0e94b221295b5e69de57a1bd4aeb0b3a29f61be6e1b478bb8a69a73377db7ba"}, + {file = "uvloop-0.20.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fee6044b64c965c425b65a4e17719953b96e065c5b7e09b599ff332bb2744bdf"}, + {file = "uvloop-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:265a99a2ff41a0fd56c19c3838b29bf54d1d177964c300dad388b27e84fd7847"}, + {file = "uvloop-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b10c2956efcecb981bf9cfb8184d27d5d64b9033f917115a960b83f11bfa0d6b"}, + {file = "uvloop-0.20.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e7d61fe8e8d9335fac1bf8d5d82820b4808dd7a43020c149b63a1ada953d48a6"}, + {file = "uvloop-0.20.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2beee18efd33fa6fdb0976e18475a4042cd31c7433c866e8a09ab604c7c22ff2"}, + {file = "uvloop-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8c36fdf3e02cec92aed2d44f63565ad1522a499c654f07935c8f9d04db69e95"}, + {file = "uvloop-0.20.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0fac7be202596c7126146660725157d4813aa29a4cc990fe51346f75ff8fde7"}, + {file = "uvloop-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d0fba61846f294bce41eb44d60d58136090ea2b5b99efd21cbdf4e21927c56a"}, + {file = "uvloop-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95720bae002ac357202e0d866128eb1ac82545bcf0b549b9abe91b5178d9b541"}, + {file = "uvloop-0.20.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:36c530d8fa03bfa7085af54a48f2ca16ab74df3ec7108a46ba82fd8b411a2315"}, + {file = "uvloop-0.20.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e97152983442b499d7a71e44f29baa75b3b02e65d9c44ba53b10338e98dedb66"}, + {file = "uvloop-0.20.0.tar.gz", hash = "sha256:4603ca714a754fc8d9b197e325db25b2ea045385e8a3ad05d3463de725fdf469"}, ] [package.extras] @@ -2541,46 +2592,41 @@ test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)" [[package]] name = "watchdog" -version = "4.0.2" +version = "5.0.2" description = "Filesystem events monitoring" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8"}, - {file = "watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19"}, - {file = "watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b"}, - {file = "watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c"}, - {file = "watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270"}, + {file = "watchdog-5.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d961f4123bb3c447d9fcdcb67e1530c366f10ab3a0c7d1c0c9943050936d4877"}, + {file = "watchdog-5.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72990192cb63872c47d5e5fefe230a401b87fd59d257ee577d61c9e5564c62e5"}, + {file = "watchdog-5.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bec703ad90b35a848e05e1b40bf0050da7ca28ead7ac4be724ae5ac2653a1a0"}, + {file = "watchdog-5.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dae7a1879918f6544201d33666909b040a46421054a50e0f773e0d870ed7438d"}, + {file = "watchdog-5.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c4a440f725f3b99133de610bfec93d570b13826f89616377715b9cd60424db6e"}, + {file = "watchdog-5.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8b2918c19e0d48f5f20df458c84692e2a054f02d9df25e6c3c930063eca64c1"}, + {file = "watchdog-5.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:aa9cd6e24126d4afb3752a3e70fce39f92d0e1a58a236ddf6ee823ff7dba28ee"}, + {file = "watchdog-5.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f627c5bf5759fdd90195b0c0431f99cff4867d212a67b384442c51136a098ed7"}, + {file = "watchdog-5.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d7594a6d32cda2b49df3fd9abf9b37c8d2f3eab5df45c24056b4a671ac661619"}, + {file = "watchdog-5.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba32efcccfe2c58f4d01115440d1672b4eb26cdd6fc5b5818f1fb41f7c3e1889"}, + {file = "watchdog-5.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:963f7c4c91e3f51c998eeff1b3fb24a52a8a34da4f956e470f4b068bb47b78ee"}, + {file = "watchdog-5.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8c47150aa12f775e22efff1eee9f0f6beee542a7aa1a985c271b1997d340184f"}, + {file = "watchdog-5.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:14dd4ed023d79d1f670aa659f449bcd2733c33a35c8ffd88689d9d243885198b"}, + {file = "watchdog-5.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b84bff0391ad4abe25c2740c7aec0e3de316fdf7764007f41e248422a7760a7f"}, + {file = "watchdog-5.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e8d5ff39f0a9968952cce548e8e08f849141a4fcc1290b1c17c032ba697b9d7"}, + {file = "watchdog-5.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fb223456db6e5f7bd9bbd5cd969f05aae82ae21acc00643b60d81c770abd402b"}, + {file = "watchdog-5.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9814adb768c23727a27792c77812cf4e2fd9853cd280eafa2bcfa62a99e8bd6e"}, + {file = "watchdog-5.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:901ee48c23f70193d1a7bc2d9ee297df66081dd5f46f0ca011be4f70dec80dab"}, + {file = "watchdog-5.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:638bcca3d5b1885c6ec47be67bf712b00a9ab3d4b22ec0881f4889ad870bc7e8"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:5597c051587f8757798216f2485e85eac583c3b343e9aa09127a3a6f82c65ee8"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:53ed1bf71fcb8475dd0ef4912ab139c294c87b903724b6f4a8bd98e026862e6d"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:29e4a2607bd407d9552c502d38b45a05ec26a8e40cc7e94db9bb48f861fa5abc"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:b6dc8f1d770a8280997e4beae7b9a75a33b268c59e033e72c8a10990097e5fde"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:d2ab34adc9bf1489452965cdb16a924e97d4452fcf88a50b21859068b50b5c3b"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:7d1aa7e4bb0f0c65a1a91ba37c10e19dabf7eaaa282c5787e51371f090748f4b"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:726eef8f8c634ac6584f86c9c53353a010d9f311f6c15a034f3800a7a891d941"}, + {file = "watchdog-5.0.2-py3-none-win32.whl", hash = "sha256:bda40c57115684d0216556671875e008279dea2dc00fcd3dde126ac8e0d7a2fb"}, + {file = "watchdog-5.0.2-py3-none-win_amd64.whl", hash = "sha256:d010be060c996db725fbce7e3ef14687cdcc76f4ca0e4339a68cc4532c382a73"}, + {file = "watchdog-5.0.2-py3-none-win_ia64.whl", hash = "sha256:3960136b2b619510569b90f0cd96408591d6c251a75c97690f4553ca88889769"}, + {file = "watchdog-5.0.2.tar.gz", hash = "sha256:dcebf7e475001d2cdeb020be630dc5b687e9acdd60d16fea6bb4508e7b94cf76"}, ] [package.extras] @@ -2680,13 +2726,13 @@ files = [ [[package]] name = "werkzeug" -version = "3.0.3" +version = "3.0.4" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.8" files = [ - {file = "werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8"}, - {file = "werkzeug-3.0.3.tar.gz", hash = "sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18"}, + {file = "werkzeug-3.0.4-py3-none-any.whl", hash = "sha256:02c9eb92b7d6c06f31a782811505d2157837cea66aaede3e217c7c27c039476c"}, + {file = "werkzeug-3.0.4.tar.gz", hash = "sha256:34f2371506b250df4d4f84bfe7b0921e4762525762bbd936614909fe25cd7306"}, ] [package.dependencies] @@ -2801,4 +2847,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "11d13e28e401b029d07772c02cf21a28cb0a96f224b87bd11e36aa4b0446fc24" +content-hash = "263e8505112c96a51e4fe34cfbdad48fe597fb2abd7821fecf3c8c81f2152a23" diff --git a/pyproject.toml b/pyproject.toml index e2175c1..5e1301b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ colorthief = "^0.2.1" beautifulsoup4 = "^4.12.3" markdownify = "^0.12.1" aiosqlite = "^0.20.0" -phx-class-registry = "^4.1.0" +phx-class-registry = "^5.0.0" [tool.poetry.group.dev] optional = true -- 2.45.3 From d92a0d27da93b6eb8317fd64eec14845a2d7e6cc Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 25 Sep 2024 22:51:45 -0400 Subject: [PATCH 339/376] fix(aurora): fix `/case` breaking if a case is resolved but the resolving user doesn't exist anymore Signed-off-by: cswimr --- aurora/utilities/factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 319de3f..af4c4dc 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -232,7 +232,7 @@ async def case_factory(interaction: Interaction, moderation: Moderation) -> Embe resolved_user = await moderation.get_resolved_by() embed.add_field( name="Resolve Reason", - value=f"Resolved by `{resolved_user.name}` ({resolved_user.id}) for:\n{box(moderation.resolve_reason)}", + value=f"Resolved by `{resolved_user.name or 'Deleted User'}` ({resolved_user.id or '0'}) for:\n{box(moderation.resolve_reason)}", inline=False, ) -- 2.45.3 From 24005800fa460768e01e173c85aedda6ec0ae764 Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 25 Sep 2024 22:55:33 -0400 Subject: [PATCH 340/376] fix(aurora): actually fixed the thing i just tried to fix Signed-off-by: cswimr --- aurora/utilities/factory.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index af4c4dc..fcb3f24 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -230,6 +230,8 @@ async def case_factory(interaction: Interaction, moderation: Moderation) -> Embe if moderation.resolved: resolved_user = await moderation.get_resolved_by() + if not resolved_user: + resolved_user = PartialUser(id=0, name="Deleted User", discriminator="0") embed.add_field( name="Resolve Reason", value=f"Resolved by `{resolved_user.name or 'Deleted User'}` ({resolved_user.id or '0'}) for:\n{box(moderation.resolve_reason)}", -- 2.45.3 From 73d34498942692faeafb37377b97d553ea5cb67a Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 25 Sep 2024 22:57:57 -0400 Subject: [PATCH 341/376] fix(aurora): fixed two pydantic validation errors Signed-off-by: cswimr --- aurora/utilities/factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index fcb3f24..bc94f50 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -231,7 +231,7 @@ async def case_factory(interaction: Interaction, moderation: Moderation) -> Embe if moderation.resolved: resolved_user = await moderation.get_resolved_by() if not resolved_user: - resolved_user = PartialUser(id=0, name="Deleted User", discriminator="0") + resolved_user = PartialUser(bot=interaction.client, id=0, username="Deleted User", discriminator="0") embed.add_field( name="Resolve Reason", value=f"Resolved by `{resolved_user.name or 'Deleted User'}` ({resolved_user.id or '0'}) for:\n{box(moderation.resolve_reason)}", -- 2.45.3 From bab80d63448517854fa0c0b53d0958e08280178d Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 26 Aug 2024 15:03:37 -0400 Subject: [PATCH 342/376] chore(pterodactyl): clean up some dirty code --- pterodactyl/pterodactyl.py | 82 +++++++++++++------------------------- 1 file changed, 27 insertions(+), 55 deletions(-) diff --git a/pterodactyl/pterodactyl.py b/pterodactyl/pterodactyl.py index 43396dd..0a7607d 100644 --- a/pterodactyl/pterodactyl.py +++ b/pterodactyl/pterodactyl.py @@ -9,7 +9,7 @@ from pydactyl import PterodactylClient from redbot.core import app_commands, commands from redbot.core.app_commands import Choice from redbot.core.bot import Red -from redbot.core.utils.chat_formatting import box, error, humanize_list +from redbot.core.utils.chat_formatting import bold, box, error, humanize_list from redbot.core.utils.views import ConfirmView from pterodactyl import mcsrvstatus @@ -20,8 +20,9 @@ from pterodactyl.logger import logger class Pterodactyl(commands.Cog): """Pterodactyl allows you to manage your Pterodactyl Panel from Discord.""" - __author__ = ["SeaswimmerTheFsh"] - __version__ = "2.0.0" + __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] + __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" + __version__ = "2.0.1" __documentation__ = "https://seacogs.coastalcommits.com/pterodactyl/" def __init__(self, bot: Red): @@ -39,9 +40,9 @@ class Pterodactyl(commands.Cog): n = "\n" if "\n\n" not in pre_processed else "" text = [ f"{pre_processed}{n}", - f"Cog Version: **{self.__version__}**", - f"Author: {humanize_list(self.__author__)}", - f"Documentation: {self.__documentation__}", + f"{bold('Cog Version:')} [{self.__version__}]({self.__git__})", + f"{bold('Author:')} {humanize_list(self.__author__)}", + f"{bold('Documentation:')} {self.__documentation__}", ] return "\n".join(text) @@ -175,76 +176,47 @@ class Pterodactyl(commands.Cog): async def power(self, ctx: Union[discord.Interaction, commands.Context], action: str, action_ing: str, warning: str = '') -> None: if isinstance(ctx, discord.Interaction): - author = ctx.user - else: - author = ctx.author + ctx = await self.bot.get_context(ctx) current_status = await config.current_status() if current_status == action_ing: - if isinstance(ctx, discord.Interaction): - return await ctx.response.send_message(f"Server is already {action_ing}.", ephemeral=True) - return await ctx.send(f"Server is already {action_ing}.") + return await ctx.send(f"Server is already {action_ing}.", ephemeral=True) if current_status in ["starting", "stopping"] and action != "kill": - if isinstance(ctx, discord.Interaction): - return await ctx.response.send_message("Another power action is already in progress.", ephemeral=True) - return await ctx.send("Another power action is already in progress.") + return await ctx.send("Another power action is already in progress.", ephemeral=True) - view = ConfirmView(author, disable_buttons=True) + view = ConfirmView(ctx.author, disable_buttons=True) - if isinstance(ctx, discord.Interaction): - await ctx.response.send_message(f"{warning}Are you sure you want to {action} the server?", view=view) - else: - message = await ctx.send(f"{warning}Are you sure you want to {action} the server?", view=view) + message = await ctx.send(f"{warning}Are you sure you want to {action} the server?", view=view) await view.wait() if view.result is True: - if isinstance(ctx, discord.Interaction): - await ctx.edit_original_response(content=f"Sending websocket command to {action} server...", view=None) - else: - await message.edit(content=f"Sending websocket command to {action} server...", view=None) + await message.edit(content=f"Sending websocket command to {action} server...", view=None) await self.websocket.send(json.dumps({"event": "set state", "args": [action]})) - if isinstance(ctx, discord.Interaction): - await ctx.edit_original_response(content=f"Server {action_ing}", view=None) - else: - await message.edit(content=f"Server {action_ing}", view=None) + await message.edit(content=f"Server {action_ing}", view=None) else: - if isinstance(ctx, discord.Interaction): - await ctx.edit_original_response(content="Cancelled.", view=None) - else: - await message.edit(content="Cancelled.", view=None) + await message.edit(content="Cancelled.", view=None) async def send_command(self, ctx: Union[discord.Interaction, commands.Context], command: str): channel = self.bot.get_channel(await config.console_channel()) if isinstance(ctx, discord.Interaction): - if channel: - await channel.send(f"Received console command from {ctx.user.id}: {command[:1900]}", allowed_mentions=discord.AllowedMentions.none()) - try: - await self.websocket.send(json.dumps({"event": "send command", "args": [command]})) - await ctx.response.send_message(f"Command sent to server. {box(command, 'json')}", ephemeral=True) - except websockets.exceptions.ConnectionClosed as e: - logger.error("WebSocket connection closed: %s", e) - await ctx.response.send_message(error("WebSocket connection closed.")) - self.task.cancel() - self.retry_counter = 0 - self.task = self.get_task() - else: - if channel: - await channel.send(f"Received console command from {ctx.author.id}: {command[:1900]}", allowed_mentions=discord.AllowedMentions.none()) - try: - await self.websocket.send(json.dumps({"event": "send command", "args": [command]})) - await ctx.send(f"Command sent to server. {box(command, 'json')}") - except websockets.exceptions.ConnectionClosed as e: - logger.error("WebSocket connection closed: %s", e) - await ctx.send(error("WebSocket connection closed.")) - self.task.cancel() - self.retry_counter = 0 - self.task = self.get_task() + ctx = await self.bot.get_context(ctx) + if channel: + await channel.send(f"Received console command from {ctx.author.id}: {command[:1900]}", allowed_mentions=discord.AllowedMentions.none()) + try: + await self.websocket.send(json.dumps({"event": "send command", "args": [command]})) + await ctx.send(f"Command sent to server. {box(command, 'json')}") + except websockets.exceptions.ConnectionClosed as e: + logger.error("WebSocket connection closed: %s", e) + await ctx.send(error("WebSocket connection closed.")) + self.task.cancel() + self.retry_counter = 0 + self.task = self.get_task() @commands.Cog.listener() async def on_red_api_tokens_update(self, service_name: str, api_tokens: Mapping[str,str]): # pylint: disable=unused-argument -- 2.45.3 From 872e1aabffb06de116a8f6be04bcda58b762b2a7 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 26 Aug 2024 17:46:42 -0400 Subject: [PATCH 343/376] fix(pterodactyl): don't depend on a website to host images when i can bundle image files in the cog itself --- pterodactyl/data/unknown.png | Bin 0 -> 66388 bytes pterodactyl/pterodactyl.py | 2 +- pterodactyl/websocket.py | 34 +++++++++++++++++++++++++--------- 3 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 pterodactyl/data/unknown.png diff --git a/pterodactyl/data/unknown.png b/pterodactyl/data/unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..16fe498cc335fa830b465ef4c910215393f74510 GIT binary patch literal 66388 zcmXtA30RD8_nv7bsk9(kP^qaDLK;#kYKmggzS=5kbw+7XQwTdN^yr`Ij@*~#`=r-R`8KXq{TD?JvxcRRY?3= zz=J;-T7AC}|KT}gq_0PsC;pdSnRS^&T1BGi?L6Rn=hi+aVX(lidSb^-=DJlMsERE{|2*$iBnyp+qh{=*0Xr-g!g|H1w=pm-Ev~IQH(2= zbTw++jT8}fUV2uI{(H_VI9K7)+|9I)+{bskaCjv3;!ktq3C;(jK_R?_-lJWQ+(sR$ zSH7QesD8lx-tUsb#|60`|NdAhIMJ9SON-q`$>5ZwF@sqPJhtx>PbRO# z+KP1bq@yB>t%lmQTxUBjwsE?JjfN)b$y}AC(f4?;nXc z_k+$Rry$;3>a)K?9GeZ9EZLq=IT|z0Oe4Lw)8c4)OXqK;;o0$Vz0!V)=dkRGdr9P1 zVPXMYb7P(pvU=66;p8)_d^ni%5$*pjE*)+tH;wn>;+j=&&yO{ZnjA<8LGB zvMh}n%8BhO?%qT<(|j?+HRHeYk4%(Hy){Q*(eL4qY5||+RkAcg;ozN$H2Nt8+9re9 z-}}r?jDEaFe#ClO!W>Y{lNPi|Bd_G}fr$gVu}}IT%EGriuERm^cw9NebavDHzPmYY zC>+yw*R-`~vbcz|&;zM)*jARX52h9HP8QF-*I&8{xVYxn=dwlmm(;8Y)cR=ROp{TY!j=K0Av-b+| zHvQX*9x6=J<;Zk^^*jXiU*q;xDz|;3(#@CcXA7WQuCFa=4Q} zhb?3$AM}!?)oJ0>EIkXR%NrM;cT3aY1OSUMbHO&RCwjc-GjKC3cCMmn_$3 zl)xIEuV6OOi!IRt_U?;{dGAKNj%Qu@y>N`WK61d(x1a&%6(e3#u~nc<$OX@snZK8y z#o7#os>kr;dFn+y#p7=z3T0_Uxm%hY-^C5sDmC6?vN}q5eU~k-{9Us3c$_Saw;v7> zE5{wvP&j?Cm`ZWEAS;*F*skTYm)j@ub^L!0!?*78Kr7o=@21%}?98fcMfg6AIjPaH zbc;SSp`LihYEc-Jy5xezRl-71h1|=HHaT68^RLT5JU_=t5*!RUBtwltle9C4HEtG5 zE*Csc+AVCC4TnrU1>fzvb&p-6?c5!>N)tPyBoA|~U2?&yfb908EN`Qc$@PgW@Aon?hq;7%}j8|4k#K2IQ>Z$WO=TWxMB4`UB*CwL-!Bj zEZe_gjTog11By8-!(^{s(J8uDlBSy+8CV7xO6BchVK-z%yhRP4?i~g-6tBcrqnr$Hr6!T?UrqaFC4}Yt0*~G)&sghHg z9vb`B|NH52-sX3fL7{$OHi!iRii>WMJeD+jc-wa`r7@Y!qM08T>66P~oBDZ!=lCuXrLk=Sg2-HWrJxw?9K|dQac|$HL;|hJ02evRr%9ksxs#;m|ewaJIr#@2S}`iF}x&vz@zQ!S+yHJd!~C z=zv-G$!^1cKbmXbyXnZRSd{XAS$+64hlgMjXOt2UzQH(MbxghcBe7W#Y<8g``82tj zb0hIS*;&U$O}ta`g*)IO+P$QRrvx#y(!tsz{drO}Fa=B!Koho#ug8TdrPc|MLd z5y>Wdm483(nNAuA%nb%G8PZ#bAMc@u<+EqC6ALLwhWf)^-S&<`mn8Axk!) z=ACy+bffU%KBizyzJjzQRgXD=bF%bKOEq6za^b(9#SgM2+4W7UnF$tjU0wsaR5ssv zQs?t=L#C|UgZnYNb64v*aMI{cC_+?i<|!*$H@Ta;`z;O#0G5jwxD&oICN+OXs!$WT z^k1OHWUgvjv|M0Q?L~JaBn`1u3mz4 zPc3VbWke%z;^TM52+Jw#&*YLbO6vF>O#H??cloYZ(G17OXA%_lpD8Zh6uV5-I727m zMSXq8Z#OF|E7q-B@rjAM3=R3@3=>`?|N1%9cKPzeDRBb={D(Tjqs~Zzk?50CKzeQPKJ37v_33$WIk+;@Z zx+`Q}GsmLf>!Z=C!+mv$ycN}cKfX4#GbfCY9-kX%wdep%EcmSbLbGAl|P zkt=!Y-qBa|qC>kB&2wMG$fp{#-#bdN$d|zDKK-5}-oHDt`nB%+a&M&^^Snb?IM=!) z)-1<-e7Lmhp8rqRBo({5STQBbqC?#H3w$YHfhRbn$WmMtSypsgc$%mnJv#q^|AMWn zJTpwlErQMEyDx3mhpy(iu=nvdYZ1*aepjzcm6Zcmup#c zrtekq{p0N$lh)ZhCtmX4xcIANRp-yoFJ!36&E7l8p69e*2tbMgfuyvi@NDPVv{-Tt zg`T0qeb+qCpFNadYTWbXvdLN{B_&4cp%=KIshJ;*R`-r9bO;>hHcC=%|2;iDRG`~W z`{2&!v8YhNBT9Bw8Tq2zd471r7b2%n6aC)wNGd2elP-@2wS_l;@}4|%=4_@ z=G$Grw%P5}x9lwX&E1P*MJd8m6WVbsq-HR%=$doO?tAp;ELF9yw{QsB<>TWs zu$|Hzq|bQq_eZGFJ=PT@1xnH;o@vrz#9@r==FN$hO?F(hE^!@RneEz|OM887^UL~r z{uFu12Z(_&T;zS1=1k7#>!Q|COzOFUdFusWHzWYcmIOI}K4bMvr9wEvlZZuL#ICA? zgBrGe=KuCCM?Zz?Epa!Y>A}fQb!WI2UD}O zR$wwa{Zr%5m&-KTxamVi*{M^frh3n*{<>hL=2Y+a>wEk055*M5HBr^CLYj`XANl0^ zwpD*iOz657${Tup+-K)tI^EPX+bm}(cGH`Czai7}^Ygd4R+l-r`NEAa3pb={23Qum zEKzfAIP$grYW=m%=Wr|$#o{l92Ys{!v*3G(GaUH9c3Gw zQ~lOnSgC${|IOXlvN9tnp?J&5ju!!=m9@E6_kUfmMw|+y$kkjEW9PARkX+?>;c|a6 z_{O-Jws=H|irlp*Xn5G4YV_vzUX8!s?-Qrgm8Vg|8@1+d48Fxna$uqIA~=2#vS*#qG4=^|rFJ}f9bJe*p%Bh?d++sAoqqkE__aUZ_FTYi7|z;GtO{h?kiF;dID>6&7>2F$1w+FC) z>F{d&q;8qw|1F!vnxY(NX@2?gWzSPVtqygUN*wt3#|P_h8jDCF%{&jY0U_G>>w+pd z$sDDy9idS(3K?$;9MTZl&3Da|8g~3W&bLfOf=Z*G`A`+K4YzpsN%+EwKVPrcr)g<1 zm3ZV-oV9=VR_= zm#$tFr_z`Lh2BHvYmINb7-+sJuI9ww75HQC0IKIa?vtE6a9>de*i|ydkbPf!sA+Xe zvjL5kvGXj?-~4-b9jdFGt!S|;H8eEpQ??~H-_%$0pL9W3=o%Xv4=4}1T;R@^r+&9% z3cM`%ASW3o+D+|t&>m;6Ygt0EEL^qB)`N^h#lp6CY}iMCG6nw?*Yw|1P&KW1dF|dq z{S7I&VVM$gnaBWd*>l6`UEpE@eX{AQ9y^EgRBu#Jv9E$XmH(@I~Sg6B+z5V4ip9Anbyxb(r~ z1Z69xfF!jk+f*K4yQ}9(1Ok)3r~Sc+mF`u4);^6Abe-Y0tip0@dXUyvdzS+AWg-+XZNA3)27Ch3*(n}f^Gu0rYnJha?0T1GuR@_pxbW`cfe zzTK;_o~M3)`jQEFXm4-F^~^tz7~t6>(6O2V(^4KD6_RY}6w#7W*nJ~-dXU({E0ss* z`NR~%8&EskJ5O0~Ma!taMpzk${ZvK05+f~n}e6xyG~ISCajNU9v0b)pQA z6MMep6nw2yDq#8l{FZ^5nB7}*j(EBFdPfp&WKoI?S(&4pBR_{Oj5>{JvSN(4`y~5K zf!LniyLphGGHpsvZgTIu@%HUo00`^si-rcLi7ziFN4wIN$m}iz-D;v4o_rMgH+p2v zdyy@>=)uG?MrN5$*EjM@W`6N*wQ_FGvr$)h^nK&Kd-t$gW*i%dX8Fb=3ugcRc7A?d zJi{xY!wJP{8UbWl5{0ZUo|~IZdCo-&?4Ka`Qk$*U;!ow?$mXNgi7dTB$HyG0A#;BA z{)2Kr1u?4r%VRPgB4ej;i++t{Bg4R&n8=*`4BZ4H{^h4f zjltk_ae@gzQO-bHfpp`Jzse3lKg|Xt_WjDy<+ z0H^+mA(CfZGNJ85GdzWBKfh8vE-Nkg8Uo~=^F`+qN)F#iBOKEt4KT;Pjo89?f?WCe za_<2lxvGi2S6;&SY*ZaQYx(fhQS2b9ne86-jyQo7 zae`u!Jy%_X!2VuC8m$M+tpDqE_uINr0;wk;cqjt}drR8vKWAs99;!>AeEH%Vc7Ecm zx}Gz;N(`ts0(L2^OC4L5uHIc~QzvrEFtPWVTYk^;mF{0Gs;6;a8eQTq=%4TOV3uD` z#4^j$lXloc{_*ae-8&plzZa#|){%{3L*&V4L)CPn6gIp=uC#HlOoX|a1ZYA>(k6({ zIn}Bchc9YAhhOUUD|qhZ&F4yr6o_X`!V#ug7y3#mNKy4-6+ephE5u8l*16M=^Z<$XpwUlUM(Bz#rF%Ly-!OVsN>^d~`wVvHm@ zzB+M$-X9Rg5oROW4?gv9AoE-q-oEw6p2oRk*_w+4Te%oAbGFSP3L(MgmvMrAh0!2CUV?z5B7}33^`1zktqrtVvBYWVz1Oy~F6FB(!qE>^5 z$@a(KH#+?a!6$fw1-Gxn^MuM#l%>$LtZX~+JnES;u!Ow#OF z3W1+pbHCJgfc-UT#F|KRNQS8bFk@l&qR%?ra_L6~gldvMl(_xq*P6fDHS<-Sb^A7P z=M<+S&dzGSV~$e3-DK1d5>);1{($a{j&!_Qz>=NVRT~K$~JW-O&|nwcU3#CSl&6{MoajWi>(U4?d0DaC*eHpd7k_ zAS~7L(98L2V_M^-)w*}=EByy#YpU+C^}3Tl2=9$QT1}Z39aU_~_v)0)UFV3$X#pp|TB4+buModpUssQ6*#CW+XMj{sJWk-UyB!BVX(Jy0 zb>zqqk2ibO$D_1n!dh-=3hzZ{p~UI+in(8<)#GnXO^Oajojy01{s6hH0FWkZ7S=?j zpD`ql@XRfS47UF~&B*Ac{zWPNm0Qjmsa7V`*ViM*$__3&;^foEhb>E42j;?ZbtLK`^fZt9i zLo-Z813G!AWH+J^UbC4InxO59%0ETBhSS-Q@8eZa5dppE*_ z7l7msHgR`yx`ImyM?hD4cvEb>K-#7|m9b0L)xoo$rtduK^7hUW3dMd5jkPt%Q5nIr z(;Xg97qhamP#8-1j7&CcAn)TF;Hc-R;_p~fqsgm0`2G`r#R6a9QiHvFZw34wshIwj zQ+(`AxpvgZH9g$47B?m65UyNlot1i402Yq#a zx-&c|5=rGpLCEYmQxnb2j96J3-*KF~Blzzy1R*&_?4jCu^1R@C5vpFSzJO&*Glh?z z{2^Rmzb|B(K2-i$-b1bb%y!;y_GjC}*ABwK^QaU#6IY{v-X1};Y$6K%3XK-dny{uCg@CPwU&zx*zX1D9aO%dq2~Z6eDT z6VdGfOwmo-5#-XEYc(K>w`Q$1Nv$6Z{=E%XCraIQFo?I9w-bd@&Dpnb(;EY%JVP=S zBWDqqEu$aDf(pU9UH+Ho3MOB>R%hj$QbXio;7a4npC7vNl=ElUN7-%c3KZ6Rek|1) z?7u|{ARFnu~`v@Uarfq=^-#p z88xE7fw%#Y=Yu$SwW39SJ@VSlzrTicv!L>l$3VhQ4ds=By2mzA>Ow|2heOSPW|lqc z!drsn4_Pd&_}?r5*);S+*tUd=EiEkr?{b!buiY|Ep%O`t`77J%{@OOX(~_X%M-g~m zzI+MC_OnU0TonSx(G98LDqu6$l!T457h)SBE4Cbe0judEPXBFVHdDjvD*{Y?y>r72 zY{TJIm^r%^+h_`us^Gd1n!VLt?gD7on=BJ)r-mDYzG%7kK7pw8xc;gd!BU_Cy9`M5 zr5UofvBin!DmaW@j&O8u&OG}uk&DV0U{}x2x(gmd1K!gOOo52z^OD=PFk&YfcW2u0 zWpRyMIy26vEO-B0jKJ~J6^0zOlBXq9D<_5FBa8~@)}DE=(0OsSNHQnSzPksqn>6aA zYr={`O(f_o6GErua!#_fS7~}gP3%OeNfg@7Dcg@Q;|YKQR2!e=S*$}`Zr?*dN8-s( zSpVK@UarnOi~S z^S$byoZ-}WUDLH!Eun|Z(jK1bi;BF@U-4oeO-LXsLyP<2SH3i{iE%C(8;M{GD+e`N#e z=(D3$e^qcZtwQNah1(d>2^QO**~R3p8sm$zSUAiyQXvGIf0sgy#2 zHfAo#aRd!0*y>2xFUDify?p^?=h34_H#o9Mkphy2gDtlRk|DVmQzoWL zohcj%bH_4szI1Q*jkvv>M-NpD!5$W z`-1ChB)1i?>1!0o=XqBUZ>A2iF8dDNO5Qq@d;g#N$RU5-ZiYetbz~`Z*F*QU%_kyO zf{NBYQ7aT3jpJO~4O~)y#_@4s-Ek0sU`ABu8~~C zt6Xz`BY4&%d`%NvdHe4UFMg@*S8{W6|9Ls>re2IN!8VA(vwlzGyzzQxp$nF`klyuQ z*(?w%2rirWR!lsMw03l?`!TrPKhUMq|Dwh!o0)iJRpxOJFU=PWT@+dZ43Git#_DU` z@aywUTm><|tS`yt%4WBu&u9YD`R~|0+A>-_zeBy#_b~C4Kl{3#;A3WQEUu&T2!;nP zz(r3>fTj>zwGAAvA(APSA(`FhyFa)U97WxqVVV%I{k@%ME!k+CwS2w6RygaaTBN&w zIrKm_ornn8*)wRX5O##%LfFxHMRRnC93z^sl`mZ2l7Q*jF&^R;xu*)IlLg6J;P1G#c$7gsgwa+ESFWhvCWI=V;Nrbnp@!Z+w-AucQmA(b{~F1A@oH zXSImLz>Iq`HU4?SlUqoO;c^~=i$Bkis9|LNP8XmJN*@}G74 zGN5#vMX)$2B#-dhsINy{oDN+Wr66#5DR2v>f}`i9jlQ7Ee9Po7^!)zL42j}Y;IzE}jooap?P_nj6e+xdt?5En?vJnXe- zY_w?!vs6fNsV(RBh_kL8<)CzgzM(*88T>OvO>}+zo^rSzdAj77Io_59o@Qw6%pv1h z5o-i}>uAFb4T6l*sK*zt*hI8xZUl^gA~6^n!z{vh0JJw?3mr+vP5Ub3#T`_ycF0_()-krXT7SkVJQsZyd@`3rd%N z8#E*l=hO`Nb)+^<60iGWPIBga1s3Lq{GgRczRhW-8#VAELCGQxlA#9#!T*fUadk%! z6@}`NcX!Q*$C3a=Ie1J1k5wNby9=iT-P%geGM3zZQEKo1QUiq?1oe_J&=f}0!N$$; z*LO{N{$#9L&rzFG=7k%Z7cltro)>tVr;tL#Ql+6s1fN*%#4A;-#1IQbXQMuY!s?RpT3{>L{S1u~5tZS(G^ikap>+(sT&^1D}(u($toBJb-gT z5A2Ij3wx>UG$16IihdA5Na=9mf5&Xuf%ouf1+ZbbOROJS@s4O$5+Xm!dpC2`%3!#DCUs^r84lv4>lKHfB#nzRU!Vm}{-#^UeZ}v6Y%!n3fv^)K&=B(fj z1H)KpK3TbB1V_=SK11^Y`^wRupH6oT2ZW%Bn``&zS7?!3aJxa=70XNbmoVmn}5NCO+-ONtDlr29o zhEWY_F1UKz?Ed z;duK!1j)&+zw$RcIG}oE68-yp+jb>ixxSnoLDL=|Pn5=|q)1YCML92R9u6leojDCh z5S3Nb!b)A-tu;W0lUIOcnq`axGk8bYq3VW-)@%aiFTStL3SOQ|_Mc~eW!|j6Pc~wSuFTyJB-ClOJuKqw1HumIw(P7j*PH?#o z&M2se&N!;c4Iy)ZL4+bri8oKpsS5 zOed^K6S}qCqQuo~#U>YR?B4~j;(WuC2l1A1UzWSjtKZmva^NvU36O%OB;Ypz#8q1z z2MxryI@e5x-dx@a>0Qe2%Mv<$=7b96G$FFJ-*+BenFH$b_}jbS#dpWhq0&RcPy1@x9t?@A;@*9Ju89v|NFQFPySqQLw=ruGzL<+hI^{`LJnO1lB z_ovg+P!mE1_$5Cq(k^XU5-SbM3x{ycEv4#csiJ#;_-XntD0@2yuVK+HUxCu)UimZW zBE{m#9n{uDFLj-DaXQ@1K0{9K4)F+1jp+yMI(e2n)rEBhv94`3ndfte+6JX{>n`-C zg`}dV0VPH>iV(H0yH`CNRa6qRwb*C?c@N4c(SwJ^LL@#wofOrGu0nL*H2o*Xj+GXz z;~n6t097n%+@KTnc~7Q(iWBbiv6zbO6;OwWU&9}xu(W>F%!JYI3oB|~#LIyCo}S@w zpcP>1gjgHZ8LB&*x@1*pDy?P13XM~;5cM^Hl!7UlX{BN=JQdPqx*ISI8%2*F;Edtj z{p=3Pe6>?w44}M&ozc&~dijztH<3&*Sb^Z0K@Ys1XdInaYk05jwArPJ&3n_p^BcM+ zMDcnEefJF0$sguIc3a2yLPt~4S~Qd_%5$3oGcyC-M9N#~UV#obQ6tCh-*$TB3!Xgm zVL9G^~>MUYGU{5A}+BeYu`3{ zuv=6I1#LyBI=mK`s9L+{iZ*6Th{ZQR8sBq$%Y`sbUZSEGbWA>F^^z$!*p$IZv@cQN ziK^IcWiVM!3w_5Ap?NeY{q@;{V0KA{jOcZV!bvYQ9ado3)5zayeiKKGw~s#qrX6|# z)s?8!mTz*o6jf;ShlMe$Vz;(9BbA5Y0Ftdvv<)LU1y#Lg7O8ZjhqVBkZ4>d`$Ou1l zkuyo)w#IrX1tF@QmRY60HxjNMm;|v~vXXhOBYM!F@|Og)X4W&}65gWrAWVQJ%q`S{ zU=5MRsDKEm37Ibt{Waudk8NQ|dbRBae-VO%ZT)5_+T71jfrwVRixb=mi#*y<-pRMLjaYcMt*z z3-|CEgPo*Nf4()ny6KoO($ZppA+gs>7`=&vmG5Dg2i2s2Da<+n9PZG@IY2%_K@l{Ncf$!@K=8Q4nT*kfM87@T8|4}HM2ywvPw%BPKezu(w`x(6}2lB!Qv**5-6WU%=rFL3)N(pQETIzc|e z*5FPxH#EEu;N2&A=a7J&c(H}G-5fVbeUS26p?X-kUecMHsvVM3nM@x4~HE+Xn-A|X3IL%M3{KzwdJRns3uH2hCbr*sl23Amuo)juN4lFK=n{xaA9(fIa zAH5{k7Z0y#hQ^L!_AFwk$sk>(`yoH=30di3$Kn||M)dztOOhF{iz_G$7wzhuTtPiW$HYtrXX4zzU%F&V>Y4?ZU* zkUB%=gGMTU+jshYzCbL|u~7a7J8f=KKELvpHQ&<7GE<5=W*1^Xri%W7#s_!7CW*0o zzh%2a6D1T$KS;^U<>LgsgZJ#K3jBjb;vS<*KJe+0dO_u{YbIg|qNW%dt#g>4wjjhT zun49@-MX&ezw1EG`|daHK#yv+irbji95>QAAzl%qD!Kg3XS4b{)+NLs)2Rw(?|XEY z9-sCIU9^0MT(F`Uf#8IfL5oHo|TD%-BZm6t-mw|N=7BLX!-?U0E7~L z{`~nSN^Am`{gWSs!pwQP$eXUPSGxKOh*}rg5P}h#r|CO_&=Nt9m|+sNi9U1U8T#hp znD0R&Aq)HmbJhRSy)kuAmS}7@W#|SK8Xdn=@q0Mo(vrF$0n3;y?lI9$sTH=E`sU=} z?`| z6vj5Muhxy+mt(#TLqA_YfjS6^Pc$jqE5>)@s%qs*NIayE9Hj~vbCkm@o>+SDfY4)y zxrt>X6+ar9#F+w5kxj}lE$cV;r@tL-aAaIQS3*C)p9KOHiBS;Ib=I3efGk#QcGbg? zA;2t5S)(BEmK2HBB1UfvB~Ft{!{dY|zr8z$mda>`nylm#a4Ds0$9>f{a-IOS+p z&gg+5C(muCJl~r_O$3vx7!v;r{eVZ8u_uM)wG+-kh?nUJ?hDENZ{0WF7qG^ZSK4u)DSNaWPM3rIm zZuTs7a6Rz>0o0gFFE7hS87~Rszd=3@o^Z3@Ic-W^Xh4{{ru|*EY1HXXzbHbxrZ9t_ zqaFXk%)+h)|6Ps<=ru>a8vIzQ3eg`?Oi_X7hj}$>CUY-Z8g9H~k~4p?WX8?p6;$oo zFL&n~JA@t4;$mJ}A1U-YzTdP*>I@hc4?UU=fkFLYo zA7jlzVh>P?GhYaCbGb=GugVk^Kg8XBeT|y-s+XgJZ$B!wp7(0_yDjzN(8S$Jod&Zh~6BTSO z9$&-S28$(&0I*o zmedNig>(`d8+*@~LqbVTZWoHqYiiDM_>)|(8RcEe1iTy$N}gdJ4DH*IC-+)tet3^2 zxLWxyYp3YYH@McFK$q&=<=!C9#tQB(|ob z7QX|GuB)#vZXiqKAPW;G=?oav91_(!m%zBisy0wue{$!B4eV3N`f@)BGq~kH+-&PB$+Uh+P<8YQ}x# zna<>1Q&ASSa*{mL+hbN1z<3v-WjUj+)`C&ozOP>usnictZng#RITyg>g5tWBLJA#q z>8yB2j6d4>v>$Dygv#J8IiP09Uy0taX<~-o)(oEbEFjAHROs{_Z zw_9;@OQ>-MTF~iCObrw~d!`3-<|rMz>&+D`p;UOo{R*qSbxE+8xOg`3=PsBpPRQsf z|Aoe=`J!bi#l~b(0t)_5n=oBsmQAn0-fn=aW}hDIJ$cAhn2h(z`+5Szv5gLs}??Xd*YpluMkPp0&oHZi(;P%=#V`MU51 zu}hou>5<;i4xdiFT2~IOH&2aZQ1|+^*+nVM;={E9L!u;Y@jyt=*EGCtW3nOf+BMe{ z&aH++t$E&4V+VsUl#gH$lc$)qENWd{ww1@SVe|f$bvW8PBrAv&Ua`@R@oOB1(RaE} z&?;0r<9+;HUx%)`Wj^?j!cJLYG+;NPyY z$1bui=IM?F1(tf;HuCOiee63Vq*eFgMH9wEH4K)lH{Z7}9RpD`2!F-ie56%+k^JJB z1nE_DsH*Vh>s}6YHieW{0?8H&QdehZvr<}DPnqx+-jH84xR@qUaby*RLX!@fj7Ppc zoWe2n0XV%GjaCZ4V7w*%RJ)Cz5HW!NHrSC&j5*m#5Ygny|GHg_^^yv=38rC4n&V#&CShN=AB)O z< zcdJ&6ogwxCu8RncYr=3NMysN)FFf(=+mnou4#NQ<*y-?j*0x-knLCIQXedc*Wd3|6 zSzg_CIv=g>0ugy*OJX@OQPBa63+zW^VQ}0H?xF)no`mk{(r?@#s@`PTVs2MXV12-4z3lqY#5t=Hm3N!x3{+#1JjWfp&0}^qjfC&REfm? zy?wGt_ZsxCE*X+t*}9;)nLn}T&fPa2zp2QSDvcxAEJ*3LrfHSNjopN;jGxbvDsf%AL3;Fs@d$=>6Tb z$1-G}4;=h;KW%o;>5j+oheIPWGuIGTG5scO4tPZJ2m^l^LR_{&gcK7KJDS3I1$6pq zoU~Rxc&$~|)c!bDzg%Ct)6_C&$M$P7#|pi}yBI^Qd-0`NkKJ~*_RgJQ80XHps^(1K zneA=NhaJ!0VD$87OKJKKpwcbIuG*QqE%m3wIF+}Z^*$IHvEH>QJq)!{9`sgRS=HsV zw1S?eQEo5?V2G5AySPj=<037`DhWUY3B^rb_l}kRnLHT_Z`#1V7q2jAO4|&Cl|_1m zyt5CYMV=|C>*cFgZ@M3!EkS`o+}o=X_b&T$%T&z+0}+Id1SNDuZEKvi<3viY`Xle2 zJ-H&dxu@&Gw*<>XS{(dM44(FgIj%xhAqM4rxk(FRp-tyt{s>LZD_G+$^r351@4McS z((jUR?uGO>dp|;TSVp%Te;E=SYQ|&yhEvgL|W|) zG#nyG4WbwaR`c`ob495S<}3nO`D3{((vlk|daRf}Hhp!ueS{ep558-8I>xu){>)4u zdX&*f7OPkonvo%T$HU=cC1qt>31Sfw69WKvLvMKv0DVGI3j9VZZ=^mk;Rp*&4H(hb zeEfYAm3u6)zv@SVgq!mV2yS`eaoLm96hY zGlV-|29gb-_9=m3`Y=SXV#A?uFl%SH;8;9TgBzw7S5O&uGH>1lw-7mY>=S23@uCS@Jeg=mmVw z;sQ1DUu=>0d_kTDGq48ic*k~4{&S(W4Q#$jE?SzQ;RAv3bLd_igJ&2Te|69hG6s-f zj8yYz3Yj$a5MSsFy|ZvQ8qMAHp)#NpRcSU{5`pnjg?5Z-Y#rq*?(7)R`Sg&l*p~SC z_-RzM4TPzoq^7~n>?NnXyf$M(Cq*-$mCC(-|0AChv%~HorblGuc_Q{p(gdybeI=`J z>M9wv%!?>}dh!)tcD;f6MF6EAfR_Q~!^)XN8oQ8ZQ~C{`L^cEM#g;q{_%)Wsvv|b- zjOh>c1)PRe!fKNpzArGY$fJ}YA~&c@dyVkO#BPyL`%-vTowxVx;f8)|$j!}7#93e? zL2U7jf|uIL!0hyNZ4gF(NE*4OGe<74j?-p5BseNs1XHfdT>$Mm2fuZ}$RoN#Or*1w z4<9~UvGGWBLzOIq)+8b|2&?@9D{7h#Asc4nQayy{vCd z8E3uugnZzkn8Av-4;#Qt#mp zX2|3v$W`ftEJq)RIPtci>0*e=#Rs4AAP^N2 z-tImw$FCTv{8()DASW#kA-xJvg~Ykv)%7kcxCj&k^>Z?Ig*YZDBtqwMK~RHJ6dIGC zoJ5%ov(WABQ@vvya+!<>)|w%qf^OsX?iKPtD&lj=NDJ-dpZtgNz_v*FKHuI_evW*y z`TNWBmFA4RrluY8*&Xl5v?E3ooV4rumJ}hD29=CpZkc8tv4ls=tg}mBB@$m#xP-wX&ZMN%rufHqD08 zoAZxfvX?DYvAqMS`fhqU8+0W!T^teZ)R>y59h$5+mW;2r=wLEUkS*b1z58jWE%klL zr9wRVYP2`clIky=JAeKy_~&ix4Y{O>n6@>=NVIuya1{s@X=jP&=iL|{HU6*ud7`*w z3jm^|g%G#I#5}i~E-y~nq~CIINT~F1sF@F$rb;V+3)C2?`g;;Gi+8JdsH((v-+l1% z>EG4!L|vn8K+G2qmCUs*CtOoF!p#f~V<#piit(`*{3|*kVeMc+>*|xW{_XcxQU=`t ziv%;tvwcYaN0vhSK{hb_e-d|4O5ovwY#5ICF=U@sinb+61bnD%1iFeOe=eiEP>IvBMEW7EIvyvXk%{c?_AGjd#5Vzl zZ1cQphYlYu!Mr4nW{_}T6;Z9U9SSw`_x3(GA~=L+YJrdSRfYsIvYezQA?`}Xpn<%e2me=FK!q+yMShz zE7K9Zde6(n%*lJ+;cf5k?AJwWq3OS(-?tM*PUtixKrd-;P2Z{Li zNYGxDjt{a4ra|00p#^{;mta4QvYQhboz!RR-s@OyRFCN~dvO87x;BG$@0nT~KV%NmPaE&UF&syeb78df;U|Feh2 z>yQL6oaTyL7kU$Pz>Z)j9AtayV=cmeFcQL3mT}s$EAv;e(Klr2~Y|5AjRnBswbXfqPX7<1u*8Jd!l76tso2T0k2?|O>Ge*=1h7hWxhZw+QGtzV-vVb|p z6q~@V^3*Cua#;sxA9HnY#F5R%>l2>^Wv(WQqZ1uv`;j@|x7$bYl|^&P>CR)s33D(= zFa(-U-?QgD7TOXeC~fZVUoIfE-6f^hTh(yINy#1te_?P(A~VTG-}e(LlTG;OXo#Qv z1Ii`}G`%!i4?J;o0-GU1^#D=17xmsMWnE2lhiZ+C%&n-y;@>%m))wRtIODxo5ibAC0sS zp9u`{ugWDb6df>2XJ5N`mJie1I%+FYp7if3)`Qk1_FJ$+u(w(OKm~XZQGHui`j;TX zECfiQo4g+*7IU8q5)u;JBh8bNnK!V7C;`b9=rD|KHdzvwh>L1L&%64MTVtvwzM8#Z zCDTpN8Gyo>eGrEHtLU5=4 z9(yV{1j<;{K(dtwOrt|(Xk=sx-7GORH6Q={2ux?PWXY0NzoT?m219Hv&=o(FdEO+< z46ky7=0XjeD)g4>HrRV@Q#0f`v#LNpq@?4&M!O2&mXaE$o>6OtrVXu+NcJ4Somqyn zyqVX)$J!ylGJp)0&ZN{*6x-;u86wr9s=Hb9?AaZ#cfyZ=OnIoCbI?}Jmp+jA97s@% zk5>pq;a}Mgc0ByP=qYuPM>xS<;YB#i6VyglkdG6*Bir&WzopYNyrV@nu%{2+l%0J? zeew$8QWgf}tnud4BOMwgVEk@v`EWytEc|OA-`*G9ME4T^e8DzofOkP_TCL)|$GUeC zB^`KIYG=@IyFB~KYwM!NZb9oKWXKaAPqi$VxrKpEOww@ctoFIUs>sx_lVL?)xv`N73Op%=l+fk zAu#rzJeg0_VsM=yvy@j`^6pXeV3`%9ajx@eX}4qAVe(!Sv+dO?+NN5at^;B0BnU63ysN6=NWv5=#1w zM2<$V(+o@R$CNt2cqFv2ELc@8%KB#ZxqD zqB2*gq|`2=c{gY@RUV2WgdIhSkOn+u$WHS_NRnMjW}?9mZJEnZh$Q-tb9=x4U+cHl zx4!q`-uG|~=Wv|Id0YYD0b*0#x0I4RN=YzEjIfdoJs2%7FE5p+*XH+{kcY`m5Nh9E zr2SrowFjR!Kv}vVVuJxh$m)sm8*NXlc`ib4E+KQ^etIF6C|$oq7ADfSCc5zS;^So? z-e%0_zmOtq@vkjUXhYZNX*3Ysw!C^P)v?I*{o$A-cQfA5;wxFv`7sIJd0g%)#FxqY z_g^3ziT>hNu$O@FBrF6(HDlXwEC5Nn%F4=i3xho5!4cp!Aw)Wg)?wgp>Ao0Uq_Y$C zbag2fSpVe}3p}th_H(MXO@5!%F7Hy$^p3QqeY>c;O?vb}> zXm`$uB6ejip$EtRe9I4iz}*uwdPe~q8G8IrQ<0lQBFY0J^PaA`v}pVA%L%2^I2D^w z1ZxGspjXy(wq9Yp?s?B7q4o=NCx`98XN>|l4;QkoJiIQMUt55tnIVu8;AkcTM*E6n{v?8I(qj6WS!2G?IJjeN%nq?7#rn--4`8unccAq6*{^TucMaHik=MeK`zJU z6oSqCu5phd7Vr`DEB1i!*FND-p9DHC7alw~T;1)^-`@`)?LU+(^RfOZt?k?(*8CKJ z@|m+|+bV+RlMz)=R8&?~%?I`ihwRDa#tubtSc~qPLmPeP-iL_2n9Br39fy|H+|xT*KHCBhO)uT(W!|MfEt#7 zHr5W_^8#^niz38FF32s-Fx&0$B(yst^2#dvf*f# z1bdY3(ol^Tp1922%PSL+g$(M$y9Hs2P`V=^p>01db%o)d(X@3~TYLCVs8sSP6k<2S z4O5^DRO7m(M0Ej5zKh|dX%`#Kp6!Qicpht_SGVnKYQ?J`c~kZ~)pS}mP=?G!A*=vY zZ8F4^2hj6k#Fwmwvl};iLkWTLkl{JwrkeNQ#5|E_Af_kp+t&t4)?+V82aA}VbcDsN z=%>IWm0-TG5~r^@IBK6GD=IDE?C8qww*y-T^tMhsKW0}WI_OWMHNJ@ge*!!Jp}>k( zR>9rfoAY(AZx#QOlIT6)7codq!olioH{{Kt3;+;4YLyRZg&9 zOXg1++*JDK8Q=^BvgTN7faC*7H|VNyH9k!F8~SeNfw~+Ln|Q*R#cBZnF#}D=kP5(* zq;Y|Mt-mN8_a4FkUhwyHW8Vk&N_9#GW5n9?(*Ed)v$YN)!9-UBa`a=~z~8|!2}iLB zueZGoyqmcoL7_GCSd4TWA2G+!jm6t?y#oh+|NAnM1FSs)kpgI~nG^^TjS$hw>YNvz zKhsPORXw!S?HsNVPHFSjnhKsB(&NLokInt>g|hl&#B1naY=!?(3(#7P`>6+ z@>LkhUL}4m`F$YcUWf+Iy2S4XOuqWr58@$vLr}DE(_6%lmw6TW$Q3!=_AB*fr0@3%{`pb1|KP{};* z71WkqwN$oZM;TCN@_w|V-`+d!4OeOYOFC74!i4fG!>>)%Tctb9VNuDo2+#{LE5(2Q zDF${>gwT(CKfyxeWny-z=45&VKG@cKAhPe_SoRO+@U;4RHf={IS1U&^&9<4CM5ocWb zkFHC*%lgt3ec#l$!ie?6aL=XmovXo~BezQ5k(ii>iwmuOe{=6uvVo5P9piGNlW_GD z^gES9_6cmo_3egzdr+W8WICUmGoC?+Ga5m%@g*8Bu7y4*Ovh9YM(iQC48=ua6ff zV(pb3WW(A(1ZNJ?(q}MMdnm$0D)RtEHPc?DL1I}&543q>T7owM`yvP$>*AbCf38&8 zoUL{HJG_JJSw~mn)yG&3YF;(g+*`d(Ez{)UD}~DtuEN?2LkQ4;5_c(_rC&Zz;RklQHBzj$x`4<{6@1NNAJ6_H?L{ujz|ddS-Wxyq`@xnZa`gP#h!tO&QV8KVp< zd-LHmIn#1pkJkH`Udi(J9p%S?#$o6OuR+_&6YV@Xb2dG&6th|n*A{_R(Hf{@V7wJU z`F4fg#kZetk7Ec*0~U zZRA%MnW!(Id`_*keS{DM%POuMX$Vzt5&M+7^Ief*w`1YrWv78~^TO-p{k{*A8jD3r zCb9fGl$QasaK-Kg+TCRU;s)?-BOexhGi)+C=?Ec#xhSf!_uFIFO% z{0nc?7F^=0w9B95w@pr1uQ#eHwJ#0+0kT>{R6(KwD&pGO`qH(M#o#=?1OL_wU28~A z9Dee5j%fu;2oQ`s&2P2Ma1aGkwb0t8nn<4@pBszbb)0ARdG0v%nYy+wT zWXc|+$2&BKnGp7<;^ZHgH?vw{lU#Vr&FFzr8ap;DM|i)Xkl@@_3tzC71 zJJc>;|E5Wq?XI`z4Bj~*L6q>4zj#I5OSnAB*#)3y+zB+ef=HT&nicR$^Cu`vG|5aB zrR_wmuamp_N&z_)BOVgi6EgUI@%AE6o9-RkC!>R%(nQs*ac!8_yLFB_+m=tzC?%?gaM&zdzRSB(?=v4M!| z1$QoGzhFVn+U>voDOQp9p!5zHHjS^8l+;j@={6M8>@QrOzkb5K;hl~>`i4!G4bD_m z#xiI@m_&V&Y<->tkuI06zcT|F379c@??K7(h>k|peoi+kBBPi8yZisR0KT=cU>gP{ zr(CtoJ!x{=X->Vfcj2%#YXC#>YVr1=Ll_R!i3V>Xp^k@>;(`CC%zQmIjcL ztsuzztBy)|+%@uNqgRtA7g6B=YS|U*L?zPzT7)B-Z6Di5kx?%#9Y;r?p|`WGw+Ddm z^Q3mu*_h;xs`RRM%iNOMGl_jOdztc|ZROj*jWRwUjdV z81XrL`0BqtHi#18D?@GNNX)M*PE$0Mtq2!DWqLqrI`B};K$k^q-wE0W?3KJz+B!Ng z29xe)GCN9;By9#sHPV-9EpMV4;_e-75Fq>j#4ksupnVOvsbCQ z6Jl9;AcSCUJV38O6i@~yfi-%=YH9VLNmuo$*3LTNh-!FO<>GSYA5wOWO*~Nj?Sbz&}&;ld_Yjc<} z$tZhZtUV#g1M{Pb!e;^K*v~CROnyK?j;+t6nytF8Dac8$M)+?%eCa<4_D9`w6<8k# zFtav}64DVA|2Y!R(4#`tZG;oXXdS2!RGNiUpJKlXidI60LzTT8s}8hcHB@!Z;nlQQ z@|>qmoyy)SrbhFJJ~Vju{g7F0MF<*%b?xHjreIpVWCaL9=Uf=|U^J%-AeO$P|CES0 z-6|C+DM}Lu5_H3K`%hcGCF+Tg5_FEdcdJa^i%nX1bUF)2Ugcd* z3VGjlDUJ>jzjs+zhVy74WJK?Yu?wq?37O*Mwh0c*5gveFe_KSzID30y&@ZgmJn-W% zD;E&)<~vN-+KTb{4mQyKFA=^A^ z$3`D{4`{n~z#P(Y?R|EMFnTp}KxjZ{jSz(srx@SU<)@1ueXSCk8Y%qpL z|KD!CfK25y(o)}*Je`n`km*RyV2@C%IuMOQy`Mg>iE4R@Ofwp!4}+})x6D1rz1uFY z_xhTU%I*siEoec!(__q&+g+u77!bY5j5VE)EJb+Uz&G>ZcW~pp=bL*c_lokSAQ6nl ze(+lvduMT}h||q~ov(#EKbdHF)3Q+p@p3+tQ~h0ChkHd!01tSh*QW{#8^q-$6wUwq zqAo9Gegj4U%5)OFveirc{j&+sKYUmXi%cGAdO6B$#29Ti42TMFOXhBE*J^rwK5y2` zraq%pBvJzl@eS|-T>E{JV?k|7BD|~aGNPJgIYO#8!LtDH2FKl;l$_k1eUG2~AaQI; zM0FTPS?|3*aA{XGzAfGUdjM9pymG5tJ@p9bRj5*F~5nf6i-|W zck^?Pf0g6)MIt4|x_VeuO+>(X^oWg_=}-&OQX>!1CySKyuj|^kCsj#9qZH2e z8E!V$D^N>q{I#me!j)8^FlK6PeSD+4>k7nZuA02=WxPemOArkD`mE$FA3P#dU47|O zP0I1a9r@?EpW5ZEuK}8kY8MKKf=xG`F{2G%av9)d(%14O6VdJBj)jG7mflbie6>W8 zKUGiwWz-EPPhNz^rHq(eS$ofo9-QJbAxMwa6QS`!8THw$7-5EmR;IETVgE_waln(H zdptmn#h$`Zcnk^~mT(9NSPw>q?~SnaV{f#j6|o(LXW>5k(i?BAo_7FMNeHj?$}-)< z#_1>m_@9Cg#ee2`pnDN`{56=3v#29uhaCi`=vHqhf6u{J?{+q2Tk+NnE6lvWe>0Ca z7BTucDgnz@dn{YVCG-ooSl&3(HoXFG+yGFBN%+zZa0!wVVkJV18R z)fLmvGsa$X0T=qM*P4#`FdZp8D*Rs2=84{}$6{+E!Kp zC^7-1>dS!tMWmA_E~`d;NhnB2rlCOUqtCNf3lbW6hApQ&VZz#+7s{z~Q#uPpCN&@5 z_E`mFR!?+cV^7B=3aL2h$VtBYTf~vGLz~<=7fuS*&qtuBh4pLX+u5^ z{(Ide*r`_LwrVJlL5ol;&a3994bQ<3l+<#Ys(x)+^u2>$}Ocog6>nOs&WI9}W zfBHWqNl}Ct4F{h}=9u$}ChwWiHt+uBEgQ>xCDfMzOM=NcdzT|qIV9b8Y;Z6Z9=jbQ zd}?C%`Nj)fyzUc*g`sKu@KLd~MkZ z&V*(Y?unXqOa7(onY?h5Jzf9KqdxJ<5!J}U$O16X%Ta78L|FoxTJj)167GS<-r5AC zdj9E}vv>QF_m=-zC!0U2Vu7zj>^yXyM}It*`cI~CU9<8dgF7x) zr@g!WSpz1aTnO;@GcFuwGoElV)#Z?V;U>xQY3gUs-C~K9d{66PJ5(>#l;ewy;oFqd z*|MlAJ0rsK(-&1{-Ug(O_zFEhcX`{9{89Ma2?SHUP*FWb@7&qc!J~)7*{Qxq-*^FP z@dB)hWfCXxHt-}D`PZ@>MpJg`RP~rzN%c>CFRsEg8Ba&bj!OZiN;lsQ&z{Ol&Yb=T zdr7c*L>bje;?js#JECjnk(cNowK>!Ht2;1C6Uz7PT#>|G*Djy7UYtEwFY2c6SfHBj z0NSwuBIQ?W*|Ge|`$#bjToj?&r6Lc)I{N4{Wu(iJ8Y-Dulvd;C;COdzki`nt(f^?R z5b$^7nS@}Tas3`R%YEuMF4*%-k?s`0>B8IS35vx`^#VlhAaV<~(BO+!DUp(7+62`a z+s%dET7nAn{nImKI$5M|6LUi^3uOUGo%8a!)mQ_1(@!Km2*`fn3d4wzss(9ZBzji_i~A$Pnux93rbGw9r3oDoxnTHR=HBFd+{yWh z;NqU8&}daj(do-1Hy*{&b_wHVSxMOM^mIS-x^5Ld*CY3!6hY8JdNc>c4K5J`~E+Fz0Dl?`rdAINfNZ zsd8cb_jf#)*W&J$7-?PD#1!v0nPf5Fu&Jpj474IFm*n_q6@8&Y1JiusNAc#N*swAO z6s9R4tv6k}=DV_bX$iNY%V6ac-qhKZ&yC6D0q(%NG)1EBjS*)9{Aooc1b=l6$TeIm zZx&!{VoYKX)YL!e%l=@DUBulj%U|?u;LRO9!3w~mMDN4={g__~^X-3X@&5;JqQ<&5 zhc9+nFJsJG#a&xCZSL3>26=!`Jy7?i7k!T&e$1$uIGfRZkC+ICfp3g|6O#5-3)qp@rFH*rd~{@Q@1FLx}0UvEBNSld+w z!bv3m(tdCki->46mQmkPKEecrLL^`a+~=^I7aO+fURF-kmri)esykz^urV>q4HY`T zO?hxbU}b8p!{Yw8tM2!I@$DNW`~_Smy8}f2hvryaj5xC!{ppve_XFq;Vj1f*$4It8oV~omAy_RaF+%3Wy2Sn<({j*JTVPTxM90}2A;{&@#?OCN@DP}s zA5q(Y?f^gHog6u)s;GDh?8h`!Ek>6Gg5^+s#s%I+oB{9-cqeMAb6#W76rnTNS|aO? zUz+Wo(f^uz1$iE9ohf_or4OmX#)_S|4ckD&2kY}WcY-OvQj~~BLSMIUykLCHV*SM0 zmhouPxYH-inBG@GniyTCg2+5TPf`vflW}R0vK3|0SJ%gSfdqwKM)*HeOpqlO0S5?w`n_8wVvL66x648u z7uI^sfe$>KlCxV#g|ilo326oX7tg@Euqb=Li^p^~O7$wuy5wXsA!zH|#QBD!)XkS* z4&mH6AuJ~+gxhK0@N8|_za3#o*QL4rPp_6i&@$noc`Zr_X#WE)$D5}XbW*oELtSzo zc$ovAy8=-Itit*z-`J&`&?99#mp8O|g02%l++a+(+;s5Cz2INkAWNLGZ5W7cm*2&K zk3t>Lr@ZQ~?hga(O+X>mxH(V*fuohJb_BTqhU?xqt2lFv#?PVQuRm-DL{E+n8j$LL zxy2VDwVtp(fVyVwW9zdSi z)e?A?KL^n~O!1szz%Wh=7q(W0YR%o<**kQ-No3O9D@Hp(|8x>~MFz<@xOOPSAsRLr z>IYV_ZCdBhcTNNh01ocBge{W4W5*@uS^%K%Jonu6XdU1wMBhZj&y zJC9qVOzWk!X*KhSxJHN^mkY{AXi@}bI5sF_(JrnMYxewpe*BU-@4P3nj*e?+{!xX< zo;rU-I)ya%0w}G5mHIsDLfxMc;-~@cbsl&`MIcD2?DUuAmEu&JVk&|HXm2-+JP0aT zbr;eV?dgeq<%^eVGKYl!1#|mZ%#>0 zMo)F!=V!+TKWcT1xvYi=Dx%=4Q1x{HDPsdp+QExt?41!vd^(L}_|}k5Z-w~+MyzqS zS*$@IPEv96^jWSWYo2xNOb4%ggT!kusMPxz!GKTgh4I#y|V3cjJQ7+ z>tP7RV1Rb9&%x5dyK%9=>4p4Q#XEkVkgwmyE030Gc{yYYz7)y;3=`Xm_)ab0WFsgK z289h(g?>l#ea0UkA zml`CREUht^G6kqSex+4`RzDEmo*=<#RI$~JBO(PZV6Uw9aWwfZ)5N5FEx#EAHUKs$ zNY)3@ZB$fHaQ%Om*T()Euwq`<0<~m6$qP>1#Sw<+Dj@3%@i*#oU?k6=?TNZJ1#Okm z{-==&({3P~6m<_zO!KCPC%;)`q^sPPko_)QG87W)8IDuYh>y+8Azqhk`4S^AUeCHP zar&slQ660*023(?G(*Az=Zmrx5an@MBrA`vO*^Y6RIk^(Zwqf6buvv#O=x?%l0gN#^<$izKcm+R5LDMHf?mA?>v;KyGKKE5- zi$!phwZz$Z?LhAS*x)CzI4S1qx5q2dtifx-PDAK8=!=>!JJN0DM?JCSW5X)M*<-th zi`_z5+6=?_0ghb{RA!M8-CDZobp{fG&;3U)FHF2J$lChDM=#(jd$wJ0Tzqq~Q%sw+VR(hmq9z-Ev06?O_Pv%9xxjpt7Kz01Y;`|ul zy9d(Jas{ySESZ}J-RqHxH2(C?qtEIU#r2|(5l0f81A&gZ$RwVHfXmKbk?IrQX6JTJ zb55%16v0Gi!ZE#@b>-(i)KxfN%bBEWLHsbN1F z%wXKp9~LbA=(zOt`-Md7spCn2h0Zem`oTa=WYYODnQkyA%8H7i@Usj@6G!&^M?|V# z*;pIoCqPqPzuCmhgEGh_l@sZUj+l;s;H8zRiKQ2N3o?|sf1zv zN%_!SjsrCRo>~g=?6H$KxMeIlvchq>M$oy*FW>%BaUO%OtqlgDi3n#HQ4$x2Vc5o$ zzrOV<`Apn8pG?N{V087~{V$y3ZEUE*jjb!No=e2Bq}@T{A=)hp%64#L@G#@;?L=SJ zO=jxPBM)pVYI5c0c^DL);l9lK`RYuZ=jzG3yz|nI9Rp0kFud1Pz5|xM%UiMth1V&y z!s?S?65hXm-#&JYvR0v|kJZJhC+RQNZ{1fs3$NPw8D)xgco2YKQ;1sR!u09HE()CZ zIPZ7k8QBV_-`s7@C)Z-AKYa)1BMj%lpu%++Wz~YMTRzv z3m)aJV7=yjd$D^$_=iW80)|O^Gm^;2-3ZhTr%rufd9}2`iWkn6*Qr*D{Wln8%5{YyqiX^-~J3B99I#)S|Sa`xEqmf ziA<{$EB91FXd~3VcE;@ZFC+Z4#}gryrxMP4x?a&|tpD(63aVy{A$U^d67K*EDI4i) zN`-meLMQCf^e;Es9cyaSkN5gvdWebsx32sC43UlA(jVGHBn;i7sDYdqafWwczQ07m?Zzv#& z+2uDQ%cG8a+~cT_mov*XZ*Wdm=;GOU<`xim!v1n$PND?72IGm<I!E) zx1&NT64hA>Tb9vmo&>R!Is^ql5@tR0D-<4E6N&dvTu1*}IX&3imRdEO|xRg#oPNq6=5xy|T;by`Y1DGG~c9UlA+` z^=ZP@>g5B@rFC2 zj-;=;=J7zt>#M?_&2f4E`lXJBfsD*WMIWsv3+RXtJVXbWW%u`aJQ0!t>J^=3+_JZj zD^j8mxLy(%77O7bQfBO!jp)FPfZiB2@#9f+1|BhwQK(oj>YtgAYfr=MBu0y=_(?iz z&A!xlVLptAW+O4#0M#MSy$9loB4}37V+6z_sSxlr%lEoCTUmF8k&le-wrO}b^E*(! zXoYUzWS=uoQm`T{9>E>KZfTI+g8L2EHauT_r5Xu~EbE}&T_KT4csB`)b+3}B86CY$ z9r#%js&jtu-k~{sFW0oA8ulkA{vQ`W<%eq4GENg5fE++9L1_dxu%R}J^h1YEA%;e6 zKOaSfVhF;);o8W-4H|0aa`mUbFm8IjfStDeYW8+dX=;W*m7YeX?=n8FH`%!CJ^(nd zWkQKq8zaoobY8g7gSrHF`6+Ly^kAWbsOGtxssJS7Jx5p_4Hk4bOd0rKm8f?NylVkC zY$MtCbgPBcwcs^)w+%!sM;vHCJVh}ph~?(t!xa$ELl zWaa0(r;3X{5A3(rPq0zYG}yUg?+$76)?n8YA-x_?+)_$CE37wfxf~F&rR|B)zy`OJ zC%Hk&O<;k@FF7!ErHKZ8%8@w?$ZYKac4V)yh75ukZ1e<3A!MdnLZg z{#p`kY_Zs?>)z-vh0*vhS2sVuVw@@KMAEU&VSr{m^Cq6VGHL=w~Z};G`%i5A@6@rZ*iL0ef zRa7j2{`x7bljRy>gTfEJZMv(6*NrZ>P;z^#bW^nbNZQ@hNzNfP-`u=*V}=^9A|M+; zXYhYtq{|3xK&xG^8q>``bIaCJYWJa-1L;vUi>32;AwxIg5tHOVWV(F{o)oth?yTm^ zP2-G1heGkBqcr?AZ;nQk;A;*6b1~9+Sv6O-XXBGkhUvm7zr9EMBN86wieX(}BT6{7 z7|@RnOXV;xKO=M=%1F1JscTzUC4zBQOHGkk{Bx!Gnf~ zO?Hcz`GWZ6iS5d`?FN*EN@=K|DA4Z8IYi8hF>}8ih>>N)-wCT<>We-ucXO$vVTC$B z7q5|2cl78uqL;Uz<+1b>lm87;zGoyP9G653rRJR9V)-oXG^CjJxMViAz|tejF|e>m z-v+>xIcWfn6%gADI4=z`^Sl(38b@@u@h>w6PK1Ytw}OZ7>E-3?(4Q;IYRVttzfYAr zwjn`A{}N=Oe#*$;U6T=ipTdSs!?6DV+4gGy;~0d*q2`_Tr^L5QcDl3kjVsKp-Z9Qk z@x0uX$b+Dyc$^CTrr(h%XuED5quagA@1x0R@7WBRp!48GhS0eVGenA|Zl;E&KPcy1}qsGd-aEU6dn zjdt$*;oN$}EG zC_{MR*Ua#zMvJ7z%x;qyXH+p*ULm3yaQ%rHylo_a=VBz;f>caNa~XAm&`DHS>;6e= zc$My>-Dh|N<(wI4D2zIYcS~3aXs-tCLZtUXk4QUoXaHksWMT2xQkqfC{U`E6`c)5g zt-VvPiDDpa6=lT-If!0RTth1k;p8e$yhD1F;zFQ=NCx-k_Z z#>phhy$NeKavTvHNi=hl*kT};2t^(mlrz%}(0)yot<)Fx!KP7bP2QJ0TGns6fZlLi zCg|@Fxiz3tq%{Bf;VGff&;?~<%!HyvQ?qpnpWis)uFRekxsjvyFXlM^JfuV@o&o}L zCRNycDjNQt;jARAxmX+=t|P>H+x{c|f4|s(4R~T3keLV2h$u))Q|L9|=-^G-(Y&}C z3vc&*d2_GNOWF!Q{k$ofDdL}v2LyVlGA?$)evbps;&0oYy}dC#+K-VoK%6gy5vQk)5HF!D%!HoE={Y# z?-cyZ)LKz?oU!b>Tt-HQPqUEr1F$@a@FtiiVcu1>4N=@v+;qi}iaHJU(wO1%iIP_@ zzHQ%o7=N_XqZS5PJaBYVWgU+j7}IN9F(|)N1cd*( z7)lZqiCIZ=fl!C-Ae0+&{eTv=o4^=a@xmrITlOXh7uV?|XuLes6u8P$h_TV82E@9b zchg+)b1z2-I^REb52{iVc1 zCf5jS_igsotzXp53;!!xE1@Fhb=dqNQXd6-SRPVW2!nnfJ&ihUrU#)^qsGL&!*RoH zR9_5@9pxYy8ZQj%s=EVYOTAy|-hDYRf@iBVY;NBlYi=8_ER!9E?X&FyXcolA1GSlM zNUY@PINq3?A6`FM_}0OPpLpTMg{-(UgA%GbFsf%!Sn;8z0W@5!z>+JX-WR;jhqGdG z?y{H7(OKFZMPc$<$M|bPD zpKD#RdAU4kcgW3wRR=H1Fm`tUw^2XFP2<6K+UXEZ!2&;^NkSsP9@x!&x#ck)N^JR_ zM+Z#-r1b44K`soL0H9LRocL$3*}4aZe`a98NbP!gGj&Ojy`mU`t-ci1fY^CxStp`m z46a1)UlFwl_piPY)l@iAWNI|qeP(_s3F z7F+$ao7EX9@~ey=fs_1NfX=p|K^}9cpynW{VezZ@%FmwBCDZi!b@rIK24U-)61SA} z4mXJf;z*MFXv`7NH}DJfXYo3Vbk7YB&kCGeF?cXR#6JP=A3>rYndh$lAU+;Ws$074 z=j(P?hVzMc@%-_TtKKptXM2CzWs8S$aIrCcEJEB~q~2bO7VV2s*IWU|F$0R`OW`2# zI~#>(^F-^|F#~NH?1ivOsM!cQ5aHH14?}!rE7+qJj9L*6Les=&^d*AAP=Je!3=Aq# zyJrlz1f82E*&Vi*fsZnM1TazXEr|(ckN_T~Vc81bot-ec{-Ei^ibwIvLMB$Qb{haG z_5dUlX!RJ_+$M4b#ZZ{p0#%J2ItzpBK~c~s!7^vEAE4wtuyevNXZc4*NxJIKP{$Q4 z9gcg*m`ojd{!Ba{Z#4I}KE|`r2lfqZ86_mWOFzM#+OXiT3T<}2lT-iMo$|d+?-PCM z(%E&(Fh)y@ii-zs1^#gZ=c^J6q6vosqOPd>ckkUl0jl;>%N?q1TU2c)Ry5dcfdS~` zBFV(L3e#>qIcP@bB$D|=u#`Wtj4^9JJ*v1_BS_eI+^WS`Kz<*dURaFP3894luxg^B zC}n}d6ZOlc3Nuw@7$J#9Z_4OkPVws^h zqAipB&jC%O(PX2sQtntv%gus%O3VN8LJb(X8RWa%LL@Rn7h+p-VjlrSB<1Uy#=7am zw?G7MUvoYSQbgREnwAhooDvvLAx=RAl%r!r zO>^-ZsEFS{vizYW;Ic1r(NY-gWtg@9aA`P7SJbgekC3Vnbug&VuD6$9n2^`#*l5QY z!2&cCpXwi3F9tL*1F;t(GA3k~N&UfcW%f!n@qS$sOB5euFwYOLiai1X*3iw7uZ97; zx5SYMSb;VRTlCBuM7?yY-{DQF2>U>1TrqY5Eraz~1_bnX9+9!JHGe7lX1DqYUa}|| z+N9Gsxxkki%RK%3BIw3Q)u;)qGegFv0kiW;_I+%8n{A+qkK{aL?daMGp`|w1Nc$0R zl%bleFHI`w+^sl~B<9VLmH2N?HDdNXL=z5;U37-K;zr1b=c82%5dcgV-8qk7=*i`bpMD;DXRX1fH)kr)Xh-b zMKT>lou@sdRR)iV={0K>&D2?xrW-XlXJMxy+`oB01ONi4oi4R$!$)VW{8tS%hI`cNO#PwlQ#jRVNZ6JK2Zn@o0loH&cS`DE4M?cimZ%an z^n=adL$WV)YpCMpqpyJ#Z^Ofut(M*x9K$u-s1?m=I)sqYgObzn+lQli)oeO}IRA#G zP6zto5tT9nK@(2sOit6w^Ud!YckMS;jsYb(L{6ob2>YKJ6;bc$CC(vR=CaP1+p3*! z^{}*NnEMsbhOxtmc}X#{nrq-esR^VP-LdCk*UGN>YCE_c(mPk-@?yr`U)X=U_Ku(H zi>?@i$Bh(f3OpT&7vbImZ0A>w>#+&1Lm?^^KEgj7f#Kg+QgaRA>?9upg-*IykuG*R z!#&+@Si9>yOib%a#OO89@m7`8>eMotRlI!f@^(NMIpg*a=RjzzBo77zR^A${biIeY*I{uuR=OAA^It zGqW)0Y1Cv++EP^Zla^D36FQ6a%_Y4^2O;KO$mD}MVK~IN#65P@_Fy~#GMpZi(jt$x zf}QlIlUh+P5YLxqG;Qg1ro7G&0s4Q222wU7E34PRdgve&HG|2Spzr)1`n4x@Nr>1e z>FT*QnIBxO!Arr(_NC;Ub z3J+{eR1GKqi(pBBkj-8}E6I+xx_cCiCxM92E|2k5r?g&nRNjOc;ox~bo(h)2& zbsb!mVz1<}L%KA5OlvXX0P^iHjNursLaN-r`L^KLQj8zN8JfOw2;S<%c+?MYR`WA1 zvJXEDRL_|0gF6urT$_$Xb0>}64M1+mewav_eC(&gw4b0gaSCknTiB^gzJ0v%=~v4r zU>SS{KE?pD44-BuWFna4$X6c1xU9kh72M$VNmL><7HeLqS1thMnl%~}7u`pj$2T+u zKCu*+n+7M?hN5FD&RWH~WD<-leB7YLhAEwO9i7MM=yLyLF4<-Ix%Ml`lwf+{Ga2TE z@fyz zoRXqiw4uGjgj8UX8}W1Ec^S^gxTD1|pPkY?f;Dg--c6*nF*tGt5nnDXuL&cAyGbZm zKqkki9W-#x^q8!2k(9b`TjCc%Rxo zds7?m4nm?pjR`r469IE#q)lIB8!^oD?~rC&O6szBnmsB5fFkms(Nl>3YmY)* zx~Qn=Oe)_(h&7T1B3M!uTxBm3VO~5|_q(FvGPi&KEyV&3LFD)lg_AN==*U1M7*d+k zcXZC*ccx^1WN`n;iP{~eIMr?*n$0?h(n@Q$nlFi&aFnDXM->%!)odCG*99dt^@}uf zz|n}^{mF)s3fhdj0KW_T;uKEO?^pWPEg++iAUG|rM)#Ps7-3T*W8<@AWo$iMT~DIz zV`)r`Y|hoE)Y*o&bf&@~7KglniOKm?KI;SE)@MirW19&}r+w4Rs7FAej`E*pQOz23 zv8zo!f8iM<7Uv&4aLd{B<_JN-ys#2zFbe89vb@S^cg^RM;sKQX$R^35(Q);oArkotzW5@v5nCbQgMs0w z0k*{~+IzCn*xM&eB)1xQ0mlv4z{dciOVGoDZ*iE=M%pK2c+ByWU|<0_JQ*hcO=rb8_>>6Sxe88bH!M#HaK|A z-0i4t;SQoNX^2q!f%n}?n0RgN z9IPhC|JwrSnuT#@lFnihdnE%rGIaOMoVbwU0KN%SQv`KIS$-9&a{s?wAYN2#A^Fy3 zigTw%kYKFGLQj?QnNVgFDK-%(gp<)=aT&D`jN8q>|N-;ksdjf#s4a(84Li!29ry#&pD9ykRWPMh)P zqg%FJzP7;N{|y>GRlwbzF6W2;Pu0N?1e(AggKGzibXm|$uiZr!Wuw}Z5YbuQ@e#j~ z(Y7}v%48foNM3`lt;A0CSf^?$VNe0;N*1UqP)Wn`cS!@W2~i$G^Z+-sKF6p-*cTJA zZn}>`;6<~jN+Bj_Ee==i+%>N3Au0rV!mXzJD~sJVK(rOOVKl9MC1C7s^FFofpqy#c?DeC2T1tnimh- zv=5L^y```wtLDY7f536fqcS9BIaYM(4jm=-L4K|XqxpwUWGxLu3#s@CLM%sy-&$v6 zW&$i@_*&6Y1R(858O?A8|A8V+jHu0as6kIhdmHM@v|?gqaW4lw!=J@h=Dj1nHFiBG z!Og>iOYPImHp0$MP7jd$o}!a7X|%@MXYnP)ymST96|gG0>4@Tss;Yp2D0m?9$8plR z(9uU;%fzbT-ief-0_UL6%f=Q&9`6zz&3R~ViU4m}(AtlAoAZefP5Ig+sS-y@LgcJT z7#(f;uqRR^;s)u8lmGKqd=VtEl-aFXB*Y{g$7wih2OHt=$7k{~AsqmyogNMJbcash ze>|htoFkvTGa9SoCt2A8{iWY>(r;M^HvjHVTu zge_|JS6ku?>8iM&>uwq|Hm%4gzZ|iPf6WdHD+CFHAV2;V^$B)!NOl^k)B?pwy5TgW zYn`r-j|c-O=;Z{<-OIJWJ z$VzW~St-zgg4*o0u5w#Yx*^q|HtKl7)yHu)m+h8^>-DB2DxZhYGuijSC&W_F(G<$w z{^uv@2>dT~<|Em+_|l}^S`K`qUi#sStCXE5W!${!G}*uUzNL8FCmgVL9~4e-O&tUe z2!$Ehac?AEszg%VoR@`e0yg@DJpfz8K&b<+gH|KBC$t)M8HDeJ8-)1oVBDeBOZ!^@SHeMkpG=wJk$V`5@3h_`VtmJ1@W(X(Mi zq7b65)TmFvrQK#L4p$H2efLo#CTWM@6_$WkT?MJ_PctQ%q)RC1`a1M!Pprs|mqJ_} zvh%%hqb*nc_}l)*h#XN5AD6^bBVSFC-O^w$ z$=F0wz*8SY1G@}N6H>Yc=4T@uy8C?SfC}3|*R$C=A57KUd)p61H%N?;3Vxw2%4pUIif)p9dl2G;fxb^6z=_$BZz77zTqac<4wF$N zY_{bPs!cm3d~WTzPB=T-aJ>H(N*J4s{M#LMtMpaazq-{LRSES?I);Na*$$jBf|%&d z9d{zmAV$+|(J*ffif5tQ8bv%WQ4u^Tk6HRO}HmAzU zT#UWTs#1l!5beLhY6e@~S01K1aTM{R&{o)zLxn z2uc!WYFt+_hIg{2#`3RcnDdH+#xK+jOs2bJtDv-`wJ0d(8_RsIi4*?fab@UkK((cz zJRRaW3$z5WL$re9FTr>;NvCuQF_9~fs$!Jn0RiJwgIp3(hOy%upyIY${5fZZ3qsNl z0r3fTwcuon7}3~9jg6fr1rY~kR&s3qIrYMfs$Y%PCFQ&#xs=YU*F=H2-NgaNH!!a! zVCgr%I_N+{B&Pzia^q0+2f?*zsf&ZPWc|~T>|PaBvF!(ciG}nI;Ui~IZ!|D8gxXM&-{r3^WprDEotHNH+N9LQQBlH-+_8^OFRqn!`3SjK zHv-x4jp`IB|4uXN`DHWz>!ZhMWqVob(7AVV!%iar11q1u86{B6ZsQN`i+8#$o~_^w?qcdoh)sG8sszS=WR=)k8dY2!>PdY%oX?xMoJ+)<6$ zYTp<9hDXYU-4}e}lp3LCb!B#(_j|_q31(%Kn2O75;EbM{_wN^ZA$HxjhBw8*LGohx zIgzRoJY@yi8nFJ{h*e3!gdJ-8QbqB>MZ2U+v^B15)oQ2!T@juGK_u`qYB1B`C7M+8 zg_q*+7n=D~Xb_f=vS+(Rudl)|*6*49=7ef?%ju$Mf7G%_0ZZa<7P?&9)^3^NLOZO_#| z#tf(9-{-YHSOLI~4Hmnx<{yu&5q74klDdv4!*8X|RebGwz|=kebPevJMWt=4%6}Ag zNng4|?Zs_l;4;{yF0Gd~uEiO@UrG%@`m|T&tBGYQ`vMAa`6!6p_*048LFQC@0YW4X z=}9UVXG0J`oG1ZU{M8T89$l)#TW)e?Sdfm|>8i<2z1`i3=S-{!;Z_UQKk!>9Knvu4 zh5g?MU@n?z>PG{szgI0lIYX*MCvCLdF}?o#h{hw&Ac_%8IVXj*5OI)7ncxc=`sX!& zcQUeirk_}2c*t;)grJ0i>8u|8(A!-8Azs`Xr$3G<(TVkR%yBOeYdEhyOuMLVAP{QnYIKPg-0UJ9yoWR#NT;po7?UO4?cSn~vz4cM( z82Q~bB6z$fGzn;|?plusLOZ)xIJ5UcD&O;Unw8XR#rcyf!j-y@*u^~~Q4ZR4Mhk;p z6jPNMlFGtt`ogX;1#h4l%*%dDgQ!{wT-uBd$aAQqXrcr zs}Y9~t(ZnXA{{%(fs+zVLTrGVROF&?^^v@ zO_8@gPfA_ll~?Xn6J`{~cD;L1 zOiT$HKFQf-I^6~Cu#nSC)`0{QI-+cqm6>^(8e;K8xIcGoh3^`YdT+(rU04q4Rx?kM z%==%&2j!c1Su(e6=i<4eC8O03o9i=C+Hk&py>z7b_5SCTrQg|Mi0lmXK zVJ22y%*#%@W^52wto@R_l~pkDjn!U>!qz)36x?Z|n(VrxMpKP-HkpZKlKcT_-ICj5 z77Awh=zi-zY#>dTzDc>G4IcLH@?KwGImiVr4gIu@zz zHR%&cAF`^ZJ<#8?K(N#*QS_pxFiEpNffCh+sufD;eP;@y7ql2vm@jyDA2~h@*h(tN z;!mp%j&?$_cm{9d`hKrLg?|vSnJ}eHckDIn9?)MzKv}dblK_aTjjLBk7eDoxkkCa zPnDM#SO?k$Pse0PKH7@6tPR4cH?XZHMYrlsEe%?};O9?;o6uROZ7jF`gB7+;fEl40 zk^ygfgd;9+HC(sdO{kC6rr~G4v%e}<-bwpz|5Ylqa_+REQGVJ|;yWqw7z`lphG?}7 zWt}t{L^JDLHF>J*=Utel71Sw5(-cxh#Q^*-bG_&PIowthYoBeo&B4~Z0;r5Yb_W}8 z%As_nl(ne8GPy5d58wweE2hPnRa2iV9+&c2bH9`Cgq?2}NupjkDOm)4X9#%(rM>J2 zs1HS>fd!Gp`2}uaRmZ1$Sqr~b3lwY0Bm`UBx9Ouht|mOjq}(^#`~% znn4u09hwBb%io~vLlSpPNPlCcQAH}tSN_yn7s<|k!E-r-@a_On%Kc0VO;i@E-+Ia* zG8ZNao4tLaz^;L%XAAflz*mUI)!vYHv8FRTU-heRzh4H(e3?$_n}S>Anh<@K-Vw)R z?*R%0|Gf0}I39c3j|%q(UaYwxgX8LE;_S!YV4tDz!`OKIe&=9K{btArmk5jyOs&Ev zE49i+X5On(I}FK?h61s_`|z^stx*1{ghSLTh~a=(R#nQ za`PAVc&&8ZHF>J>2;-<>5JsM^?Z`A)>aF6iFKkuz<230|+;b+*k)jofKZ8$5 zR8uE*X*_qJGA^DyK`Wixq4)cWd2OocjJ41GCB}^R_#bY8tK;$!;DZdKBGaie&F8_t z^ozw5{_Mq3e|t!R?|*h7@aXJ~Ca*nTg*^Y=c#7w%T{v@e`Aa{1si1a44z~Z;?2u;N z<=2MnyQ318q%-X?T1N%}-&45}p})2J z5A)Kvo1!*r1QwN*p%{Ob;&=Sv8>7&lTbu0f|9yN@F)w6~dxBaR);}y~O>DV_a@1Jg zZ|GA2UGky=EuL*+B*}g0Q**>wmJ3xY3fVhsocJ>&v8ttjz$uPOvx-7 zbRx=lC^8S38f3~CrGbtnQjxiV299J*A&NLnS7;&>DN1E(pi+|Rd-l=)`#!(l{oQ+c z-~H}k?X}ll>sil=uZqwg(OdJ}xJ8yF5xRF>cLR7_3De2He!84l9^8(=r7t8)L@`TI zS!2U+?}``)#q{fD#|{%s0{6!7E2heO6{~k?bGoOfvBr;ZIzpq@dE(SON<#Rcn%|K~ z9;A#Jxw~hP%o`FES>&n)3_uHHyyoEZ9MqTTt->3$MdV) z)2jLH!=q6#GtGGo&0hxgg(2bSkhS&IQnS;|gcbcxaRQF(M7rW*6%eMZh;|p^O2SV_ z77Pbc!=oTS|4PD}h*Qb6KBI5aXFDe^X&M{V|BP@TaeV&MK5l-%q@+4EZ|r=HeO8g4 zs(D2H?acoFEx*Fhs#&~Ne_Sdov?CEmNHUh+Nj*P{BkxEpl1#kAT($qOFr02?KolSh zOde+!s(I9${G!54zh7FD{9&pZ>-1IzR}=)_xT*5mb9#LotNeu8`@$4QuhL&f zfTzJ0o(ewd@;{!Fk{*t$zk7JI36Gd|j=`9D3o^=U8w1JAo{pdxJO^Pd;w;2>ik}(c z;5vXTeZ3LEo_)Q7TTp>+^3Yw%v1drak7za#5B+hg|D>kh2~_O49?EB#ywFu>_y7=d(A)nJQyo8xNsi`v50l6I zLzL0bA%4er&R!JmI}qs(R38i`!rM)}!1ytKiMt{ZEC+jgXS0z5d@P0nql_LVS83(t z(Bxei@U0*|UWAm)=AE~&PLIH7u|eDR*CD}OD>0cF7M)&<+oB-UH* zelNYW%Zhgv^(?P>c3j12r&iFaHH#RYZ_ZxswR}1A0x&DqP)Nj0i66teqyP}G`y1+q zk6N%kD$aEkS~0iM+AC_I-`NP^I?%juh(U&*?EOEgY?hj7Xk1qKfn&5qR6!jpEfix& zibvvJobm4nlxlkTunoM*MP6FIjC-1b=J0G}%Lbjp3AmQ^tJr94HQ>sVsb-|v8A%B5 zVs@<0av%^^^-~2Li#gAVjK=QatiNtVBhPTl2$B_?t3&gmwM_sSiF-P-2Ge-Ck>h7nsI!L>8yv?0bG@sQ=h6gEH8eOB5 zaGiGwpGUkKEBQ?Ii}^0aT>)6{PRsF(1nbSRYe;wy#42f-4>CwTHl>H8X4|1c6E7}y zPqRQVB0c;G)BIA+63ofZl&lv8{2X+UQi-H(;g7wO3esA|sD@|v0 z1~G1HBD3KlFCfBi^5EDxe%6X0CYpZ$~F{kb`Li%A$&d*UQgt zc=cz6rnqx}LLl^=(%OwY;qPJ(6rOy(z%MI8IIqSH9nop0PADiTnU!q~)#gpL*AU7W zxAOd5W5@GW&bch^jC92RuL(8WA_ju@{W=pdt!~BnUPipnuAAI~^lt?b!Ui1xwIlQu zIH@g9oJYAwQn(f}{53ma=c2RkM)@q6wGUoC{i{^OhPU8W4XBi%?%=&%Zl}n&MxUu{FvmH$UOee~Gep{f?19O) z7QkKn4V4S9!*lwIXvPOTMT({;J37Y>rvTUF|K)ANKW#E)6V7j5?#Z+|7g?fse1|Q0 zLFEVnVkMZMN#(q^1P27KUez>%FYBD%5R`7dv93_IA(Dc6k?|RssYQ(BSI}?EkuTH+ z(D(m_^oGb^vs6G%*nw4**kSpEarPN zkR7Y~?+J%8SyjqHgTO;6}fn_=?}s}n%dN+-`5 zX&oeH0k_-0JS-EKw&XF>SnVgoJjJ^5^M*YjEwOiW1eAib*fTRXH+MIFg}H1?VZMqP zOYbHoo7?~!r%3~VmZZ+Z|DHv1RVzu5-8|MD&9W;ty6XxYkVEp>EA-c9e{uapu=C#? zttSlT@KaK#jB)3(sbvA=J>bZCY}qDKopSih)vMb2@ZkUJuf`9Mi<^Mug3RZogq_m0 z8H)rQlQ>r(c)k$$ab(>7TTr(_0M(wf=GPj$-uiAA3q|$b$lAd7HeWu!1?$w>))qR| zo{WsEjEPzs5fPj8;~k7R9u}bXm1a=xn)>R5gD1=d+NrGB(Cf{}-5^*xo_hrq%|Td{ z;8^13hkpOZ8gFG9*C^ORO(&{S#m=~lA?v%a(L%6`e1TGrgyli-Wx)sIG&kAQH8w8K zShe&!Ykn}}b|Q&-@aTMaOUzXybT7Or^oKofswj6ejr9~=(XMrza?#01BPoH`&q3Kr_5f^EB7r`NM z#|IBGSJ(lKk??N^Cc!1iD?54E(_tVoFDYbJ1$R6H(jq%C2n47D0Z2|7eVGWeujR2h zZys}5V}&no@M6_VHf_eE2v(U*A{NP~4KoS5#H6}*nzAxVQE^91g;~p%p&8Mm$O#`L zVWml73=IQ;i~e|j4ijxOR@XIIq~+|Gqx~9Iic2&D0e*@>zSb z<~Ua?u7i9zA@zyWmi#9Mo77O;%kJXvcjn>$EIR`jw_6B7L2t#`uYVH_8Xa4m7fxR& z5&dxI{ba=@rs*QeE-LEnY9<$awRE;fZXG){vfMKGH_CkAMl`mOA%DH$5q`&9Yjx?j41bftuq`{S>FY7AI1r3)fNnk4HB4NXi0 zU^!yxaG$8C* zwsV2WG=M`P{?YxdiPT-ZCv88$DODiSg)+rz&L{d)5=gVDX$U!8?@d^lt#h@*wMVph z<^Y$f`fhtq5*meBdlx_kMwTpTv|tNr3@!yIxLKm(gY2y6A8pU1N^2v;OPNf$4Wt$= ztTz)MbJD6x11u#j?u0pLRi$TNj(p1@T6?7!ZQt>P`&$W@A$;!5668@%V0qX(3$VS+ z&Pw|DNhsaej5AfJ=<^M6XK6-KG3@Q@@6tD9>)=TR){B0mOuR?NWgLd(N!@oO!CZ;% z++C5`8kei0?Zu^_`rgdR&URW5%n+{o#~$6^v6H5X9vq>y|IioSD}iQV;=vy%1cy_z zGOrWra27R!Txr1PMnMI;_1(vDQ8er{tqV^-{DWlC#a>+Y9TFY!~2?Nb`&9L6GSIwlk>354#i7Q7HSV3{ly=t$CP8N@CtmsyQdwq z>xkK%>*V&o4zC4k9Wv_{G38&phirY!I-kd*_dPZ4f9tBcEz1Uu9FNW?QOpKz@bH{A=`2U_-JZp{Z|{U};H3Dlz3=qN``S z`G&IPuezX6S@%3ebW{1b8$g%ROD^pWi0L*l+rlSQ^zf^M)&i#73&I=pe+A3-4V>Tc zGv)Wr%b)*EC@e=_JBHT&zIv+jd`8koAXM%_<4($o@|C?Ejupz3PYDV4=U^Pc0>i&B z=cMv-369svrL-slEU*;drT$|IRnwiZ*2+?)*B%)5^y1MUZ&R$bgSx8zJ(`KCj#}HE zm*Ua;R6#SdEwhA*)XSvD)`c6-azhrXhu9(_qHUMXpJyWrQI09E9K>&d9zyKWC8yUw znm@uB^LDuvd91(`D5T-$TZ1DiJ)6xo+@}T%P0YU(mvDav4#KxMaua#$$0_>pd~@Pr z;70M;MM@RQzEd%MSrTkf0jC3)>69}=k|tyV^9vrFGdPFQ82c#PTi^{3H_;K;fEJ;i--;XGIC`b<0qn=2X9GM1*$B&)cN;FHCG38P)uyDQ z+^$Fu&rM9@QVYW#P^IJXbr=Q&^pURVDgE#3KBR_Q4tC3>nF2_(qI@WW&wa&O|+z8w$|GarS9IX$N! zc5m1Y*Hzd76q$u3f?!wQfIv*Zh_ZE(-_G=MgjNXU7R+CsbYr$tRw}? zm<2f|bOR-tK)4OHVQ*R8SSuY_jb`)d)$P zS{CRUZkn8$+)3G+zhN$V?5e}AGci+WK-P8>0U+OP%+u_)71x2iKDjDtcerWG zG0K0C+88{0T|~UYf0RoT)dEy(vbzOgD9k5?+H+obvWUOrc!IfzP|;u+rAi&G!t-2( zN{eH#LMOLoe&d5P%M(G<0X2LiNU#=am^?nZKuZUY!+K=l#;>fQkzkbs0pg&JuG?Dt z#s#HQ!Yx{AXw!}*m_suSI*7PY$Cz>cOAx++Vw^jnAqk? zR;9bTs>QJybq+FNf=?b@wz<1dIRyAqXPg}RY-=Znl|n`HRw+rIM{41N%z+>C$gG_T zMi{|uPw|gfq5HHTY;id}q#9G0BcHq#xDxQFp54EH|KtpJ`eV+?Z=eNC@)VjK3~jK> zR(Rc$m_7|}o<>>8r>J?_*tpl;g~c`?+?|l?`&rXvTqt^aiVi+C03YIUZ`V}VaxY|4p=OAFu zC(fOd$x60=cH+h#vs+T7E%hnfF?5#H{(I&z6ip5j<=-GcJVW#=Q$F7`<;Hh2KiFnB zzfnXm6TUs%m}wH)3X>|jb}{H+Kq@yUE6KiTr1@6)8+MwC--|u&HE<; z#NShRxt7V4Zy4vBnj`;BU8v~W*PT7@@Np!Ky)G(yvr z#$0HgIj(`n?N$%k+|KSlp#UC)9(YSRrB9SrkYmW94iMc(%po;gy|e9-{T1^czqQbz zI}a#}SIIKv^5Fwn2gkdzs_Idm{H88|2^RjT>lD)*rda|XBP zQeNiBmxto>A1!+tF}|-#3m{p^1*fgqoI}#wH)tXgO-NGpaP-@+I-r3eqR;;VqJ#t%>6@6Dm!53p=9!&(bmvp=b{bkiXh{NeSNPL)lX_hHIr1y- zqA=jxtfX)mN~N)x?^pCFy@Gp){rHN&4dCDQ-Yg~>qgWf9c>mPr1|c{0xniAon&bPQ z;>14URO5m%PiN~|-d^EM`_gJ>9SQ+5@ev-U*7~oyqwD2;aSyu^69UNOF|hNZlqhF% ze@l45OYkcHjPyd<4-+%rCVc*)wr%39l4Eq%RUBbYkPo-@@s6qt^rAcztfLpBetoZP z(|Z+mUUI#3*M;I9cG~qnqWyCjN#Q7i3JRse6B84YZTo@o_8cH=>z$qFWy$qZ-QCl?<=*>7d8|gYRuyIp&s|Ufr znmpqL247Y$ha<{9{IKmfpY(wyKDu*9?`p4Y;Rkyz@B6LFGx^C0&!JSl+#!iPsJKV# z8yEGw?iY5T3l)8^p}O&@9iz|eLMGn?ZWqUS#*_VV;?f}%HO+h$DT-F9G1sKkQ&p?? z3b+ZUn#2m@l5_{i$;mD_98fwNxgY798cZW)Z|+a-m;MWHEL zkWw^xB0G?(a z3)Y^FWQ-Z%VbA0J6o*s4*)H6mX4(DjJ71=OW-;u;m3mX2SyG??^uw~ev%6J*^gm{0 z(`efhg45VI?eT2q4ps4f)4{Nv0;+0i90bfrJ*r9FqH+sp5nmLl>vb5vv>-yMyw@Q; zjN2Hb$+s^dVZFub)l~Q-xBg#MbnO<%lpX|t>hSp5Q6aCr;Rg#65@&3!`^etM z_b|sOHH=FY8b)UQQy62Dg0q1L&TMPFB)AuFk?!6-*LU6E#{-SFbmxZB<-?j@m-}br zP9QbP2fiTaxmA;WTlN&!rWGT1Xa58lT#nthVokPujAFBFf$OR@C#QMxxrZLNk_0?^ z3bLa&HO#83x4_(;^1@xGd|OA$h|0|(A!cu6nlQeySfXE?aUu9&*2)YxkH@=eAQh?a zp&xxat||g=a@4AM=WoGC9p;+0J7&Tuxq|seU%oJj?cWe96Ris>uK9aDTruMvGn~Iy zQH>lRmIj~(vhBXPYf}1>cmFy+3x~q49YR|vzs&F&>JGib{mUEqoX2^}=UXt@P5y21 z2={1W3Pu-)Oj|#Xkv-Tef3TrUs$aP1D80E7&KiA$E*>JCXwnd&Vl6p1suP?B^5*p) z>~(mf>!tX#j{OQ}KnXbOp90B&fDwadN-MgChAsx~-Wwv?tUO*@$o`QdZ~t4WGHtqJ^cj7^Pr9 zQkcP8N#(`(*gB}tF=UZSWMzLoLtP@&ZXCPlFfE-?u-&*(7BaV^#==^W z<6-7}Yn6Upy8d#?5i=L!j_{m#o` zslPD8D1Ombyq!UaI>9g~Gx?<&pxd4zQiW0&v$L|N?~&AvX_Y^iOiQoLqe6xs_s@vx zUMGp?cb-_zuEhaV3PbATY%ARuSZijy%`f4N zEt&~8U{<>*mW z)TsE1sq0$c6%u~1C1t1AKRZx4%5m_cKDtu+rdG%6Vrtv^vbw9=X;2}f$6A77> z>n!2i22I0$8eNxthrUvcX$B1-@&jqIA>eB%1LHl$VL3^n!P?+r-EBsUUT^iP@sCM&gY-RU`5+3Qp(3A9zm={D~}xh>axsmFx$UZuPTSI%t=t^-~A z_tsa)BOsfSNMeO14|JXKWd4{>c$~J~Lo7l$%kUhI_)g*`ASFl1O_y9dITjXQ*5STDppnfR>=Iz!Kr0=7p*0>0eMZz7)x~q2#FSBR0yJk1;~h=RpRDznbRxeyy3F zDNuw>`F=as*4st2MmUr9VP;qMIyiZ~Ap7uPlYQ^sIvhpE+ZLXPjgfk0T{~U`BIVq; z&-d#C0V@Hr4vdM`g2r~?lY$>47}*b>Rs=Xn@AHZ+s|4h*1xqJ^} zI+|r0H84*OuLIAkt{21ibg)T*O8gIp77R29G*t`iZ1@e7sEY;ryRJvRh^|+D!7*wH zjOF*gz-+}UK#Ys76nUO=P|_e;ub#0}>fF9RyRaIb0wK!zd7&JOKE+Q37N4m@<~Os} zOL#%9;E2q`jW!e&&&|l3D#xI{A(xB{KKvZJa_=BMK~u9udsg6c>ja|tst#|7Lz*0M zp#oIc=$Dse`tY=LE7=QeK-%Vzy?{~I`e}Wg#vhHd`onvClKz4!AET3FRPJqM@H?C& zaD$ynlGjx=M`veqWWS%%4c!zTf30ht?GKM#LRSk?F_TS?IA;&7TE;Zq@cxOBs5cN} z6G#N(U3P56P!i@bilk&|&S_j5OjBpS>7U_ka1LxM%7UHLbEdJrP4IG^LHIWvs9_VL zU6q^0mVG$3ETh#&uU^$*s*svP9-r;d-steSYYzZ%hUZcMSx>x6hHZKzGURlBzD=3D zmtJ#|4pGT}9BEq-!nKXqK*`+S-LL%!G${SAZmvXRVH1!aJZWxR56=g=<+_F5n~O~j zp=z2-Q6KTzUvO%tm$HRjkAv4UsGsXNM|3vb75?9`#F=&#wKD5TOow(%HGWf4Z1PX;g7qPPS3%HoBmNxD%C@ zEnhxLj4Bv^O^N#^dU@L=HwM_%NBTe9Jh0oKfNqM|o@)~{jWw6fSbt+oG9)1U;I&sc zZcQjw$p7nn8rr2@~~;#M@zY}xmPu9lngk)0P~)hye&ES9lj z9;(0gz;?psBDM~xx}gguFT^CRAjB{2I2wUF581npkoUBE_VygYlAnRwiVfhrHt}W= zHGf;711Ch z;N36$Bms3Im43lRE}fO#xR~xMT4k&f_!FC6#}cpY z2S7UL=BQ&y%@+%vd7INXGCyP)Jk-XWb7W-g7j_7oG{o5|ri*IGy8tor1=AUCN}~-C z>mfc*h{RDVn|Heov^uEY!}#70_aD%1@b8(%Eo*ey1fx?bdhGQvsTJBhdqa}U7TsVX zq`vTj_VHF9)p}L$X+mn=r`MccI_wc1r&14|KKPbs2oG)f=xVKjUgjP}=MfaR1utk5 zq$+#6{jOI6os`0CBaZrO`Gbx2drs{3_ywcE;j9sT#X;bUwh!MD;u&m;od8wBfSL-Z zRGHe`6C<^ew#5Ci4zUL?c*lXy$~f=Rmv!L%{L`&kJ?QzeX@~${e#;^R$gH`SNEK z3!SAUQ2%&_998LnpYJDvK5>zJ&b&Jya;M14CZl z?w4{neuUcr5j;9JWqrpbF|GJk8yD{jDOSuQa7AA2j{e2d_1>wlskZ~8xY)ZfwSSI7 z))hlDFZb{``%^VE%MM@l5HYQVOk;=5xTs3)c)pQT&ZmYy*SR63$TPI-+Bi(ywJ<)ojxOP?m=)|@34amT|#2*y~(IG|1IB=D<-UvTJd~e`FKlTV7Zjr?x0KnG119woio&D$^{%_RA93xJ_`zdOQCIU~y ztCnI;0+8QA67#}8cBT=3Gm!=VvMmj>klwu(Kxw^*wBIW1Gi=GfzXOzqcJW!Vz6zGk z(PeyQH~AxS@*45BJV=C8*nL^vk?1f8lkWn&6*a#;Rb#BXy}1sCfBR?TGk;P&SP`r8 z_guLq`f2@AU4X|UfpB>ajn3OADs3d(+EyrzI|OWl0<$S0i?ty11wm)Iwzdxiw^Ds* zEBPxg#iQawBG7NgqP};;!ZJ1{v*ZvDaR_U7@mUO`6AP2L={!wKg=rk$gR#D3agTB| zBAxh9Vlf?7)=4;fdD0u0hPVvTRtwjjoRO71SjOiogyS(OI}*cOE)yx>EBZm|O!nY# zgVH%IIEiti7Ef3;?(5(F&0P!@h7K&z7O?*VfNE@IWfh)K@OV?toSv-y8Oq5@rJPh+ zOh!ypj*)#7IkNH5yEbNwxx^0ocHmXi4|mAW>)!nhDN{2=_DV72OuqKVq-u-$Ce$rf zXvCdL7q^`2KrX{h&=-8-Ta&yT*22am?=qtqM6UfPZNRBY6o z2*FhFb_R7AcJvdxB&Oju4?|qe(4`^bE0;SJ;M493eq1At(rreOvP4|f@A1!8++oQ| zD&GRS0VWp%F8J^oi;Lo{sD+_5$$t)HR9SXcN=J%47t+ zc#N!z668;9IZR^W3Mc3s3yUs|S(o^#B*tFW?NcA9i!3)B-?)>KLBsi15Dmy=PgQS1 zFSzNwA<4XsPmMyoB{zVirS?sXkTllj74bG}23y-+-eTCge&tUu_tS~_!7gJn4s4j? z1^2QZU@#wW(IfW9Do2D5uDP&SQ&0#w53n_!9IuEk6Va8NHy0DPQs!v#GEX}%wc(Wh z8Tb6UsusgV*@J*L&p9JOkmB!e43)?$DJd~cuGI2(CXdHl=d2r^7gLUiBW`d<=r);| znNqIhzNdC|O+z1z0FxFxrk=#|jTWjr_-A2~I6rzsy|Y*Q6$NRyN{F_3}MR z&Q?}*pa_L2W-?JrR(>co3c;%uPUNNq`%50%&KtO9jQ7XF5RrU&L)D`@&FeW5?2L(TcVZC?nr7C1*i-;@A*gyx@NWb2^BHzxHnPb z19>F;1k~B7Q#$$raQ1uQoFlFd{QA|1g=e*-u6VtwU!krS-0#z>sQvUJ(IA`oCvl4= zUNvN$_cm$j&(vVq&cf-_jEFk8E*jr9q~vT*m9}78Lc_%Oh$(M|VPe0+mG3dF+AMaF zK0IHs;5G=mGky7b%oR~i_V++`QU#xU6)N33mu+1ap3qXSeO`ZfcX(XtfK(}`ar*)- z!LeQ8aV_=m=RAbR)dX1*mt3A2U51Tv2G~H6%wO)TfM#kGlNLIm@=UwO-pe;6 zw&lSy@$0aP29T>lbP^|!cxvEuC63omk-5_)P>8BG%|4&>@yEH0CFw$yiyjj3hY}-I z+5yhahFRMp29Y50Op5j3&$3Ljf%*(RmcxBB;oO1<`mjQ&B?e~=_i2AenG!M1M+e(@ zG9+oUem$2kyrN7nlCxNt8oQYx(!+^RNE=pou^c`xvdyUeJe!gI&Au|o9faFW@VE!? zZfEkWRrl>q9{j9?L%~X@QUa#-xK&42MTc@k_gJT4;?Aw z%7F2vIztLKa@kbk9U;ED<`ovf!F&uh>^R$NFEp5j7I6+-EicWU`#oa0`LMzkT4mmc ze|a@7rYk;_-oX+TiYT%QG@w5aojVBfWNn;aU}eimNqr?Pc!N(Brhl zevC2*`TETO#*+90$N_lvJ}jtNa4>zvRdYLBz>86-xL?Zqux3mGw;ZqfVFq-6@#UDi zf6)kRfl=3p5^!s9L`q#%V08*Yto3jyAT+5w30SnfX5C9>b z5ZQhZNgJgrunf-E)MOIN6gIPV@T(ehGkugB!R^M!INQ0&EoPQIEdHK>7Z?ILkV zeCp~TANvd9#_tb9MnMjU<^8HgWl}H0Ttf$29zJF_8>aNoz0bp+b^;gEQ;1QO{{Alg zK1D(C8F@VulOU7IbAJ|o|O8At(bc*i^Z_{B-V9dS_Le!5pac`Zqlee zhGkg+-yY0~-J|}8r%Buf6vm7=j1sh;&FGo$6&N1J35Hk>6bcPf@{hjCRmZJCfA^11 z4@uY+E|{5F@+{l5pWu0&r{zU~n)M>y%N31o_qYz+Cp~nQWDmYxDbE&X|ArgqI_?KX z0BK$ahvsttS;!@^U<6D5PHV&DrWE|T&#V$Tzm2{<^S>QU%?_f&2!w~@Tx$5!+{JfC}<>&~v+9&iRF z%~Aj`4F&w3c+$wODDNQPhd)2|{mnpn6G-r8X5~DnlpdS@L}oa6k@7Z}upvk8%O{dbl*dUtP|7=l#rdyrKe~SAG1anh?TeJ% znZu?Nea>mV8SXn?gIg~fE}e-t;&pL&Uy)pN`+)!eF_QxDG?;mfcU&3vO7_(rG1i9r zqP4bLSJEQ+hVLI!ae(FN`|`$8>>CC&Q?}{!ebpxv9I}wZ1Ng~YQlJLgz5lmkfrw?y z(U{O?+2m^p=gc_|p3R69(Otzf?ic{B;35DL1XR>o;=U4+lWKy^4;;lj9L1z0H#*>P znI=wIbyUS$OGr(54AL|p)zY(Tj%vEygtySaw^2G2${>3AL zZ`+=F(;{XiOMh9v`~lm;*eO?=j&QZ$MTooVL`HyXH|~mW5trYBdw-l2P7F5a1c}dC z8pxwRKOgTKKY6~uRXSu72S@PsQu21C&hUc#&8@Z-9UEgAzE3Ys&u|Nyf?&Z& zi5jAskikCiM!vySsTcp|IlovIXIFEqJmx}m6fiLfVc`o$&-^NBmbEwwMX?>%x2ISK zy5197OmgaUKo>}6#(!|Y+=J^4tFTs;-4r99ZKU9!k9Bm37Sx*}CDV0*|JOUseJmW; z{ax2}sy_{$Rbidt;84Qd=P(EmwKo5EtY1p;#Sqto^J>{5Why%VHh)SNWkUM-;wqCV zj;Ov3I%jJ%fR#KXUT0~0T18XS2f=kD@1!Qln_a~Y>sL^G!8|V$B7?}eT>gCQz=k&d zd4f{27;;OuJwHJ%Utrt{d$L-HY+yD_HR9_ars$V1dT+DKhgXHjYOQ1%+m1qhk^_}` zM7a?htF5fpBxLny8BCI9!{ln*`A? zQ({SenHQp7s*R!Op(lTfX~SCUHQ{DBfeQ`sTN6wXPWO9OD?iSGAWCe+NnL|NX~c~T zk75!Es`o4SZBC~+QF3yO6mmt;isV&sEq-5^kiSomU^moZ^93Uzw6Mf_D}V%mUy>@a{vTfk?I>wLoHSrZ>$e)b{Xj;b()>(0wiAhEz*TAp%85%rwuj?R z>|EhL7u@@^G;446ON;BY|br^E-1+}Wm&{qt{@|e=-{T`wt2b!psE$=T;!)c#rZhWaE zpkqe7oiLsWAcc2xO;O0V-HYqSF~-VtKy61*<<*8jG!+8#-x+$^2H#015iCVN%ZWMj zgv*c8ldge@cByY?xiaXR1>qog2L;W6wp2|`l>nj*paVf%I=s88LP^RrY~6k}zkr*< z-}q~>*;6GZ?5a7%p{s@$l$sI04i-rU1rwVvtktM0@f^lSPKv_7N*tsQk%oJ_DztYV zYLR(H5BNlR*IZ`5;_5*2Y9Gb?6pzmC2{w$y&0HIqd`F3CPZkTIX%OPi%TiFj0A2Bz zGyocR+k_)(z;7+DGq*X|i=dTqhs{{XU!uhXO{k1#U@YlvqE{zRM~ZvdWoS9*v3 z^^+QFLowhyVE7(ED-gcRTHxfic2PbvoiQtik;&w(k*PEp9cjx#V=u+Yh4*CFER0Py!6pA)s0G=V5GE3KFwA|A4|)IH>= zy*eGBL!yJpEe(;c4sbkUVg)u_*(88H_tJz=D06bDC0m-HC=dd$0~J8O8q1*wP9!odfLnaUr2_6nne`qX(picQl{;gk zxkZq@4xA0P4xI_DtfFf3tOv=n@*p=$g1Sfm`Slr1nH8zp-SC&3!u<*<7_Y(N?u7%A z#I<}_HjaG1&D|AWhpFaU;67GBpU$r1^MR@!AWrO`%Qv?pW@82tOH4}OZ9o?v0OEEJ zAV5+JYmA^aQaIrwd`~2u=P~4ztDztZtbCH@U;Pf(NJ|6!%MI{v8X-f%7Y9_m)b?ox zmISmPgYiX5&h#(gp{*B#SeO6>uyzQ!@7|YI9-7OgaWwoq z8C`P9tEEa6Ojd|Q&hsVrxc!LIggsbXAA+!9*xi|CAqeacXbYxA0(58lfn_-czr8k6 zKHw661m}Mf7>u%?a@LN}^DR5O6S2vF6ib#16mnZVXxuJ+OWpRrj=;*7x)Z~9>V7f@ zFXiYCb7>vXdqkI$*aE@i0FW@W(i6erII9%xW+!w^=2%9#r3g%8Wk##~=*8Qg*pJOw zFU}*DPKm1!R9RLQh?{9Sx%Q-hLH z0j5Z9X_(11GKAw-nP+I815Kh7vR264VZMlydOMOUaMP|f?qi(^#HEnHVc~(%!u%1c zHpF^Q8tkjx>Bve8R>`lN`Uo0DA%vTp8tqRJr|zWf!E(41L(V?b{rw{q{$zExL?tR2 zekjddk6`Tspm5-~2sSOa9E;TK_U2tu!bO9*~1q8#K zETw@Bv)KVLiP+kHn;{?G@pNvK;T`NNNvAw325^A}P;%xtq9zqRwvD5yLwiP@^- zFonc=_X|v|{R#dFMIfNS1Pn)51MvTs?i)$jp8h2@wp0tQ#pGr8Aj%8#r*|0-in>-D z*q{)Y3)^R(jxVtyz-XUB%t8F749<$Hh@*|9oSQh8Y4!KrY z%nvBq*LvCW9QkVBGlM@Pi9}Fqe|F-YMgHqK;lCHJlzw!af>3~ zg_E~-;!9I-^i5=TSg&Js6idw$`6eIXQmsJ3D6CT-gl!F0=qXnj*`B`SUi}@4V_)Ki zh{4tiNUh&i_xt+?OdI)kYw?B*oUz2%nEuBH^|Llt+)N6E03sw>3Je3XuUyap7?OEN zzyhAJbjL?mYz7kq7}2Y|^72&BM}rUSTUN}Vfl%Sn06k~f0m;jhI_g%_So4;4BBawF zQU6e+=0GF;iqa4Iod+-IRY3THhU+{LQ{J`f=gvPjFUKxo6$q~2lz5(;!H{FUxQ!LM z_FTH3+C^=}Hd0{4f1ev7IV{|>Nkh38G0+99G>%lH_`GQ!C`;~r4u#WmS3BhgpL>il z=g%>cVgV1@)wVwzY1I$=yN7rP5Xxa%oxqp<8x--0Sv|P_ z`v9cX-eK?W8qT)m3}1RCwMM23o;Leae+0^@R(D4%Y}4U_gpV^qiipI%%&+QPcIVqGi8GD ze2Ok#oqimbYADpBcwS+dS@Ih=_>*gc4Q$18JorD%ARSN6;g6g)CVxU4|KkUd zPhR%Phx-r_N5*D^w`|2!Wg})y1WA=B_#J?d`aO*noS^p~CSHmHJw@(}9%|@QSt@bMp+&^y(K-s-2eWKX|ZZRxc+QUo?r4uJXV#} zNzT;r(fKEKmk(>(25SO&(0QVQ>t%bVO&k-KnnXVNVksq>=0N~Ie@j$--CrbP;mA$_^ZB>C!o^vI!BhU!FlHaX9n!LI@#2E)Ro zD&)`cWe#VaVrqUn3O$*m{asLwU>3B6a_6AqcFu3P07ByL6j6ZV5 zJdru~E}AD}GL&z&@^?}}U5HMwEV7@m|8OlM7gsCfPRE9}@LXp;-KCGZlDwGuu$|93 zWq!$4X#M16Tzs^p+nTNV_jiR8nW~O0Glyqr2|JU)j#IG;sVjEy-AKNnG!#dqPP?Oy zEyR9p$ilOJI#@v4t^R`F_#X-Qljc&Vv{N4QiPD0}|6DtPK6_u&H@|taRA|_M$a`*1 zqWN*hL|PN+8O!~N2CH!v>D|q1w9aH^T7=4a9lXI&v7sMRisd@1 z9+@UYc?nypQ)!tA@J>l)gC2!-w68>p9e^1~PJZ{da;Hz-jx+(O!=9YnX(l3kBHF_H zsT{$(3+}FujdL(wVs&Jm=0wwy#s1kb^H$FpoWYHoM@_T2b6!9(oqv({#krcbQDF(| zFC2PW67^`;*)2YzdE#|V?;lpSGs`i}sU0*uhWPX&QIEqlGvMc?gB6juKw~H4ZfBJ~(W%aQjxgTUx;$c znZf$DrEPYk$)z((DY_?KIk-DS<&K9}khj#zG72OM10_4i)-bM7Lcr3tESA3RLGW9*Q6AM=ypKp7pz15Fj}+_!IwE+Ai!& zS^IH#P^T?JGDA{&CAz-#tiPLBF=o> zbjk-Aw9(cR)z&`vWzg>WOg(N&+vS45w&QKzF$V4nc`s^dr<7|HXJpGAYp0B5L3Gj5 z(>L8-whKEhci8E;XQ4YkrOBMj=T-5-IqGUCbLh)pCSFuK^GouI|AvU|qaQGi9xi6v zIlw9~^O0*+*YH6+@S#kpz;oIDwrhh|$aij$@1)<%8DC$KJ02O~vR_QgV26F>GApN- zZZA{LT&9(pLU2m^PYia69cWJZ|`pj~TZN|k9+mh@O_Ah<&bMTYt`5QSii$3LhWQL)JAHJy7O)q{Fc(>@#`3R4Q z#?&0ILoZ(Gxqm7o&HK!lTt!&k6 z4Ay@njg|f-gLHq@vFSOpa@?!;ZhGlG|L;FcPr3>_{BZo?P`$8=pQ0vDol0pxoKsj< zs8d+x@pbp-gVkQ1HLm)O`fmDF8PCd|uA@=tf_O-`=9yXXkH;Q)OF!Ka5b8YppW?o$ zHiH*B0$x|2$)|DWFZ7~Pg5Q=79y7hq%weSap#Jt?@@b3 z%}2j%8KSVS^B#XTa{Oe3zkHB7f63FWbvLU+8;`aP-5c!wsJ~Wy;`>|j;9P4iABBE+ zbHNXLC3_`DrH8A|t None: if join_message: if chat_channel is not None: if coginstance.bot.embed_requested(chat_channel): - await chat_channel.send(embed=await generate_join_leave_embed(join_message, True)) + embed, img = await generate_join_leave_embed(coginstance=coginstance, username=chat_message['username'],join=True) + if img: + with open(img, 'rb') as file: + await chat_channel.send(embed=embed, file=file) + else: + await chat_channel.send(embed=embed) else: await chat_channel.send(f"{join_message} joined the game", allowed_mentions=discord.AllowedMentions.none()) @@ -86,7 +93,12 @@ async def establish_websocket_connection(coginstance: Pterodactyl) -> None: if leave_message: if chat_channel is not None: if coginstance.bot.embed_requested(chat_channel): - await chat_channel.send(embed=await generate_join_leave_embed(leave_message, False)) + embed, img = await generate_join_leave_embed(coginstance=coginstance, username=chat_message['username'],join=False) + if img: + with open(img, 'rb') as file: + await chat_channel.send(embed=embed, file=file) + else: + await chat_channel.send(embed=embed) else: await chat_channel.send(f"{leave_message} left the game", allowed_mentions=discord.AllowedMentions.none()) @@ -219,29 +231,33 @@ async def send_chat_discord(coginstance: Pterodactyl, username: str, message: st else: logger.warning("Chat channel not set. Skipping sending chat message to Discord") -async def generate_join_leave_embed(username: str, join: bool) -> discord.Embed: +async def generate_join_leave_embed(coginstance: Pterodactyl, username: str, join: bool) -> Tuple[discord.Embed, Optional[Union[str, Path]]]: embed = discord.Embed() embed.color = discord.Color.green() if join else discord.Color.red() embed.description = await config.join_msg() if join else await config.leave_msg() info = await get_info(username) if info: + img = None embed.set_author(name=username, icon_url=info['data']['player']['avatar']) else: - embed.set_author(name=username, icon_url='https://seafsh.cc/u/j3AzqQ.png') + img = bundled_data_path(coginstance) / "unknown.png" + embed.set_author(name=username, icon_url='attachment://unknown.png') embed.timestamp = discord.utils.utcnow() - return embed + return embed, img -async def generate_achievement_embed(username: str, achievement: str, challenge: bool) -> discord.Embed: +async def generate_achievement_embed(coginstance: Pterodactyl, username: str, achievement: str, challenge: bool) -> Tuple[discord.Embed, Optional[Union[str, Path]]]: embed = discord.Embed() embed.color = discord.Color.from_str('#a800a7') if challenge else discord.Color.from_str('#54fb54') embed.description = f"{bold(username)} has {'completed the challenge' if challenge else 'made the advancement'} {bold(achievement)}" info = await get_info(username) if info: + img = None embed.set_author(name=username, icon_url=info['data']['player']['avatar']) else: - embed.set_author(name=username, icon_url='https://seafsh.cc/u/j3AzqQ.png') + img = bundled_data_path(coginstance) / "unknown.png" + embed.set_author(name=username, icon_url='attachment://unknown.png') embed.timestamp = discord.utils.utcnow() - return embed + return embed, img def mask_ip(string: str) -> str: def check(match: re.Match[str]): -- 2.45.3 From b80dedbda2292c6b008ae1d2aca9f03fc20f18e5 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 26 Aug 2024 19:43:57 -0400 Subject: [PATCH 344/376] fix(pterodactyl): fixed join and leave listeners throwing errors --- pterodactyl/pterodactyl.py | 2 +- pterodactyl/websocket.py | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pterodactyl/pterodactyl.py b/pterodactyl/pterodactyl.py index 95ccdca..a1a8227 100644 --- a/pterodactyl/pterodactyl.py +++ b/pterodactyl/pterodactyl.py @@ -22,7 +22,7 @@ class Pterodactyl(commands.Cog): __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" - __version__ = "2.0.2" + __version__ = "2.0.3" __documentation__ = "https://seacogs.coastalcommits.com/pterodactyl/" def __init__(self, bot: Red): diff --git a/pterodactyl/websocket.py b/pterodactyl/websocket.py index 879d477..3412fb6 100644 --- a/pterodactyl/websocket.py +++ b/pterodactyl/websocket.py @@ -80,7 +80,7 @@ async def establish_websocket_connection(coginstance: Pterodactyl) -> None: if join_message: if chat_channel is not None: if coginstance.bot.embed_requested(chat_channel): - embed, img = await generate_join_leave_embed(coginstance=coginstance, username=chat_message['username'],join=True) + embed, img = await generate_join_leave_embed(coginstance=coginstance, username=join_message,join=True) if img: with open(img, 'rb') as file: await chat_channel.send(embed=embed, file=file) @@ -93,7 +93,7 @@ async def establish_websocket_connection(coginstance: Pterodactyl) -> None: if leave_message: if chat_channel is not None: if coginstance.bot.embed_requested(chat_channel): - embed, img = await generate_join_leave_embed(coginstance=coginstance, username=chat_message['username'],join=False) + embed, img = await generate_join_leave_embed(coginstance=coginstance, username=leave_message,join=False) if img: with open(img, 'rb') as file: await chat_channel.send(embed=embed, file=file) @@ -165,7 +165,7 @@ async def check_if_server_message(text: str) -> Union[bool, str]: regex = await config.server_regex() match: Optional[re.Match[str]] = re.match(regex, text) if match: - logger.debug("Message is a server message") + logger.trace("Message is a server message") return match.group(1) return False @@ -174,7 +174,7 @@ async def check_if_chat_message(text: str) -> Union[bool, dict]: match: Optional[re.Match[str]] = re.match(regex, text) if match: groups = {"username": match.group(1), "message": match.group(2)} - logger.debug("Message is a chat message\n%s", json.dumps(groups)) + logger.trace("Message is a chat message\n%s", json.dumps(groups)) return groups return False @@ -182,7 +182,7 @@ async def check_if_join_message(text: str) -> Union[bool, str]: regex = await config.join_regex() match: Optional[re.Match[str]] = re.match(regex, text) if match: - logger.debug("Message is a join message") + logger.trace("Message is a join message") return match.group(1) return False @@ -190,7 +190,7 @@ async def check_if_leave_message(text: str) -> Union[bool, str]: regex = await config.leave_regex() match: Optional[re.Match[str]] = re.match(regex, text) if match: - logger.debug("Message is a leave message") + logger.trace("Message is a leave message") return match.group(1) return False @@ -203,23 +203,23 @@ async def check_if_achievement_message(text: str) -> Union[bool, dict]: groups["challenge"] = True else: groups["challenge"] = False - logger.debug("Message is an achievement message") + logger.trace("Message is an achievement message") return groups return False async def get_info(username: str) -> Optional[dict]: - logger.debug("Retrieving player info for %s", username) + logger.verbose("Retrieving player info for %s", username) endpoint = await config.api_endpoint() async with aiohttp.ClientSession() as session: async with session.get(f"https://playerdb.co/api/player/{endpoint}/{username}") as response: if response.status == 200: - logger.debug("Player info retrieved for %s", username) + logger.verbose("Player info retrieved for %s", username) return await response.json() - logger.error("Failed to retrieve player info for %s: %s", username, response.status) + logger.warning("Failed to retrieve player info for %s: %s", username, response.status) return None async def send_chat_discord(coginstance: Pterodactyl, username: str, message: str, avatar_url: str) -> None: - logger.debug("Sending chat message to Discord") + logger.trace("Sending chat message to Discord") channel = coginstance.bot.get_channel(await config.chat_channel()) if channel is not None: webhooks = await channel.webhooks() @@ -227,7 +227,7 @@ async def send_chat_discord(coginstance: Pterodactyl, username: str, message: st if webhook is None: webhook = await channel.create_webhook(name="Pterodactyl Chat") await webhook.send(content=message, username=username, avatar_url=avatar_url, allowed_mentions=discord.AllowedMentions(everyone=False, roles=False, users=True)) - logger.debug("Chat message sent to Discord") + logger.trace("Chat message sent to Discord") else: logger.warning("Chat channel not set. Skipping sending chat message to Discord") -- 2.45.3 From 3e4efa92206321fa480d45b2f5a4b967a8889c7a Mon Sep 17 00:00:00 2001 From: cswimr Date: Tue, 27 Aug 2024 14:03:15 -0400 Subject: [PATCH 345/376] fix(actions): updated container tags --- .forgejo/workflows/workflow.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index 98b12fc..3c23538 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -8,7 +8,7 @@ on: jobs: Lint Code (Ruff & Pylint): runs-on: docker - container: www.coastalcommits.com/seaswimmerthefsh/actionscontainers-seacogs:latest + container: www.coastalcommits.com/cswimr/actions:seacogs steps: - name: Checkout uses: actions/checkout@v3 @@ -25,7 +25,7 @@ jobs: Build Documentation (MkDocs): runs-on: docker - container: www.coastalcommits.com/seaswimmerthefsh/actionscontainers-seacogs:latest + container: www.coastalcommits.com/cswimr/actions:seacogs steps: - name: Checkout uses: actions/checkout@v3 -- 2.45.3 From eb331faf55ae22a46fdc996584aa20d2fc1b770b Mon Sep 17 00:00:00 2001 From: cswimr Date: Tue, 27 Aug 2024 14:05:10 -0400 Subject: [PATCH 346/376] fix(pterodactyl): fixed a missing argument in one of the websocket events --- pterodactyl/pterodactyl.py | 2 +- pterodactyl/websocket.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pterodactyl/pterodactyl.py b/pterodactyl/pterodactyl.py index a1a8227..c86c949 100644 --- a/pterodactyl/pterodactyl.py +++ b/pterodactyl/pterodactyl.py @@ -22,7 +22,7 @@ class Pterodactyl(commands.Cog): __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" - __version__ = "2.0.3" + __version__ = "2.0.4" __documentation__ = "https://seacogs.coastalcommits.com/pterodactyl/" def __init__(self, bot: Red): diff --git a/pterodactyl/websocket.py b/pterodactyl/websocket.py index 3412fb6..e5fd8db 100644 --- a/pterodactyl/websocket.py +++ b/pterodactyl/websocket.py @@ -106,7 +106,7 @@ async def establish_websocket_connection(coginstance: Pterodactyl) -> None: if achievement_message: if chat_channel is not None: if coginstance.bot.embed_requested(chat_channel): - await chat_channel.send(embed=await generate_achievement_embed(achievement_message['username'], achievement_message['achievement'], achievement_message['challenge'])) + await chat_channel.send(embed=await generate_achievement_embed(coginstance, achievement_message['username'], achievement_message['achievement'], achievement_message['challenge'])) else: await chat_channel.send(f"{achievement_message['username']} has {'completed the challenge' if achievement_message['challenge'] else 'made the advancement'} {achievement_message['achievement']}") -- 2.45.3 From 2c7b0f54412cb9c115ef294e0bffe0eff70dc900 Mon Sep 17 00:00:00 2001 From: cswimr Date: Tue, 27 Aug 2024 14:22:19 -0400 Subject: [PATCH 347/376] feat(repo): updated all cogs (except aurora) to use the help formatting present in the indev version of aurora --- antipolls/antipolls.py | 13 +++++++------ backup/backup.py | 13 +++++++------ bible/bible.py | 16 +++++++++------- emojiinfo/emojiinfo.py | 21 +++++++++++---------- nerdify/nerdify.py | 13 ++++++++----- pterodactyl/pterodactyl.py | 17 +++++++++++++++++ seautils/seautils.py | 14 +++++++++----- 7 files changed, 68 insertions(+), 39 deletions(-) diff --git a/antipolls/antipolls.py b/antipolls/antipolls.py index 810e88b..15aecfd 100644 --- a/antipolls/antipolls.py +++ b/antipolls/antipolls.py @@ -9,14 +9,15 @@ import discord from red_commons.logging import getLogger from redbot.core import commands from redbot.core.bot import Config, Red -from redbot.core.utils.chat_formatting import humanize_list +from redbot.core.utils.chat_formatting import bold, humanize_list class AntiPolls(commands.Cog): """AntiPolls deletes messages that contain polls, with a configurable per-guild role and channel whitelist and support for default Discord permissions (Manage Messages).""" - __author__ = ["SeaswimmerTheFsh"] - __version__ = "1.0.0" + __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] + __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" + __version__ = "1.0.1" __documentation__ = "https://seacogs.coastalcommits.com/antipolls/" def __init__(self, bot: Red): @@ -38,9 +39,9 @@ class AntiPolls(commands.Cog): n = "\n" if "\n\n" not in pre_processed else "" text = [ f"{pre_processed}{n}", - f"Cog Version: **{self.__version__}**", - f"Author: {humanize_list(self.__author__)}", - f"Documentation: {self.__documentation__}", + f"{bold('Cog Version:')} [{self.__version__}]({self.__git__})", + f"{bold('Author:')} {humanize_list(self.__author__)}", + f"{bold('Documentation:')} {self.__documentation__}", ] return "\n".join(text) diff --git a/backup/backup.py b/backup/backup.py index 6202e3a..5d01c6b 100644 --- a/backup/backup.py +++ b/backup/backup.py @@ -14,15 +14,16 @@ from redbot.cogs.downloader import errors from redbot.cogs.downloader.converters import InstalledCog from redbot.core import commands from redbot.core.bot import Red -from redbot.core.utils.chat_formatting import error, humanize_list, text_to_file +from redbot.core.utils.chat_formatting import bold, error, humanize_list, text_to_file # pylint: disable=protected-access class Backup(commands.Cog): """A utility to make reinstalling repositories and cogs after migrating the bot far easier.""" - __author__ = ["SeaswimmerTheFsh"] - __version__ = "1.1.0" + __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] + __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" + __version__ = "1.1.1" __documentation__ = "https://seacogs.coastalcommits.com/backup/" def __init__(self, bot: Red): @@ -35,9 +36,9 @@ class Backup(commands.Cog): n = "\n" if "\n\n" not in pre_processed else "" text = [ f"{pre_processed}{n}", - f"Cog Version: **{self.__version__}**", - f"Author: {humanize_list(self.__author__)}", - f"Documentation: {self.__documentation__}", + f"{bold('Cog Version:')} [{self.__version__}]({self.__git__})", + f"{bold('Author:')} {humanize_list(self.__author__)}", + f"{bold('Documentation:')} {self.__documentation__}", ] return "\n".join(text) diff --git a/bible/bible.py b/bible/bible.py index 10cc953..0cfdb3c 100644 --- a/bible/bible.py +++ b/bible/bible.py @@ -15,7 +15,7 @@ from PIL import Image from red_commons.logging import getLogger from redbot.core import Config, commands, data_manager from redbot.core.bot import Red -from redbot.core.utils.chat_formatting import error, humanize_list +from redbot.core.utils.chat_formatting import bold, error, humanize_list import bible.errors from bible.models import Version @@ -24,9 +24,10 @@ from bible.models import Version class Bible(commands.Cog): """Retrieve Bible verses from the API.bible API.""" - __author__ = ["SeaswimmerTheFsh"] - __version__ = "1.1.0" - __documentation__ = "https://seacogs.coastalcommits.com/bible/" + __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] + __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" + __version__ = "1.1.1" + __documentation__ = "https://seacogs.coastalcommits.com/pterodactyl/" def __init__(self, bot: Red): super().__init__() @@ -44,12 +45,13 @@ class Bible(commands.Cog): n = "\n" if "\n\n" not in pre_processed else "" text = [ f"{pre_processed}{n}", - f"Cog Version: **{self.__version__}**", - f"Author: {humanize_list(self.__author__)}", - f"Documentation: {self.__documentation__}", + f"{bold('Cog Version:')} [{self.__version__}]({self.__git__})", + f"{bold('Author:')} {humanize_list(self.__author__)}", + f"{bold('Documentation:')} {self.__documentation__}", ] return "\n".join(text) + def get_icon(self, color: Colour) -> File: """Get the docs.api.bible favicon with a given color.""" image_path = data_manager.bundled_data_path(self) / "api.bible-logo.png" diff --git a/emojiinfo/emojiinfo.py b/emojiinfo/emojiinfo.py index 7413e6e..3dd8188 100644 --- a/emojiinfo/emojiinfo.py +++ b/emojiinfo/emojiinfo.py @@ -1,5 +1,4 @@ import io -from typing import Any, Literal import aiohttp import discord @@ -15,9 +14,10 @@ from .model import PartialEmoji class EmojiInfo(commands.Cog): """Retrieve information about emojis.""" - __author__: list[str] = ["SeaswimmerTheFsh"] - __version__: str = "1.0.0" - __documentation__: str = "https://seacogs.coastalcommits.com/emojiinfo/" + __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] + __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" + __version__ = "1.0.1" + __documentation__ = "https://seacogs.coastalcommits.com/emojiinfo/" def __init__(self, bot: Red) -> None: super().__init__() @@ -25,16 +25,17 @@ class EmojiInfo(commands.Cog): self.logger: RedTraceLogger = getLogger(name="red.SeaCogs.Emoji") def format_help_for_context(self, ctx: commands.Context) -> str: - pre_processed: Any | Literal[''] = super().format_help_for_context(ctx) or "" - n: Literal['\n'] | Literal[''] = "\n" if "\n\n" not in pre_processed else "" - text: list[str] = [ + pre_processed = super().format_help_for_context(ctx) or "" + n = "\n" if "\n\n" not in pre_processed else "" + text = [ f"{pre_processed}{n}", - f"Cog Version: **{self.__version__}**", - f"Author: {humanize_list(items=self.__author__)}", - f"Documentation: {self.__documentation__}", + f"{bold('Cog Version:')} [{self.__version__}]({self.__git__})", + f"{bold('Author:')} {humanize_list(self.__author__)}", + f"{bold('Documentation:')} {self.__documentation__}", ] return "\n".join(text) + async def fetch_twemoji(self, unicode_emoji) -> str: base_url = "https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/72x72/" emoji_codepoint = "-".join([hex(ord(char))[2:] for char in unicode_emoji]) diff --git a/nerdify/nerdify.py b/nerdify/nerdify.py index 76307b1..f5e92b5 100644 --- a/nerdify/nerdify.py +++ b/nerdify/nerdify.py @@ -12,13 +12,15 @@ from typing import Any, Optional, Union import discord from redbot.core import commands from redbot.core.utils import chat_formatting, common_filters +from redbot.core.utils.chat_formatting import bold, humanize_list class Nerdify(commands.Cog): """Nerdify your text.""" - __author__ = ["SeaswimmerTheFsh"] - __version__ = "1.3.4" + __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] + __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" + __version__ = "1.3.5" __documentation__ = "https://seacogs.coastalcommits.com/nerdify/" def __init__(self, bot): @@ -29,12 +31,13 @@ class Nerdify(commands.Cog): n = "\n" if "\n\n" not in pre_processed else "" text = [ f"{pre_processed}{n}", - f"Cog Version: **{self.__version__}**", - f"Author: {chat_formatting.humanize_list(self.__author__)}", - f"Documentation: {self.__documentation__}" + f"{bold('Cog Version:')} [{self.__version__}]({self.__git__})", + f"{bold('Author:')} {humanize_list(self.__author__)}", + f"{bold('Documentation:')} {self.__documentation__}", ] return "\n".join(text) + @commands.command(aliases=["nerd"]) async def nerdify( self, ctx: commands.Context, *, text: Optional[str] = None diff --git a/pterodactyl/pterodactyl.py b/pterodactyl/pterodactyl.py index c86c949..fc49e3f 100644 --- a/pterodactyl/pterodactyl.py +++ b/pterodactyl/pterodactyl.py @@ -46,6 +46,23 @@ class Pterodactyl(commands.Cog): ] return "\n".join(text) + async def cog_load(self) -> None: + pterodactyl_keys = await self.bot.get_shared_api_tokens("pterodactyl") + api_key = pterodactyl_keys.get("api_key") + if api_key is None: + self.task.cancel() + raise ValueError("Pterodactyl API key not set. Please set it using `[p]set api`.") + base_url = await config.base_url() + if base_url is None: + self.task.cancel() + raise ValueError("Pterodactyl base URL not set. Please set it using `[p]pterodactyl config url`.") + server_id = await config.server_id() + if server_id is None: + self.task.cancel() + raise ValueError("Pterodactyl server ID not set. Please set it using `[p]pterodactyl config serverid`.") + + self.client = PterodactylClient(base_url, api_key).client + async def cog_unload(self) -> None: self.update_topic.cancel() self.task.cancel() diff --git a/seautils/seautils.py b/seautils/seautils.py index 5485dcc..a895c35 100644 --- a/seautils/seautils.py +++ b/seautils/seautils.py @@ -38,22 +38,26 @@ def format_rfc_text(text: str, number: int) -> str: class SeaUtils(commands.Cog): """A collection of random utilities.""" - __author__ = ["SeaswimmerTheFsh"] - __version__ = "1.0.0" + __author__ = ["[cswimr](https://www.coastalcommits.com/cswimr)"] + __git__ = "https://www.coastalcommits.com/cswimr/SeaCogs" + __version__ = "1.0.1" + __documentation__ = "https://seacogs.coastalcommits.com/seautils/" def __init__(self, bot: Red) -> None: self.bot = bot def format_help_for_context(self, ctx: commands.Context) -> str: - pre_processed = super().format_help_for_context(ctx=ctx) or "" + pre_processed = super().format_help_for_context(ctx) or "" n = "\n" if "\n\n" not in pre_processed else "" text = [ f"{pre_processed}{n}", - f"Cog Version: **{self.__version__}**", - f"Author: {cf.humanize_list(items=self.__author__)}" + f"{cf.bold('Cog Version:')} [{self.__version__}]({self.__git__})", + f"{cf.bold('Author:')} {cf.humanize_list(self.__author__)}", + f"{cf.bold('Documentation:')} {self.__documentation__}", ] return "\n".join(text) + def format_src(self, obj: Any) -> str: """A large portion of this code is repurposed from Zephyrkul's RTFS cog. https://github.com/Zephyrkul/FluffyCogs/blob/master/rtfs/rtfs.py""" -- 2.45.3 From f3f99209daf9a6f8a3d9a6e07258cd5f990192cd Mon Sep 17 00:00:00 2001 From: cswimr Date: Tue, 27 Aug 2024 14:22:38 -0400 Subject: [PATCH 348/376] fix(backup): update for red 3.5.13 --- backup/info.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/info.json b/backup/info.json index 83d211c..075c208 100644 --- a/backup/info.json +++ b/backup/info.json @@ -8,7 +8,7 @@ "hidden": false, "disabled": false, "min_bot_version": "3.5.6", - "max_bot_version": "3.5.12", + "max_bot_version": "3.5.13", "min_python_version": [3, 9, 0], "tags": [ "utility", -- 2.45.3 From 14fe976a0d14f6e346f5c506715fbff6d0b674f4 Mon Sep 17 00:00:00 2001 From: cswimr Date: Tue, 27 Aug 2024 14:25:14 -0400 Subject: [PATCH 349/376] fix(repo): update all instances of SeaswimmerTheFsh to cswimr --- .docs/aurora/index.md | 2 +- .docs/backup.md | 4 +- .docs/bible.md | 2 +- .docs/emojiinfo.md | 2 +- .docs/nerdify.md | 2 +- .docs/pterodactyl/getting-started.md | 2 +- .docs/pterodactyl/index.md | 2 +- .docs/pterodactyl/installing-red.md | 2 +- .forgejo/ISSUE_TEMPLATE/bug_report.yaml | 2 +- .forgejo/pull_request_template.md | 4 +- README.md | 2 +- antipolls/info.json | 4 +- aurora/aurora.py | 390 +++++++----------------- aurora/info.json | 4 +- backup/backup.py | 4 +- backup/info.json | 4 +- bible/info.json | 4 +- emojiinfo/info.json | 2 +- info.json | 8 +- mkdocs.yml | 10 +- nerdify/info.json | 4 +- pterodactyl/info.json | 6 +- pyproject.toml | 2 +- seautils/info.json | 4 +- 24 files changed, 150 insertions(+), 322 deletions(-) diff --git a/.docs/aurora/index.md b/.docs/aurora/index.md index f6e5527..4c6f321 100644 --- a/.docs/aurora/index.md +++ b/.docs/aurora/index.md @@ -10,7 +10,7 @@ Aurora is a fully-featured moderation system. It is heavily inspired by Galactic ## Installation ```bash -[p]repo add seacogs https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs +[p]repo add seacogs https://www.coastalcommits.com/cswimr/SeaCogs [p]cog install seacogs aurora [p]cog load aurora ``` diff --git a/.docs/backup.md b/.docs/backup.md index b8182a5..4ddc56f 100644 --- a/.docs/backup.md +++ b/.docs/backup.md @@ -5,14 +5,14 @@ Backup allows you to export a JSON list of all of your installed repositories an ## Installation ```bash -[p]repo add seacogs https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs +[p]repo add seacogs https://www.coastalcommits.com/cswimr/SeaCogs [p]cog install seacogs backup [p]cog load backup ``` ## Version Compatibility -As of commit [1edb08a](https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs/commit/1edb08a1271f12098ca0bed11a735f7162cedd14), the Backup cog no longer supports Red versions older than 3.5.6. If you want to use the cog on an earlier version (3.5.0 - 3.5.5), install the cog pinned to this commit: `43464db6a7c51bc69282b1ae3dc507a4aae851de`. +As of commit [1edb08a](https://www.coastalcommits.com/cswimr/SeaCogs/commit/1edb08a1271f12098ca0bed11a735f7162cedd14), the Backup cog no longer supports Red versions older than 3.5.6. If you want to use the cog on an earlier version (3.5.0 - 3.5.5), install the cog pinned to this commit: `43464db6a7c51bc69282b1ae3dc507a4aae851de`. ```bash [p]cog installversion sea-cogs 43464db6a7c51bc69282b1ae3dc507a4aae851de backup diff --git a/.docs/bible.md b/.docs/bible.md index b748de2..188f985 100644 --- a/.docs/bible.md +++ b/.docs/bible.md @@ -6,7 +6,7 @@ This cog does require an api key to work. ## Installation ```bash -[p]repo add seacogs https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs +[p]repo add seacogs https://www.coastalcommits.com/cswimr/SeaCogs [p]cog install seacogs bible [p]cog load bible ``` diff --git a/.docs/emojiinfo.md b/.docs/emojiinfo.md index 1473e59..ef63ab6 100644 --- a/.docs/emojiinfo.md +++ b/.docs/emojiinfo.md @@ -5,7 +5,7 @@ EmojiInfo allows you to retrieve information about an emoji. ## Installation ```bash -[p]repo add seacogs https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs +[p]repo add seacogs https://www.coastalcommits.com/cswimr/SeaCogs [p]cog install seacogs emojiinfo [p]cog load emojiinfo ``` diff --git a/.docs/nerdify.md b/.docs/nerdify.md index c1c50a9..87662b6 100644 --- a/.docs/nerdify.md +++ b/.docs/nerdify.md @@ -5,7 +5,7 @@ Nerdify allows you to nerdify other people's text. ## Installation ```bash -[p]repo add seacogs https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs +[p]repo add seacogs https://www.coastalcommits.com/cswimr/SeaCogs [p]cog install seacogs nerdify [p]cog load nerdify ``` diff --git a/.docs/pterodactyl/getting-started.md b/.docs/pterodactyl/getting-started.md index 9b4f75e..ce9ef31 100644 --- a/.docs/pterodactyl/getting-started.md +++ b/.docs/pterodactyl/getting-started.md @@ -28,7 +28,7 @@ The Downloader cog allows you to add Git repositories to your bot in order to do Now, use Downloader to add my repository to your bot: ``` -[p]repo add sea-cogs https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs +[p]repo add sea-cogs https://www.coastalcommits.com/cswimr/SeaCogs ``` Now, install the Pterodactyl cog: diff --git a/.docs/pterodactyl/index.md b/.docs/pterodactyl/index.md index bd3455e..cb69a5d 100644 --- a/.docs/pterodactyl/index.md +++ b/.docs/pterodactyl/index.md @@ -10,7 +10,7 @@ Pterodactyl allows for connecting to a Pterodactyl server through websockets. It ## Installation ```bash -[p]repo add seacogs https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs +[p]repo add seacogs https://www.coastalcommits.com/cswimr/SeaCogs [p]cog install seacogs pterodactyl [p]cog load aurora ``` diff --git a/.docs/pterodactyl/installing-red.md b/.docs/pterodactyl/installing-red.md index 93ed9f6..3f26e7b 100644 --- a/.docs/pterodactyl/installing-red.md +++ b/.docs/pterodactyl/installing-red.md @@ -64,7 +64,7 @@ Red is quite a large bot, so I'll focus on the specifics of getting the bot work ``` 2. Add my repository to the bot ```bash -[p]repo add sea-cogs https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs +[p]repo add sea-cogs https://www.coastalcommits.com/cswimr/SeaCogs ``` 3. Install and load the Pterodactyl cog ```bash diff --git a/.forgejo/ISSUE_TEMPLATE/bug_report.yaml b/.forgejo/ISSUE_TEMPLATE/bug_report.yaml index d603128..7fa4c8d 100644 --- a/.forgejo/ISSUE_TEMPLATE/bug_report.yaml +++ b/.forgejo/ISSUE_TEMPLATE/bug_report.yaml @@ -13,7 +13,7 @@ body: attributes: label: Please confirm that; options: - - label: I have checked that this bug does not already have an opened/closed [issue](https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs/issues) or [pull request](https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs/pulls) associated with it. + - label: I have checked that this bug does not already have an opened/closed [issue](https://www.coastalcommits.com/cswimr/SeaCogs/issues) or [pull request](https://www.coastalcommits.com/cswimr/SeaCogs/pulls) associated with it. required: true - label: I have checked that I am on the latest version of [Red-DiscordBot](https://github.com/CogCreators/Red-DiscordBot), and SeaCogs. required: true diff --git a/.forgejo/pull_request_template.md b/.forgejo/pull_request_template.md index 2813cd5..efe146e 100644 --- a/.forgejo/pull_request_template.md +++ b/.forgejo/pull_request_template.md @@ -2,5 +2,5 @@ -- [ ] By submitting this pull request, I permit SeaswimmerTheFsh to license my work under - the [Mozilla Public License Version 2.0](https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs/src/branch/main/LICENSE). +- [ ] By submitting this pull request, I permit cswimr to license my work under + the [Mozilla Public License Version 2.0](https://www.coastalcommits.com/cswimr/SeaCogs/src/branch/main/LICENSE). diff --git a/README.md b/README.md index 3524dda..ea29384 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ My assorted cogs for Red-DiscordBot. To get started with a development environment, first clone this repository. ```sh -git clone https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs.git +git clone https://coastalcommits.com/cswimr/SeaCogs.git ``` Then, install Poetry. diff --git a/antipolls/info.json b/antipolls/info.json index 2af0457..7856195 100644 --- a/antipolls/info.json +++ b/antipolls/info.json @@ -1,6 +1,6 @@ { - "author" : ["SeaswimmerTheFsh (seasw.)"], - "install_msg" : "Thank you for installing AntiPolls!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).", + "author" : ["cswimr"], + "install_msg" : "Thank you for installing AntiPolls!\nYou can find the source code of this cog [here](https://coastalcommits.com/cswimr/SeaCogs).", "name" : "AntiPolls", "short" : "AntiPolls deletes messages that contain polls.", "description" : "AntiPolls deletes messages that contain polls, with a configurable per-guild role and channel whitelist and support for default Discord permissions (Manage Messages).", diff --git a/aurora/aurora.py b/aurora/aurora.py index 84c2252..8702e52 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -70,9 +70,7 @@ class Aurora(commands.Cog): if requester == "user_strict": await config.user_from_id(user_id).clear() else: - logger.warning( - "Invalid requester passed to red_delete_data_for_user: %s", requester - ) + logger.warning("Invalid requester passed to red_delete_data_for_user: %s", requester) def __init__(self, bot: Red) -> None: super().__init__() @@ -85,7 +83,7 @@ class Aurora(commands.Cog): # and the information that aiosqlite logs is not useful to the bot owner. # This is a bad solution though as it overrides it for any other cogs that are using aiosqlite too. # If there's a better solution that you're aware of, please let me know in Discord or in a CoastalCommits issue. - py_logging.getLogger('aiosqlite').setLevel(py_logging.INFO) + py_logging.getLogger("aiosqlite").setLevel(py_logging.INFO) def format_help_for_context(self, ctx: commands.Context) -> str: pre_processed = super().format_help_for_context(ctx) or "" @@ -140,13 +138,7 @@ class Aurora(commands.Cog): if dm_users is None: dm_users = await config.guild(ctx.guild).dm_users() silent = not dm_users - return await moderation_type.handler( - ctx=ctx, - target=target, - silent=silent, - **kwargs - ) - + return await moderation_type.handler(ctx=ctx, target=target, silent=silent, **kwargs) @commands.Cog.listener("on_guild_join") async def db_generate_on_guild_join(self, guild: discord.Guild): @@ -189,27 +181,23 @@ class Aurora(commands.Cog): reason = "This action was performed without the bot." if entry.action == discord.AuditLogAction.kick: - moderation_type = type_registry['kick'] + moderation_type = type_registry["kick"] elif entry.action == discord.AuditLogAction.ban: - moderation_type = type_registry['ban'] + moderation_type = type_registry["ban"] elif entry.action == discord.AuditLogAction.unban: - moderation_type = type_registry['unban'] + moderation_type = type_registry["unban"] elif entry.action == discord.AuditLogAction.member_update: if entry.after.timed_out_until is not None: - timed_out_until_aware = entry.after.timed_out_until.replace( - tzinfo=timezone.utc - ) - duration_datetime = timed_out_until_aware - datetime.now( - tz=timezone.utc - ) + timed_out_until_aware = entry.after.timed_out_until.replace(tzinfo=timezone.utc) + duration_datetime = timed_out_until_aware - datetime.now(tz=timezone.utc) minutes = round(duration_datetime.total_seconds() / 60) duration = timedelta(minutes=minutes) - moderation_type = type_registry['mute'] + moderation_type = type_registry["mute"] else: - moderation_type = type_registry['unmute'] + moderation_type = type_registry["unmute"] else: return @@ -254,7 +242,7 @@ class Aurora(commands.Cog): target=target, silent=silent, permissions=["moderate_members"], - moderation_type=type_registry['note'], + moderation_type=type_registry["note"], reason=reason, ) @@ -281,7 +269,7 @@ class Aurora(commands.Cog): target=target, silent=silent, permissions=["moderate_members"], - moderation_type=type_registry['warn'], + moderation_type=type_registry["warn"], reason=reason, ) @@ -309,16 +297,7 @@ class Aurora(commands.Cog): How long are you adding this role for? silent: bool Should the user be messaged?""" - await self.moderate( - ctx=interaction, - target=target, - silent=silent, - permissions=["moderate_members", "manage_roles"], - moderation_type=type_registry['addrole'], - reason=reason, - role=role, - duration=duration - ) + await self.moderate(ctx=interaction, target=target, silent=silent, permissions=["moderate_members", "manage_roles"], moderation_type=type_registry["addrole"], reason=reason, role=role, duration=duration) @app_commands.command(name="removerole") async def removerole( @@ -344,16 +323,7 @@ class Aurora(commands.Cog): How long are you removing this role for? silent: bool Should the user be messaged?""" - await self.moderate( - ctx=interaction, - target=target, - silent=silent, - permissions=["moderate_members", "manage_roles"], - moderation_type=type_registry['removerole'], - reason=reason, - role=role, - duration=duration - ) + await self.moderate(ctx=interaction, target=target, silent=silent, permissions=["moderate_members", "manage_roles"], moderation_type=type_registry["removerole"], reason=reason, role=role, duration=duration) @app_commands.command(name="mute") async def mute( @@ -381,7 +351,7 @@ class Aurora(commands.Cog): target=target, silent=silent, permissions=["moderate_members"], - moderation_type=type_registry['mute'], + moderation_type=type_registry["mute"], duration=duration, reason=reason, ) @@ -409,7 +379,7 @@ class Aurora(commands.Cog): target=target, silent=silent, permissions=["moderate_members"], - moderation_type=type_registry['unmute'], + moderation_type=type_registry["unmute"], reason=reason, ) @@ -436,7 +406,7 @@ class Aurora(commands.Cog): target=target, silent=silent, permissions=["kick_members"], - moderation_type=type_registry['kick'], + moderation_type=type_registry["kick"], reason=reason, ) @@ -480,7 +450,7 @@ class Aurora(commands.Cog): target=target, silent=silent, permissions=["ban_members"], - moderation_type=type_registry['tempban'], + moderation_type=type_registry["tempban"], reason=reason, duration=duration, delete_messages=delete_messages, @@ -491,7 +461,7 @@ class Aurora(commands.Cog): target=target, silent=silent, permissions=["ban_members"], - moderation_type=type_registry['ban'], + moderation_type=type_registry["ban"], reason=reason, delete_messages=delete_messages, ) @@ -519,7 +489,7 @@ class Aurora(commands.Cog): target=target, silent=silent, permissions=["ban_members"], - moderation_type=type_registry['unban'], + moderation_type=type_registry["unban"], reason=reason, ) @@ -549,7 +519,7 @@ class Aurora(commands.Cog): target=channel, silent=True, permissions=["manage_channel"], - moderation_type=type_registry['slowmode'], + moderation_type=type_registry["slowmode"], interval=interval, reason=reason, ) @@ -600,46 +570,26 @@ class Aurora(commands.Cog): export: bool Exports the server's moderation history to a JSON file""" if ephemeral is None: - ephemeral = ( - await config.user(interaction.user).history_ephemeral() - or await config.guild(interaction.guild).history_ephemeral() - or False - ) + ephemeral = await config.user(interaction.user).history_ephemeral() or await config.guild(interaction.guild).history_ephemeral() or False if inline is None: - inline = ( - await config.user(interaction.user).history_inline() - or await config.guild(interaction.guild).history_inline() - or False - ) + inline = await config.user(interaction.user).history_inline() or await config.guild(interaction.guild).history_inline() or False if pagesize is None: if inline is True: - pagesize = ( - await config.user(interaction.user).history_inline_pagesize() - or await config.guild(interaction.guild).history_inline_pagesize() - or 6 - ) + pagesize = await config.user(interaction.user).history_inline_pagesize() or await config.guild(interaction.guild).history_inline_pagesize() or 6 else: - pagesize = ( - await config.user(interaction.user).history_pagesize() - or await config.guild(interaction.guild).history_pagesize() - or 5 - ) + pagesize = await config.user(interaction.user).history_pagesize() or await config.guild(interaction.guild).history_pagesize() or 5 if before and not on: try: before = parse(before) except (ParserError, OverflowError) as e: if e == ParserError: - await interaction.response.send_message( - content=error("Invalid date format for `before` parameter!"), ephemeral=True - ) + await interaction.response.send_message(content=error("Invalid date format for `before` parameter!"), ephemeral=True) return if e == OverflowError: - await interaction.response.send_message( - content=error("Date is too far in the future!"), ephemeral=True - ) + await interaction.response.send_message(content=error("Date is too far in the future!"), ephemeral=True) return if after and not on: @@ -647,14 +597,10 @@ class Aurora(commands.Cog): after = parse(after) except (ParserError, OverflowError) as e: if e == ParserError: - await interaction.response.send_message( - content=error("Invalid date format for `after` parameter!"), ephemeral=True - ) + await interaction.response.send_message(content=error("Invalid date format for `after` parameter!"), ephemeral=True) return if e == OverflowError: - await interaction.response.send_message( - content=error("Date is too far in the future!"), ephemeral=True - ) + await interaction.response.send_message(content=error("Date is too far in the future!"), ephemeral=True) return if on: @@ -662,14 +608,10 @@ class Aurora(commands.Cog): on = parse(on) except (ParserError, OverflowError) as e: if e == ParserError: - await interaction.response.send_message( - content=error("Invalid date format for `on` parameter!"), ephemeral=True - ) + await interaction.response.send_message(content=error("Invalid date format for `on` parameter!"), ephemeral=True) return if e == OverflowError: - await interaction.response.send_message( - content=error("Date is too far in the future!"), ephemeral=True - ) + await interaction.response.send_message(content=error("Date is too far in the future!"), ephemeral=True) return before = datetime.combine(on, datetime.max.time()) @@ -677,20 +619,16 @@ class Aurora(commands.Cog): await interaction.response.defer(ephemeral=ephemeral) - permissions = check_permissions( - interaction.client.user, ["embed_links"], interaction - ) + permissions = check_permissions(interaction.client.user, ["embed_links"], interaction) if permissions: await interaction.followup.send( - error( - f"I do not have the `{permissions}` permission, required for this action." - ), + error(f"I do not have the `{permissions}` permission, required for this action."), ephemeral=True, ) return if export and not types: - types = 'all' + types = "all" type_list = [] registry_values = type_registry.values() @@ -722,29 +660,20 @@ class Aurora(commands.Cog): if export: try: - filepath = ( - str(data_manager.cog_data_path(cog_instance=self)) - + str(os.sep) - + filename - ) + filepath = str(data_manager.cog_data_path(cog_instance=self)) + str(os.sep) + filename with open(filepath, "w", encoding="utf-8") as f: dump(obj=moderations, fp=f) await interaction.followup.send( - file=discord.File( - fp=filepath, filename=filename - ), + file=discord.File(fp=filepath, filename=filename), ephemeral=ephemeral, ) os.remove(filepath) except json.JSONDecodeError as e: await interaction.followup.send( - content=error( - "An error occurred while exporting the moderation history.\nError:\n" - ) - + box(text=e, lang="py"), + content=error("An error occurred while exporting the moderation history.\nError:\n") + box(text=e, lang="py"), ephemeral=ephemeral, ) return @@ -756,23 +685,17 @@ class Aurora(commands.Cog): embed = discord.Embed(color=await self.bot.get_embed_color(interaction.channel)) embed.set_author(icon_url=interaction.guild.icon.url, name="Infraction History") - embed.set_footer( - text=f"Page {page:,}/{page_quantity:,} | {case_quantity:,} Results" - ) + embed.set_footer(text=f"Page {page:,}/{page_quantity:,} | {case_quantity:,} Results") memory_dict = {} for mod in moderations[start_index:end_index]: if mod.target_id not in memory_dict: - memory_dict.update({ - str(mod.target_id): await mod.get_target() - }) + memory_dict.update({str(mod.target_id): await mod.get_target()}) target = memory_dict[str(mod.target_id)] if mod.moderator_id not in memory_dict: - memory_dict.update({ - str(mod.moderator_id): await mod.get_moderator() - }) + memory_dict.update({str(mod.moderator_id): await mod.get_moderator()}) moderator = memory_dict[str(mod.moderator_id)] field_name = f"Case #{mod.id:,} ({mod.type.string.title()})" @@ -784,16 +707,10 @@ class Aurora(commands.Cog): field_value += f"\n**Reason:** `{str(mod.reason)}`" if mod.duration: - duration_embed = ( - f"{humanize_timedelta(timedelta=mod.duration)} | " - if mod.expired is False - else f"{humanize_timedelta(timedelta=mod.duration)} | Expired" - ) + duration_embed = f"{humanize_timedelta(timedelta=mod.duration)} | " if mod.expired is False else f"{humanize_timedelta(timedelta=mod.duration)} | Expired" field_value += f"\n**Duration:** {duration_embed}" - field_value += ( - f"\n**Timestamp:** | " - ) + field_value += f"\n**Timestamp:** | " if mod.role_id: role = await mod.get_role() @@ -806,8 +723,8 @@ class Aurora(commands.Cog): await interaction.followup.send(embed=embed, ephemeral=ephemeral) - @history.autocomplete('types') - async def _history_types(self, interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]: # pylint: disable=unused-argument + @history.autocomplete("types") + async def _history_types(self, interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]: # pylint: disable=unused-argument types: List[str] = sorted(self.type_registry.keys()) choices = [] if current.endswith(","): @@ -815,7 +732,7 @@ class Aurora(commands.Cog): if c in types: types.remove(c) for t in types: - choices.append(app_commands.Choice(name=current+t, value=current+t)) + choices.append(app_commands.Choice(name=current + t, value=current + t)) else: choices.append(app_commands.Choice(name="all", value="all")) for t in types: @@ -824,9 +741,7 @@ class Aurora(commands.Cog): return choices[:25] @app_commands.command(name="resolve") - async def resolve( - self, interaction: discord.Interaction, case: int, reason: str = "No reason provided." - ): + async def resolve(self, interaction: discord.Interaction, case: int, reason: str = "No reason provided."): """Resolve a specific case. Parameters @@ -842,9 +757,7 @@ class Aurora(commands.Cog): ) if permissions: await interaction.response.send_message( - error( - f"I do not have the `{permissions}` permission, required for this action." - ), + error(f"I do not have the `{permissions}` permission, required for this action."), ephemeral=True, ) return @@ -852,15 +765,11 @@ class Aurora(commands.Cog): try: moderation = await Moderation.find_by_id(interaction.client, case, interaction.guild.id) except ValueError: - await interaction.response.send_message( - content=error(f"Case #{case:,} does not exist!"), ephemeral=True - ) + await interaction.response.send_message(content=error(f"Case #{case:,} does not exist!"), ephemeral=True) return if len(moderation.changes) > 25: await interaction.response.send_message( - content=error( - "Due to limitations with Discord's embed system, you cannot edit a case more than 25 times." - ), + content=error("Due to limitations with Discord's embed system, you cannot edit a case more than 25 times."), ephemeral=True, ) return @@ -869,21 +778,15 @@ class Aurora(commands.Cog): success, msg = await moderation.resolve(interaction.user.id, reason) except (ValueError, TypeError) as e: if e == ValueError: - await interaction.response.send_message( - content=error("This case has already been resolved!"), ephemeral=True - ) + await interaction.response.send_message(content=error("This case has already been resolved!"), ephemeral=True) elif e == TypeError: - await interaction.response.send_message( - content=error("This case type cannot be resolved!"), ephemeral=True - ) + await interaction.response.send_message(content=error("This case type cannot be resolved!"), ephemeral=True) embed = await case_factory( interaction=interaction, moderation=moderation, ) - await interaction.response.send_message( - content=f"✅ Moderation #{case:,} resolved!\n" + error(f"Resolve handler returned an error message: `{msg}`") if success is False else "", embed=embed - ) + await interaction.response.send_message(content=f"✅ Moderation #{case:,} resolved!\n" + error(f"Resolve handler returned an error message: `{msg}`") if success is False else "", embed=embed) ctx = await self.bot.get_context(interaction, cls=commands.Context) await log(ctx=ctx, moderation_id=case, resolved=True) @@ -917,47 +820,31 @@ class Aurora(commands.Cog): List the changes made to the case raw: bool Export the case to a JSON file or codeblock""" - permissions = check_permissions( - interaction.client.user, ["embed_links"], interaction - ) + permissions = check_permissions(interaction.client.user, ["embed_links"], interaction) if permissions: await interaction.response.send_message( - error( - f"I do not have the `{permissions}` permission, required for this action." - ), + error(f"I do not have the `{permissions}` permission, required for this action."), ephemeral=True, ) return if ephemeral is None: - ephemeral = ( - await config.user(interaction.user).history_ephemeral() - or await config.guild(interaction.guild).history_ephemeral() - or False - ) + ephemeral = await config.user(interaction.user).history_ephemeral() or await config.guild(interaction.guild).history_ephemeral() or False try: mod = await Moderation.find_by_id(interaction.client, case, interaction.guild.id) except ValueError: - await interaction.response.send_message( - content=error(f"Case #{case:,} does not exist!"), ephemeral=True - ) + await interaction.response.send_message(content=error(f"Case #{case:,} does not exist!"), ephemeral=True) return if raw: if raw.value == "file" or len(mod.to_json(2)) > 1800: - filename = ( - str(data_manager.cog_data_path(cog_instance=self)) - + str(os.sep) - + f"moderation_{interaction.guild.id}_case_{case}.json" - ) + filename = str(data_manager.cog_data_path(cog_instance=self)) + str(os.sep) + f"moderation_{interaction.guild.id}_case_{case}.json" with open(filename, "w", encoding="utf-8") as f: mod.to_json(2, f) if raw.value == "codeblock": - content = f"Case #{case:,} exported.\n" + warning( - "Case was too large to export as codeblock, so it has been uploaded as a `.json` file." - ) + content = f"Case #{case:,} exported.\n" + warning("Case was too large to export as codeblock, so it has been uploaded as a `.json` file.") else: content = f"Case #{case:,} exported." @@ -973,29 +860,19 @@ class Aurora(commands.Cog): os.remove(filename) return await interaction.response.send_message( - content=box(mod.to_json(2), 'json'), + content=box(mod.to_json(2), "json"), ephemeral=ephemeral, ) return if changes: - embed = await changes_factory( - interaction=interaction, moderation=mod - ) - await interaction.response.send_message( - embed=embed, ephemeral=ephemeral - ) + embed = await changes_factory(interaction=interaction, moderation=mod) + await interaction.response.send_message(embed=embed, ephemeral=ephemeral) elif evidenceformat: content = await evidenceformat_factory(moderation=mod) - await interaction.response.send_message( - content=content, ephemeral=ephemeral - ) + await interaction.response.send_message(content=content, ephemeral=ephemeral) else: - embed = await case_factory( - interaction=interaction, moderation=mod - ) - await interaction.response.send_message( - embed=embed, ephemeral=ephemeral - ) + embed = await case_factory(interaction=interaction, moderation=mod) + await interaction.response.send_message(embed=embed, ephemeral=ephemeral) return @app_commands.command(name="edit") @@ -1017,14 +894,10 @@ class Aurora(commands.Cog): duration: str What is the new duration? Does not reapply the moderation if it has already expired. """ - permissions = check_permissions( - interaction.client.user, ["embed_links"], interaction - ) + permissions = check_permissions(interaction.client.user, ["embed_links"], interaction) if permissions: await interaction.response.send_message( - error( - f"I do not have the `{permissions}` permission, required for this action." - ), + error(f"I do not have the `{permissions}` permission, required for this action."), ephemeral=True, ) return @@ -1033,16 +906,12 @@ class Aurora(commands.Cog): moderation = await Moderation.find_by_id(interaction.client, case, interaction.guild.id) old_moderation = moderation.model_copy() except ValueError: - await interaction.response.send_message( - content=error(f"Case #{case:,} does not exist!"), ephemeral=True - ) + await interaction.response.send_message(content=error(f"Case #{case:,} does not exist!"), ephemeral=True) return if len(moderation.changes) > 25: return await interaction.response.send_message( - content=error( - "Due to limitations with Discord's embed system, you cannot edit a case more than 25 times." - ), + content=error("Due to limitations with Discord's embed system, you cannot edit a case more than 25 times."), ephemeral=True, ) @@ -1053,18 +922,14 @@ class Aurora(commands.Cog): raise commands.BadArgument() moderation.duration = timedelta_from_relativedelta(relativedelta=parsed_time) except (commands.BadArgument, ValueError): - return await interaction.response.send_message( - error("Please provide a valid duration!"), ephemeral=True - ) + return await interaction.response.send_message(error("Please provide a valid duration!"), ephemeral=True) moderation.end_timestamp = moderation.timestamp + timedelta(seconds=moderation.duration.total_seconds()) try: success = await moderation.type.duration_edit_handler(interaction=interaction, old_moderation=old_moderation, new_moderation=moderation) except NotImplementedError: - return await interaction.response.send_message( - error("This case type does not support duration editing!"), ephemeral=True - ) + return await interaction.response.send_message(error("This case type does not support duration editing!"), ephemeral=True) if not success: return @@ -1072,27 +937,35 @@ class Aurora(commands.Cog): moderation.reason = reason if not reason and not duration: - return await interaction.response.send_message( - error("Please provide a new reason or duration to edit this case!"), ephemeral=True - ) + return await interaction.response.send_message(error("Please provide a new reason or duration to edit this case!"), ephemeral=True) if not moderation.changes: - moderation.changes.append(Change.from_dict(interaction.client, { - "type": "ORIGINAL", - "timestamp": old_moderation.timestamp, - "reason": old_moderation.reason, - "user_id": old_moderation.moderator_id, - "duration": timedelta_to_string(old_moderation.duration) if old_moderation.duration else None, - "end_timestamp": old_moderation.end_timestamp, - })) - moderation.changes.append(Change.from_dict(interaction.client, { - "type": "EDIT", - "timestamp": int(time.time()), - "reason": reason if reason else None, - "user_id": interaction.user.id, - "duration": timedelta_to_string(moderation.duration) if duration else None, - "end_timestamp": moderation.end_timestamp if duration else None, - })) + moderation.changes.append( + Change.from_dict( + interaction.client, + { + "type": "ORIGINAL", + "timestamp": old_moderation.timestamp, + "reason": old_moderation.reason, + "user_id": old_moderation.moderator_id, + "duration": timedelta_to_string(old_moderation.duration) if old_moderation.duration else None, + "end_timestamp": old_moderation.end_timestamp, + }, + ) + ) + moderation.changes.append( + Change.from_dict( + interaction.client, + { + "type": "EDIT", + "timestamp": int(time.time()), + "reason": reason if reason else None, + "user_id": interaction.user.id, + "duration": timedelta_to_string(moderation.duration) if duration else None, + "end_timestamp": moderation.end_timestamp if duration else None, + }, + ) + ) await moderation.update() embed = await case_factory(interaction=interaction, moderation=moderation) @@ -1135,7 +1008,7 @@ class Aurora(commands.Cog): except NotImplementedError: logger.warning("Expiry handler not implemented for expirable moderation type %s", moderation.type.key) continue - except Exception as e: # pylint: disable=broad-except + except Exception as e: # pylint: disable=broad-except logger.exception("Expiry handler failed for moderation %s with the type %s", moderation.id, moderation.type.key, exc_info=e) error_num += 1 continue @@ -1153,34 +1026,15 @@ class Aurora(commands.Cog): await Moderation.execute(bot=self.bot, guild_id=guild.id, query=expiry_query, parameters=(time.time(),), return_obj=False) per_guild_completion_time = (time.time() - time_per_guild) * 1000 - logger.debug( - "Completed expiry loop for %s (%s) in %sms with %s errors, %s users unbanned, %s roles added, and %s roles removed (%s other cases expired)", - guild.name, - guild.id, - f"{per_guild_completion_time:.6f}", - error_num, - unban_num, - addrole_num, - removerole_num, - other_num - ) + logger.debug("Completed expiry loop for %s (%s) in %sms with %s errors, %s users unbanned, %s roles added, and %s roles removed (%s other cases expired)", guild.name, guild.id, f"{per_guild_completion_time:.6f}", error_num, unban_num, addrole_num, removerole_num, other_num) global_unban_num = global_unban_num + unban_num global_addrole_num = global_addrole_num + addrole_num global_removerole_num = global_removerole_num + removerole_num global_other_num = global_other_num + other_num global_err_num = global_err_num + error_num - completion_time = (time.time() - current_time) * 1000 - logger.debug( - "Completed expiry loop in %sms with %s errors, %s users unbanned, %s roles added, and %s roles removed (%s other cases expired)", - f"{completion_time:.6f}", - global_err_num, - global_unban_num, - global_addrole_num, - global_removerole_num, - global_other_num - ) + logger.debug("Completed expiry loop in %sms with %s errors, %s users unbanned, %s roles added, and %s roles removed (%s other cases expired)", f"{completion_time:.6f}", global_err_num, global_unban_num, global_addrole_num, global_removerole_num, global_other_num) ######################################################################################################################## ### Configuration Commands # @@ -1252,18 +1106,10 @@ class Aurora(commands.Cog): @commands.admin() async def aurora_import_aurora(self, ctx: commands.Context): """Import moderation history from another bot using Aurora.""" - if ( - ctx.message.attachments - and ctx.message.attachments[0].content_type - == "application/json; charset=utf-8" - ): + if ctx.message.attachments and ctx.message.attachments[0].content_type == "application/json; charset=utf-8": file = await ctx.message.attachments[0].read() data: list[dict] = sorted(json.loads(file), key=lambda x: x["moderation_id"]) - message = await ctx.send( - warning( - "Are you sure you want to import moderations from another bot?\n**This will overwrite any moderations that already exist in this guild's moderation table.**\n*The import process will block the rest of your bot until it is complete.*" - ) - ) + message = await ctx.send(warning("Are you sure you want to import moderations from another bot?\n**This will overwrite any moderations that already exist in this guild's moderation table.**\n*The import process will block the rest of your bot until it is complete.*")) await message.edit(view=ImportAuroraView(60, ctx, message, data)) else: await ctx.send(error("Please provide a valid Aurora export file.")) @@ -1272,21 +1118,11 @@ class Aurora(commands.Cog): @commands.admin() async def aurora_import_galacticbot(self, ctx: commands.Context): """Import moderation history from GalacticBot.""" - if ( - ctx.message.attachments - and ctx.message.attachments[0].content_type - == "application/json; charset=utf-8" - ): - message = await ctx.send( - warning( - "Are you sure you want to import GalacticBot moderations?\n**This will overwrite any moderations that already exist in this guild's moderation table.**\n*The import process will block the rest of your bot until it is complete.*" - ) - ) + if ctx.message.attachments and ctx.message.attachments[0].content_type == "application/json; charset=utf-8": + message = await ctx.send(warning("Are you sure you want to import GalacticBot moderations?\n**This will overwrite any moderations that already exist in this guild's moderation table.**\n*The import process will block the rest of your bot until it is complete.*")) await message.edit(view=ImportGalacticBotView(60, ctx, message)) else: - await ctx.send( - error("Please provide a valid GalacticBot moderation export file.") - ) + await ctx.send(error("Please provide a valid GalacticBot moderation export file.")) @aurora.group(autohelp=True, name="convert") async def aurora_convert(self, ctx: commands.Context): @@ -1353,14 +1189,8 @@ class Aurora(commands.Cog): timestamp=datetime.now(), ) embed.set_thumbnail(url=self.bot.user.avatar.url) - embed.add_field( - name="Version", - value=f"[{self.__version__}]({self.__git__})" - ) - embed.add_field( - name="Author", - value=', '.join(self.__author__) - ) + embed.add_field(name="Version", value=f"[{self.__version__}]({self.__git__})") + embed.add_field(name="Author", value=", ".join(self.__author__)) if ctx.author.id in self.bot.owner_ids: results = await Moderation.execute(query="SELECT name FROM sqlite_master WHERE type='table';", return_obj=False) tables = [table[0] for table in results] @@ -1378,9 +1208,5 @@ class Aurora(commands.Cog): name="Database Stats", value=f"{bold('Table Count:')} {table_count:,}\n{bold('Row Count:')} {row_count:,}\n{bold('File Size:')} {filesize:,.0f} KB", ) - embed.add_field( - name="Moderation Types", - value=f"{len(type_registry)} registered types\n{box(', '.join(type_registry.keys()))}", - inline=False - ) + embed.add_field(name="Moderation Types", value=f"{len(type_registry)} registered types\n{box(', '.join(type_registry.keys()))}", inline=False) await ctx.send(embed=embed) diff --git a/aurora/info.json b/aurora/info.json index 2db0794..8229183 100644 --- a/aurora/info.json +++ b/aurora/info.json @@ -1,6 +1,6 @@ { - "author" : ["Seaswimmer (cswimr)"], - "install_msg" : "Thank you for installing Aurora!\nMost of this cog's functionality requires enabling slash commands.\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).", + "author" : ["cswimr"], + "install_msg" : "Thank you for installing Aurora!\nMost of this cog's functionality requires enabling slash commands.\nYou can find the source code of this cog [here](https://coastalcommits.com/cswimr/SeaCogs).", "name" : "Aurora", "short" : "A full replacement for Red's core Mod cogs.", "description" : "Aurora is a fully-featured moderation system. It is heavily inspired by GalacticBot, and is designed to be a more user-friendly alternative to Red's core Mod cogs. This cog stores all of its data in an SQLite database.", diff --git a/backup/backup.py b/backup/backup.py index 5d01c6b..dfc5397 100644 --- a/backup/backup.py +++ b/backup/backup.py @@ -197,7 +197,7 @@ class Backup(commands.Cog): cog_modules = [] for cog in cogs: # If you're forking this cog, make sure to change these strings! - if cog["name"] == "backup" and "SeaswimmerTheFsh/SeaCogs" in url: + if cog["name"] == "backup" and "cswimr/SeaCogs" in url: continue try: cog_module = await InstalledCog.convert(ctx, cog["name"]) @@ -233,7 +233,7 @@ class Backup(commands.Cog): commit = None # If you're forking this cog, make sure to change these strings! - if cog_name == "backup" and "SeaswimmerTheFsh/SeaCogs" in url: + if cog_name == "backup" and "cswimr/SeaCogs" in url: continue async with repository.checkout( diff --git a/backup/info.json b/backup/info.json index 075c208..2e465b0 100644 --- a/backup/info.json +++ b/backup/info.json @@ -1,6 +1,6 @@ { - "author" : ["SeaswimmerTheFsh (seasw.)"], - "install_msg" : "Thank you for installing Backup!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).", + "author" : ["cswimr"], + "install_msg" : "Thank you for installing Backup!\nYou can find the source code of this cog [here](https://coastalcommits.com/cswimr/SeaCogs).", "name" : "Backup", "short" : "A utility to make reinstalling repositories and cogs after migrating the bot far easier.", "description" : "A utility to make reinstalling repositories and cogs after migrating the bot far easier.", diff --git a/bible/info.json b/bible/info.json index dc33f92..b2da6d1 100644 --- a/bible/info.json +++ b/bible/info.json @@ -1,6 +1,6 @@ { - "author" : ["SeaswimmerTheFsh (seasw.)"], - "install_msg" : "Thank you for installing Bible!\nThis cog requires setting an API key for API.Bible. Please read the [documentation](https://seacogs.coastalcommits.com/bible/#setup) for more information.\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).", + "author" : ["cswimr"], + "install_msg" : "Thank you for installing Bible!\nThis cog requires setting an API key for API.Bible. Please read the [documentation](https://seacogs.coastalcommits.com/bible/#setup) for more information.\nYou can find the source code of this cog [here](https://coastalcommits.com/cswimr/SeaCogs).", "name" : "Bible", "short" : "Retrieve Bible verses from API.Bible.", "description" : "Retrieve Bible verses from the API.Bible API. This cog requires an API.Bible api key.", diff --git a/emojiinfo/info.json b/emojiinfo/info.json index febea9b..68a8de1 100644 --- a/emojiinfo/info.json +++ b/emojiinfo/info.json @@ -1,5 +1,5 @@ { - "author" : ["SeaswimmerTheFsh (seasw.)"], + "author" : ["cswimr"], "install_msg" : "Thank you for installing Emoji!", "name" : "Emoji", "short" : "Retrieve information about emojis.", diff --git a/info.json b/info.json index 816e30b..c679a52 100644 --- a/info.json +++ b/info.json @@ -1,9 +1,9 @@ { "author": [ - "SeaswimmerTheFsh (seasw.)" + "cswimr" ], - "install_msg": "Thanks for installing my repo!\n\nIf you have any issues with any of the cogs, please create an issue [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs/issues) or join my [Discord Server](https://discord.gg/eMUMe77Yb8 ).", + "install_msg": "Thanks for installing my repo!\n\nIf you have any issues with any of the cogs, please create an issue [here](https://coastalcommits.com/cswimr/SeaCogs/issues) or join my [Discord Server](https://discord.gg/eMUMe77Yb8 ).", "index_name": "sea-cogs", - "short": "Various cogs for Red, by SeaswimmerTheFsh (seasw.)", - "description": "Various cogs for Red, by SeaswimmerTheFsh (seasw.)" + "short": "Various cogs for Red, by cswimr", + "description": "Various cogs for Red, by cswimr" } diff --git a/mkdocs.yml b/mkdocs.yml index 2777b5f..9d61aee 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,12 +1,12 @@ site_name: SeaCogs Documentation site_url: !ENV [SITE_URL, 'https://seacogs.coastalcommits.com'] repo_name: CoastalCommits -repo_url: https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs +repo_url: https://coastalcommits.com/cswimr/SeaCogs edit_uri: !ENV [EDIT_URI, 'src/branch/main/.docs'] -copyright: Copyright © 2023-2024, SeaswimmerTheFsh +copyright: Copyright © 2023-2024, cswimr docs_dir: .docs -site_author: SeaswimmerTheFsh +site_author: cswimr site_description: Documentation for my Red-DiscordBot Cogs. nav: @@ -30,7 +30,7 @@ nav: plugins: - git-authors - search - #- social + - social - git-revision-date-localized: enable_creation_date: true type: timeago @@ -113,3 +113,5 @@ watch: - ./bible - ./nerdify - ./pterodactyl + - ./emojiinfo + - ./antipolls diff --git a/nerdify/info.json b/nerdify/info.json index 38730c7..1d06223 100644 --- a/nerdify/info.json +++ b/nerdify/info.json @@ -1,6 +1,6 @@ { - "author" : ["SeaswimmerTheFsh (seasw.)"], - "install_msg" : "Thank you for installing Nerdify!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs). Based off of PhasecoreX's [UwU]() cog.", + "author" : ["cswimr"], + "install_msg" : "Thank you for installing Nerdify!\nYou can find the source code of this cog [here](https://coastalcommits.com/cswimr/SeaCogs). Based off of PhasecoreX's [UwU]() cog.", "name" : "Nerdify", "short" : "Nerdify your text!", "description" : "Nerdify your text!", diff --git a/pterodactyl/info.json b/pterodactyl/info.json index 0a10241..7c4545a 100644 --- a/pterodactyl/info.json +++ b/pterodactyl/info.json @@ -1,6 +1,6 @@ { - "author" : ["SeaswimmerTheFsh (seasw.)"], - "install_msg" : "Thank you for installing Pterodactyl!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).\nDocumentation can be found [here](https://seacogs.coastalcommits.com/pterodactyl ).", + "author" : ["cswimr"], + "install_msg" : "Thank you for installing Pterodactyl!\nYou can find the source code of this cog [here](https://coastalcommits.com/cswimr/SeaCogs).\nDocumentation can be found [here](https://seacogs.coastalcommits.com/pterodactyl ).", "name" : "Pterodactyl", "short" : "Interface with Pterodactyl through websockets.", "description" : "Interface with Pterodactyl through websockets.", @@ -9,7 +9,7 @@ "disabled": false, "min_bot_version": "3.5.0", "min_python_version": [3, 8, 0], - "requirements": ["git+https://github.com/SeaswimmerTheFsh/pydactyl", "websockets"], + "requirements": ["git+https://github.com/cswimr/pydactyl", "websockets"], "tags": [ "pterodactyl", "minecraft", diff --git a/pyproject.toml b/pyproject.toml index 5e1301b..327602c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "seacogs" version = "0.1.0" description = "My assorted cogs for Red-DiscordBot." -authors = ["SeaswimmerTheFsh"] +authors = ["cswimr"] license = "MPL 2" readme = "README.md" package-mode = false diff --git a/seautils/info.json b/seautils/info.json index 7356137..2f8fa83 100644 --- a/seautils/info.json +++ b/seautils/info.json @@ -1,6 +1,6 @@ { - "author" : ["SeaswimmerTheFsh (seasw.)"], - "install_msg" : "Thank you for installing SeaUtils!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).", + "author" : ["cswimr"], + "install_msg" : "Thank you for installing SeaUtils!\nYou can find the source code of this cog [here](https://coastalcommits.com/cswimr/SeaCogs).", "name" : "SeaUtils", "short" : "A collection of useful utilities.", "description" : "A collection of useful utilities.", -- 2.45.3 From 03c43710e08219686a47a67b6402426acc74fa71 Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 28 Aug 2024 17:01:58 -0400 Subject: [PATCH 350/376] chore(poetry): update deps --- poetry.lock | 2850 --------------------------------------------------- 1 file changed, 2850 deletions(-) delete mode 100644 poetry.lock diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 627a8a8..0000000 --- a/poetry.lock +++ /dev/null @@ -1,2850 +0,0 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. - -[[package]] -name = "aiohttp" -version = "3.9.5" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.8" -files = [ - {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7"}, - {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c"}, - {file = "aiohttp-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10"}, - {file = "aiohttp-3.9.5-cp310-cp310-win32.whl", hash = "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb"}, - {file = "aiohttp-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb"}, - {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342"}, - {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d"}, - {file = "aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75"}, - {file = "aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6"}, - {file = "aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a"}, - {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"}, - {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"}, - {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"}, - {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"}, - {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"}, - {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8"}, - {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8"}, - {file = "aiohttp-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe"}, - {file = "aiohttp-3.9.5-cp38-cp38-win32.whl", hash = "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da"}, - {file = "aiohttp-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a"}, - {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed"}, - {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a"}, - {file = "aiohttp-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2"}, - {file = "aiohttp-3.9.5-cp39-cp39-win32.whl", hash = "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09"}, - {file = "aiohttp-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1"}, - {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"}, -] - -[package.dependencies] -aiosignal = ">=1.1.2" -attrs = ">=17.3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" - -[package.extras] -speedups = ["Brotli", "aiodns", "brotlicffi"] - -[[package]] -name = "aiohttp-json-rpc" -version = "0.13.3" -description = "Implementation JSON-RPC 2.0 server and client using aiohttp on top of websockets transport" -optional = false -python-versions = ">=3.5" -files = [ - {file = "aiohttp-json-rpc-0.13.3.tar.gz", hash = "sha256:6237a104478c22c6ef96c7227a01d6832597b414e4b79a52d85593356a169e99"}, - {file = "aiohttp_json_rpc-0.13.3-py3-none-any.whl", hash = "sha256:4fbd197aced61bd2df7ae3237ead7d3e08833c2ccf48b8581e1828c95ebee680"}, -] - -[package.dependencies] -aiohttp = ">=3,<4" - -[[package]] -name = "aiosignal" -version = "1.3.1" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.7" -files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - -[[package]] -name = "aiosqlite" -version = "0.20.0" -description = "asyncio bridge to the standard sqlite3 module" -optional = false -python-versions = ">=3.8" -files = [ - {file = "aiosqlite-0.20.0-py3-none-any.whl", hash = "sha256:36a1deaca0cac40ebe32aac9977a6e2bbc7f5189f23f4a54d5908986729e5bd6"}, - {file = "aiosqlite-0.20.0.tar.gz", hash = "sha256:6d35c8c256637f4672f843c31021464090805bf925385ac39473fb16eaaca3d7"}, -] - -[package.dependencies] -typing_extensions = ">=4.0" - -[package.extras] -dev = ["attribution (==1.7.0)", "black (==24.2.0)", "coverage[toml] (==7.4.1)", "flake8 (==7.0.0)", "flake8-bugbear (==24.2.6)", "flit (==3.9.0)", "mypy (==1.8.0)", "ufmt (==2.3.0)", "usort (==1.0.8.post1)"] -docs = ["sphinx (==7.2.6)", "sphinx-mdinclude (==0.5.3)"] - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "apsw" -version = "3.46.1.0" -description = "Another Python SQLite Wrapper" -optional = false -python-versions = ">=3.8" -files = [ - {file = "apsw-3.46.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ebfaf4d84bc61ecf79587acf31a31f732be72cb8fc8c999ce9453147a2e57dc"}, - {file = "apsw-3.46.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2545b9c885f98d7dedf9c0f9c485f84d39c5a40352b8a3c3f05f99e1e1d2ae73"}, - {file = "apsw-3.46.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5b83967c1b68877976a06bb8a2eb314b1f8923d787f6d7cd41b48776847bfe6"}, - {file = "apsw-3.46.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:110dae383750f75fc57d63ea14a759e4309886e1dd5243993db7eaa8f9d06d90"}, - {file = "apsw-3.46.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e403aab2b5653152e85341218a49d73eed66319f0deccce5db21f7a89def394a"}, - {file = "apsw-3.46.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3382459357f0819b631087b32818a502da47c84ddea76132d76ec02aa473af45"}, - {file = "apsw-3.46.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d43d80bbd497ddb86fa5774bd80df1825253a3765e01e707cbcc6242f06f21eb"}, - {file = "apsw-3.46.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:402233ed77b7bd99f81c5b68bd8201dd1c4c1dedc40d12871f709b922842d5c6"}, - {file = "apsw-3.46.1.0-cp310-cp310-win32.whl", hash = "sha256:c17dab34c487ee562f81672f6bf3c067493e017d1a8c816485e6de06ce25f620"}, - {file = "apsw-3.46.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:9484b47e792ad54b36fced07b9ff91b9ab32f0d7de44da3a9b5fa9d78e28ddae"}, - {file = "apsw-3.46.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8acacf3a0187cbd4c82c9eaa2c7e2704c13997a351efdffbdfa69ea1778bda1f"}, - {file = "apsw-3.46.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2fcc5fd76a4a21fb1cc1694495e221206a46d932c675ba5dda8f070262347e0b"}, - {file = "apsw-3.46.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca319360995762fbed9e7d252c3ae4ea84af2d7bc1aef21adbcb4e088a416373"}, - {file = "apsw-3.46.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42036093f8b7dd66bbb18b717ef6dfa62c4a2acd9bcdf05fdf5caedf77a47c01"}, - {file = "apsw-3.46.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4d54efc7d7d58b782dc84f29c5d25d190984dec20d8233484d3b092ded1241e1"}, - {file = "apsw-3.46.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3864151c23edd3a232e059925bd37044e2c1b90f20ba1d0b46005d0e5d97d10d"}, - {file = "apsw-3.46.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3e42ebb5997fcd6234cdb888f641ca37a7e9d03c13c4f2e1e0ac66151a182e79"}, - {file = "apsw-3.46.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7ea887719b60d48ac569eb42594f7dd772ab2b2287aaae9c9a007789467aa26a"}, - {file = "apsw-3.46.1.0-cp311-cp311-win32.whl", hash = "sha256:67754bc4c0b2dda1a112f0adfdd6d25c2f724d8c086decb9690349056f799eed"}, - {file = "apsw-3.46.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fef6891bc388d92ac8208db2e6f5cd90bd75a64930147f515f2e28526a278c81"}, - {file = "apsw-3.46.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a892c3dccbb2f96611a0707fb4cf1573c88a4a2898b45f013a202557f602faa8"}, - {file = "apsw-3.46.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e01e2cf7faae0d86540e9c638778c98cdd14b365136d9b11d2a0a7dfe4893f3"}, - {file = "apsw-3.46.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf96999557f5ccc5c8424b0c8637447652994e26b4fe87b72626def24c53dcf1"}, - {file = "apsw-3.46.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925c01733c0de8adf7f3cbf299e4bcb38961b62de4436f8704e5ff9800523a7c"}, - {file = "apsw-3.46.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:979f1fca9ec09c1e8bd466ad17fde25dffb06ea621bd8b7c08e404d042c4d362"}, - {file = "apsw-3.46.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e02c614ca3afceb6c80349485dd2d49fea584a885794ca732513d8aa746781d7"}, - {file = "apsw-3.46.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c9c130253eba2f70547253f54db05d0e6aa41962d9d712b9e1b8efba1ea2990b"}, - {file = "apsw-3.46.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:999f8fc2607a98ecfddb9d266bd746ae9a08dfa67841700ccfb0108a9cfe9104"}, - {file = "apsw-3.46.1.0-cp312-cp312-win32.whl", hash = "sha256:0f864580269c5cfe7aed899057a6e76f06940d2bc4134c2e32d36aadad0b3e29"}, - {file = "apsw-3.46.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:fb770bbe185d3cd6609bb245e22108490c81a025e3be82cd278116b5e21cbbee"}, - {file = "apsw-3.46.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8113139847f1ad7023a2b8ab8cee15ceec2406c9fbc6709c64a029947485bc23"}, - {file = "apsw-3.46.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:038e9550dc24413a12fde36492ab275410c35982e97d33cc5fd7c18325bbc9e1"}, - {file = "apsw-3.46.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1779f6d512d07b1fa914d268c42ac47170fd41aeae3352c3ce1c5c9f410496b9"}, - {file = "apsw-3.46.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b2497696ccb5ac928ba3bbae988a82e00d0be3242b7bdd0553ce4447bdcc73b"}, - {file = "apsw-3.46.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b182bafe729822f7a934d081d9190b76e0dae1f5f098efa7430fcdd38e3a315"}, - {file = "apsw-3.46.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d08cf0df8f58b4bdf8c0b7a4c8e70f2a8840be631f40dae848b384636a22fe0d"}, - {file = "apsw-3.46.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7d37e2f6e1a22bb1a82905237b4d433124ccc53a62f918b9cf7c42c6e49241d0"}, - {file = "apsw-3.46.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3d49e1996c13661011505cd53502e580c63062eafeebaebcd80ec34b435475c4"}, - {file = "apsw-3.46.1.0-cp313-cp313-win32.whl", hash = "sha256:42039f5d650ef1bb12e1304aebe47338c20bead38b41bae0f22f98e78cc6855c"}, - {file = "apsw-3.46.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c37abd9f344aefa11c3fe213738c1db4fe49bacef1aee360087fa1ac840b1c4"}, - {file = "apsw-3.46.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a8cd20bff7e1294d8b779153f2ff0fbd7821c4b479b31caef4b1427f3b443307"}, - {file = "apsw-3.46.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9b7e6395b8b20681a9b4a5f9621c9b1800e32a332cf75010bc8fde1d43465610"}, - {file = "apsw-3.46.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:348c88254bf05527909494a690d846cae5a95dd87e2359788b4ccb4d4a56c64a"}, - {file = "apsw-3.46.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d508bcbf81d0f8339572e8e9775cc45991d2548f19605a5445d8dc05f23910f4"}, - {file = "apsw-3.46.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7bf2ca987fcb136bdb23c241e0b18469a2c45255bee80d7884ff56bc6d5461"}, - {file = "apsw-3.46.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:81f7c3ca9267a290922ddef73293c86bc373afc128867412d6f844a4a271a381"}, - {file = "apsw-3.46.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:63278cee066c2365327d5d5976570834a559b9f64068186038af29b08063ba5a"}, - {file = "apsw-3.46.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f53f489ebb024464e9223de9d8a139a2e206d33de1ab0538a01962dfe40c6526"}, - {file = "apsw-3.46.1.0-cp38-cp38-win32.whl", hash = "sha256:fc60738ad5594f72eb611178f161869dc7ff02789468c963296c4da743415e55"}, - {file = "apsw-3.46.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:d4f48ef4f7d061b819cc35878ac661835e84debe17886abbefa7b0f935a24b85"}, - {file = "apsw-3.46.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:85552b0696342e601420e02beba02ef8b1544eeb92895d771d795c1e5e696285"}, - {file = "apsw-3.46.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b0b71f1f76200907782c6bd17b6b623b4ccc95f6d4187f0361c8f5c1a3e9fd81"}, - {file = "apsw-3.46.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:755f0cd2a3b70436e69b347ffb0774cca32db96ca7cf9b8660f29226d8eec2b1"}, - {file = "apsw-3.46.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c95adc014380489b37c97a70ab6ead31a1774d35f921e309407241a035d1485"}, - {file = "apsw-3.46.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:029f03385379882a6ce5df9713ebed86dde1cdf0435181431c264d1333719d13"}, - {file = "apsw-3.46.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fed308f151dab9ca3052ee9c35beedfb5fd788734b24514e6bedf58f6f86f5d"}, - {file = "apsw-3.46.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:66773bc9b0428a4178bb5dd0dbbca00104e184252832ec1bcd81712a29ef65ed"}, - {file = "apsw-3.46.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:55d248a9d55d39d366f532f4ae70bdf7f2b8269f5e75b71742e1bdf039853151"}, - {file = "apsw-3.46.1.0-cp39-cp39-win32.whl", hash = "sha256:4739482e35f5da3cc694959c43c813433b444ce865b60d5d78ba0734eb4a3840"}, - {file = "apsw-3.46.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:2bffff5cbfcd84ce7409d3ecb885b4707a264effbaa950f0ba5c68eaaca1ad5d"}, - {file = "apsw-3.46.1.0.tar.gz", hash = "sha256:96e3dfad1fd0cc77a778aa6b27468292041a8e9cb1f2dcf06bd773762c9b0c0c"}, -] - -[[package]] -name = "argcomplete" -version = "3.5.0" -description = "Bash tab completion for argparse" -optional = false -python-versions = ">=3.8" -files = [ - {file = "argcomplete-3.5.0-py3-none-any.whl", hash = "sha256:d4bcf3ff544f51e16e54228a7ac7f486ed70ebf2ecfe49a63a91171c76bf029b"}, - {file = "argcomplete-3.5.0.tar.gz", hash = "sha256:4349400469dccfb7950bb60334a680c58d88699bff6159df61251878dc6bf74b"}, -] - -[package.extras] -test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] - -[[package]] -name = "astroid" -version = "3.3.3" -description = "An abstract syntax tree for Python with inference support." -optional = false -python-versions = ">=3.9.0" -files = [ - {file = "astroid-3.3.3-py3-none-any.whl", hash = "sha256:2d79acfd3c594b6a2d4141fea98a1d62ab4a52e54332b1f1ddcf07b652cc5c0f"}, - {file = "astroid-3.3.3.tar.gz", hash = "sha256:63f8c5370d9bad8294163c87b2d440a7fdf546be6c72bbeac0549c93244dbd72"}, -] - -[[package]] -name = "attrs" -version = "24.2.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -files = [ - {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, - {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, -] - -[package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] - -[[package]] -name = "babel" -version = "2.16.0" -description = "Internationalization utilities" -optional = false -python-versions = ">=3.8" -files = [ - {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, - {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, -] - -[package.extras] -dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] - -[[package]] -name = "beautifulsoup4" -version = "4.12.3" -description = "Screen-scraping library" -optional = false -python-versions = ">=3.6.0" -files = [ - {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, - {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, -] - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -cchardet = ["cchardet"] -chardet = ["chardet"] -charset-normalizer = ["charset-normalizer"] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "blinker" -version = "1.8.2" -description = "Fast, simple object-to-object and broadcast signaling" -optional = false -python-versions = ">=3.8" -files = [ - {file = "blinker-1.8.2-py3-none-any.whl", hash = "sha256:1779309f71bf239144b9399d06ae925637cf6634cf6bd131104184531bf67c01"}, - {file = "blinker-1.8.2.tar.gz", hash = "sha256:8f77b09d3bf7c795e969e9486f39c2c5e9c39d4ee07424be2bc594ece9642d83"}, -] - -[[package]] -name = "brotli" -version = "1.1.0" -description = "Python bindings for the Brotli compression library" -optional = false -python-versions = "*" -files = [ - {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752"}, - {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9"}, - {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3"}, - {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d"}, - {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e"}, - {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e"}, - {file = "Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2"}, - {file = "Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128"}, - {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc"}, - {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6"}, - {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd"}, - {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf"}, - {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61"}, - {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8"}, - {file = "Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50"}, - {file = "Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1"}, - {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409"}, - {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2"}, - {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451"}, - {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91"}, - {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408"}, - {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966"}, - {file = "Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0"}, - {file = "Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951"}, - {file = "Brotli-1.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1"}, - {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d"}, - {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b"}, - {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112"}, - {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fdc3ff3bfccdc6b9cc7c342c03aa2400683f0cb891d46e94b64a197910dc4064"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2"}, - {file = "Brotli-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460"}, - {file = "Brotli-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579"}, - {file = "Brotli-1.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c"}, - {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985"}, - {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60"}, - {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a"}, - {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438"}, - {file = "Brotli-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95"}, - {file = "Brotli-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68"}, - {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3"}, - {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208"}, - {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7"}, - {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751"}, - {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48"}, - {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596"}, - {file = "Brotli-1.1.0-cp38-cp38-win32.whl", hash = "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b"}, - {file = "Brotli-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0"}, - {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a"}, - {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f"}, - {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9"}, - {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf"}, - {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac"}, - {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59"}, - {file = "Brotli-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64"}, - {file = "Brotli-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467"}, - {file = "Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724"}, -] - -[[package]] -name = "cairocffi" -version = "1.7.1" -description = "cffi-based cairo bindings for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "cairocffi-1.7.1-py3-none-any.whl", hash = "sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f"}, - {file = "cairocffi-1.7.1.tar.gz", hash = "sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b"}, -] - -[package.dependencies] -cffi = ">=1.1.0" - -[package.extras] -doc = ["sphinx", "sphinx_rtd_theme"] -test = ["numpy", "pikepdf", "pytest", "ruff"] -xcb = ["xcffib (>=1.4.0)"] - -[[package]] -name = "cairosvg" -version = "2.7.1" -description = "A Simple SVG Converter based on Cairo" -optional = false -python-versions = ">=3.5" -files = [ - {file = "CairoSVG-2.7.1-py3-none-any.whl", hash = "sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b"}, - {file = "CairoSVG-2.7.1.tar.gz", hash = "sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0"}, -] - -[package.dependencies] -cairocffi = "*" -cssselect2 = "*" -defusedxml = "*" -pillow = "*" -tinycss2 = "*" - -[package.extras] -doc = ["sphinx", "sphinx-rtd-theme"] -test = ["flake8", "isort", "pytest"] - -[[package]] -name = "certifi" -version = "2024.8.30" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, - {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, -] - -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "colorthief" -version = "0.2.1" -description = "A module for grabbing the color palette from an image." -optional = false -python-versions = "*" -files = [ - {file = "colorthief-0.2.1-py2.py3-none-any.whl", hash = "sha256:b04fc8ce5cf9c888768745e29cb19b7b688d5711af6fba26e8057debabec56b9"}, - {file = "colorthief-0.2.1.tar.gz", hash = "sha256:079cb0c95bdd669c4643e2f7494de13b0b6029d5cdbe2d74d5d3c3386bd57221"}, -] - -[package.dependencies] -Pillow = "*" - -[[package]] -name = "cssselect2" -version = "0.7.0" -description = "CSS selectors for Python ElementTree" -optional = false -python-versions = ">=3.7" -files = [ - {file = "cssselect2-0.7.0-py3-none-any.whl", hash = "sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969"}, - {file = "cssselect2-0.7.0.tar.gz", hash = "sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a"}, -] - -[package.dependencies] -tinycss2 = "*" -webencodings = "*" - -[package.extras] -doc = ["sphinx", "sphinx_rtd_theme"] -test = ["flake8", "isort", "pytest"] - -[[package]] -name = "defusedxml" -version = "0.7.1" -description = "XML bomb protection for Python stdlib modules" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, - {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, -] - -[[package]] -name = "dill" -version = "0.3.8" -description = "serialize all of Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, - {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, -] - -[package.extras] -graph = ["objgraph (>=1.7.2)"] -profile = ["gprof2dot (>=2022.7.29)"] - -[[package]] -name = "discord-py" -version = "2.4.0" -description = "A Python wrapper for the Discord API" -optional = false -python-versions = ">=3.8" -files = [ - {file = "discord.py-2.4.0-py3-none-any.whl", hash = "sha256:b8af6711c70f7e62160bfbecb55be699b5cb69d007426759ab8ab06b1bd77d1d"}, - {file = "discord_py-2.4.0.tar.gz", hash = "sha256:d07cb2a223a185873a1d0ee78b9faa9597e45b3f6186df21a95cec1e9bcdc9a5"}, -] - -[package.dependencies] -aiohttp = ">=3.7.4,<4" - -[package.extras] -docs = ["sphinx (==4.4.0)", "sphinx-inline-tabs (==2023.4.21)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "sphinxcontrib-websupport (==1.2.4)", "typing-extensions (>=4.3,<5)"] -speed = ["Brotli", "aiodns (>=1.1)", "cchardet (==2.1.7)", "orjson (>=3.5.4)"] -test = ["coverage[toml]", "pytest", "pytest-asyncio", "pytest-cov", "pytest-mock", "typing-extensions (>=4.3,<5)", "tzdata"] -voice = ["PyNaCl (>=1.3.0,<1.6)"] - -[[package]] -name = "distro" -version = "1.9.0" -description = "Distro - an OS platform information API" -optional = false -python-versions = ">=3.6" -files = [ - {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, - {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, -] - -[[package]] -name = "flask" -version = "3.0.3" -description = "A simple framework for building complex web applications." -optional = false -python-versions = ">=3.8" -files = [ - {file = "flask-3.0.3-py3-none-any.whl", hash = "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3"}, - {file = "flask-3.0.3.tar.gz", hash = "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842"}, -] - -[package.dependencies] -blinker = ">=1.6.2" -click = ">=8.1.3" -itsdangerous = ">=2.1.2" -Jinja2 = ">=3.1.2" -Werkzeug = ">=3.0.0" - -[package.extras] -async = ["asgiref (>=3.2)"] -dotenv = ["python-dotenv"] - -[[package]] -name = "frozenlist" -version = "1.4.1" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -files = [ - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, - {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, - {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, - {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, - {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, - {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, - {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, - {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, - {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, - {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, - {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, - {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, - {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, -] - -[[package]] -name = "ghp-import" -version = "2.1.0" -description = "Copy your docs directly to the gh-pages branch." -optional = false -python-versions = "*" -files = [ - {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, - {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, -] - -[package.dependencies] -python-dateutil = ">=2.8.1" - -[package.extras] -dev = ["flake8", "markdown", "twine", "wheel"] - -[[package]] -name = "gitdb" -version = "4.0.11" -description = "Git Object Database" -optional = false -python-versions = ">=3.7" -files = [ - {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, - {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.43" -description = "GitPython is a Python library used to interact with Git repositories" -optional = false -python-versions = ">=3.7" -files = [ - {file = "GitPython-3.1.43-py3-none-any.whl", hash = "sha256:eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff"}, - {file = "GitPython-3.1.43.tar.gz", hash = "sha256:35f314a9f878467f5453cc1fee295c3e18e52f1b99f10f6cf5b1682e968a9e7c"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" - -[package.extras] -doc = ["sphinx (==4.3.2)", "sphinx-autodoc-typehints", "sphinx-rtd-theme", "sphinxcontrib-applehelp (>=1.0.2,<=1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (>=2.0.0,<=2.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)"] -test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions"] - -[[package]] -name = "griffe" -version = "1.3.1" -description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." -optional = false -python-versions = ">=3.8" -files = [ - {file = "griffe-1.3.1-py3-none-any.whl", hash = "sha256:940aeb630bc3054b4369567f150b6365be6f11eef46b0ed8623aea96e6d17b19"}, - {file = "griffe-1.3.1.tar.gz", hash = "sha256:3f86a716b631a4c0f96a43cb75d05d3c85975003c20540426c0eba3b0581c56a"}, -] - -[package.dependencies] -colorama = ">=0.4" - -[[package]] -name = "idna" -version = "3.8" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -files = [ - {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, - {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, -] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "itsdangerous" -version = "2.2.0" -description = "Safely pass data to untrusted environments and back." -optional = false -python-versions = ">=3.8" -files = [ - {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, - {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, -] - -[[package]] -name = "jinja2" -version = "3.1.4" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -files = [ - {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, - {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "markdown" -version = "3.7" -description = "Python implementation of John Gruber's Markdown." -optional = false -python-versions = ">=3.8" -files = [ - {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"}, - {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"}, -] - -[package.extras] -docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] -testing = ["coverage", "pyyaml"] - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "markdownify" -version = "0.12.1" -description = "Convert HTML to markdown." -optional = false -python-versions = "*" -files = [ - {file = "markdownify-0.12.1-py3-none-any.whl", hash = "sha256:a3805abd8166dbb7b27783c5599d91f54f10d79894b2621404d85b333c7ce561"}, - {file = "markdownify-0.12.1.tar.gz", hash = "sha256:1fb08c618b30e0ee7a31a39b998f44a18fb28ab254f55f4af06b6d35a2179e27"}, -] - -[package.dependencies] -beautifulsoup4 = ">=4.9,<5" -six = ">=1.15,<2" - -[[package]] -name = "markupsafe" -version = "2.1.5" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.7" -files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, -] - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - -[[package]] -name = "mergedeep" -version = "1.3.4" -description = "A deep merge function for 🐍." -optional = false -python-versions = ">=3.6" -files = [ - {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, - {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, -] - -[[package]] -name = "mkdocs" -version = "1.5.3" -description = "Project documentation with Markdown." -optional = false -python-versions = ">=3.7" -files = [ - {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"}, - {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"}, -] - -[package.dependencies] -click = ">=7.0" -colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} -ghp-import = ">=1.0" -jinja2 = ">=2.11.1" -markdown = ">=3.2.1" -markupsafe = ">=2.0.1" -mergedeep = ">=1.3.4" -packaging = ">=20.5" -pathspec = ">=0.11.1" -platformdirs = ">=2.2.0" -pyyaml = ">=5.1" -pyyaml-env-tag = ">=0.1" -watchdog = ">=2.0" - -[package.extras] -i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] - -[[package]] -name = "mkdocs-autorefs" -version = "1.2.0" -description = "Automatically link across pages in MkDocs." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_autorefs-1.2.0-py3-none-any.whl", hash = "sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f"}, - {file = "mkdocs_autorefs-1.2.0.tar.gz", hash = "sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f"}, -] - -[package.dependencies] -Markdown = ">=3.3" -markupsafe = ">=2.0.1" -mkdocs = ">=1.1" - -[[package]] -name = "mkdocs-git-authors-plugin" -version = "0.7.2" -description = "Mkdocs plugin to display git authors of a page" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mkdocs-git-authors-plugin-0.7.2.tar.gz", hash = "sha256:f541730e4cabdafa0ac758c94d28ba5e8ddca4c859e5de4c89f1226cb6ccd0ad"}, - {file = "mkdocs_git_authors_plugin-0.7.2-py3-none-any.whl", hash = "sha256:c8a2784a867db79ad3b477a96ee96875d17b09192b6d3be71f08df25afff76c4"}, -] - -[package.dependencies] -mkdocs = ">=1.0" - -[[package]] -name = "mkdocs-git-revision-date-localized-plugin" -version = "1.2.2" -description = "Mkdocs plugin that enables displaying the localized date of the last git modification of a markdown file." -optional = false -python-versions = ">=3.6" -files = [ - {file = "mkdocs-git-revision-date-localized-plugin-1.2.2.tar.gz", hash = "sha256:0c43a9aac1fa69df99a823f833cc223bac9967b60d5261a857761c7c6e3b30de"}, - {file = "mkdocs_git_revision_date_localized_plugin-1.2.2-py3-none-any.whl", hash = "sha256:85c7fe9ab06e7a63c4e522c26fee8b51d357cb8cbe605064501ad80f4f31cb94"}, -] - -[package.dependencies] -babel = ">=2.7.0" -GitPython = "*" -mkdocs = ">=1.0" -pytz = "*" - -[[package]] -name = "mkdocs-material" -version = "9.5.18" -description = "Documentation that simply works" -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_material-9.5.18-py3-none-any.whl", hash = "sha256:1e0e27fc9fe239f9064318acf548771a4629d5fd5dfd45444fd80a953fe21eb4"}, - {file = "mkdocs_material-9.5.18.tar.gz", hash = "sha256:a43f470947053fa2405c33995f282d24992c752a50114f23f30da9d8d0c57e62"}, -] - -[package.dependencies] -babel = ">=2.10,<3.0" -cairosvg = {version = ">=2.6,<3.0", optional = true, markers = "extra == \"imaging\""} -colorama = ">=0.4,<1.0" -jinja2 = ">=3.0,<4.0" -markdown = ">=3.2,<4.0" -mkdocs = ">=1.5.3,<1.6.0" -mkdocs-material-extensions = ">=1.3,<2.0" -paginate = ">=0.5,<1.0" -pillow = {version = ">=10.2,<11.0", optional = true, markers = "extra == \"imaging\""} -pygments = ">=2.16,<3.0" -pymdown-extensions = ">=10.2,<11.0" -regex = ">=2022.4" -requests = ">=2.26,<3.0" - -[package.extras] -git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"] -imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"] -recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] - -[[package]] -name = "mkdocs-material-extensions" -version = "1.3.1" -description = "Extension pack for Python Markdown and MkDocs Material." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, - {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, -] - -[[package]] -name = "mkdocs-redirects" -version = "1.2.1" -description = "A MkDocs plugin for dynamic page redirects to prevent broken links." -optional = false -python-versions = ">=3.6" -files = [ - {file = "mkdocs-redirects-1.2.1.tar.gz", hash = "sha256:9420066d70e2a6bb357adf86e67023dcdca1857f97f07c7fe450f8f1fb42f861"}, - {file = "mkdocs_redirects-1.2.1-py3-none-any.whl", hash = "sha256:497089f9e0219e7389304cffefccdfa1cac5ff9509f2cb706f4c9b221726dffb"}, -] - -[package.dependencies] -mkdocs = ">=1.1.1" - -[package.extras] -dev = ["autoflake", "black", "isort", "pytest", "twine (>=1.13.0)"] -release = ["twine (>=1.13.0)"] -test = ["autoflake", "black", "isort", "pytest"] - -[[package]] -name = "mkdocstrings" -version = "0.24.0" -description = "Automatic documentation from sources, for MkDocs." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocstrings-0.24.0-py3-none-any.whl", hash = "sha256:f4908560c10f587326d8f5165d1908817b2e280bbf707607f601c996366a2264"}, - {file = "mkdocstrings-0.24.0.tar.gz", hash = "sha256:222b1165be41257b494a9d29b14135d2b7ca43f38161d5b10caae03b87bd4f7e"}, -] - -[package.dependencies] -click = ">=7.0" -Jinja2 = ">=2.11.1" -Markdown = ">=3.3" -MarkupSafe = ">=1.1" -mkdocs = ">=1.4" -mkdocs-autorefs = ">=0.3.1" -mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""} -platformdirs = ">=2.2.0" -pymdown-extensions = ">=6.3" - -[package.extras] -crystal = ["mkdocstrings-crystal (>=0.3.4)"] -python = ["mkdocstrings-python (>=0.5.2)"] -python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] - -[[package]] -name = "mkdocstrings-python" -version = "1.8.0" -description = "A Python handler for mkdocstrings." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocstrings_python-1.8.0-py3-none-any.whl", hash = "sha256:4209970cc90bec194568682a535848a8d8489516c6ed4adbe58bbc67b699ca9d"}, - {file = "mkdocstrings_python-1.8.0.tar.gz", hash = "sha256:1488bddf50ee42c07d9a488dddc197f8e8999c2899687043ec5dd1643d057192"}, -] - -[package.dependencies] -griffe = ">=0.37" -mkdocstrings = ">=0.20" - -[[package]] -name = "multidict" -version = "6.0.5" -description = "multidict implementation" -optional = false -python-versions = ">=3.7" -files = [ - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, - {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, - {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, - {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, - {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, - {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, - {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, - {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, - {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, - {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, - {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, - {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, - {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, - {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, - {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, - {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, -] - -[[package]] -name = "numpy" -version = "1.26.4" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, - {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, - {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, - {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, - {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, - {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, - {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, - {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, - {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, - {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, - {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, -] - -[[package]] -name = "orjson" -version = "3.10.7" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -optional = false -python-versions = ">=3.8" -files = [ - {file = "orjson-3.10.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:74f4544f5a6405b90da8ea724d15ac9c36da4d72a738c64685003337401f5c12"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34a566f22c28222b08875b18b0dfbf8a947e69df21a9ed5c51a6bf91cfb944ac"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf6ba8ebc8ef5792e2337fb0419f8009729335bb400ece005606336b7fd7bab7"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac7cf6222b29fbda9e3a472b41e6a5538b48f2c8f99261eecd60aafbdb60690c"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de817e2f5fc75a9e7dd350c4b0f54617b280e26d1631811a43e7e968fa71e3e9"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:348bdd16b32556cf8d7257b17cf2bdb7ab7976af4af41ebe79f9796c218f7e91"}, - {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:479fd0844ddc3ca77e0fd99644c7fe2de8e8be1efcd57705b5c92e5186e8a250"}, - {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fdf5197a21dd660cf19dfd2a3ce79574588f8f5e2dbf21bda9ee2d2b46924d84"}, - {file = "orjson-3.10.7-cp310-none-win32.whl", hash = "sha256:d374d36726746c81a49f3ff8daa2898dccab6596864ebe43d50733275c629175"}, - {file = "orjson-3.10.7-cp310-none-win_amd64.whl", hash = "sha256:cb61938aec8b0ffb6eef484d480188a1777e67b05d58e41b435c74b9d84e0b9c"}, - {file = "orjson-3.10.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7db8539039698ddfb9a524b4dd19508256107568cdad24f3682d5773e60504a2"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:480f455222cb7a1dea35c57a67578848537d2602b46c464472c995297117fa09"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a9c9b168b3a19e37fe2778c0003359f07822c90fdff8f98d9d2a91b3144d8e0"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8de062de550f63185e4c1c54151bdddfc5625e37daf0aa1e75d2a1293e3b7d9a"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6b0dd04483499d1de9c8f6203f8975caf17a6000b9c0c54630cef02e44ee624e"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b58d3795dafa334fc8fd46f7c5dc013e6ad06fd5b9a4cc98cb1456e7d3558bd6"}, - {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33cfb96c24034a878d83d1a9415799a73dc77480e6c40417e5dda0710d559ee6"}, - {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e724cebe1fadc2b23c6f7415bad5ee6239e00a69f30ee423f319c6af70e2a5c0"}, - {file = "orjson-3.10.7-cp311-none-win32.whl", hash = "sha256:82763b46053727a7168d29c772ed5c870fdae2f61aa8a25994c7984a19b1021f"}, - {file = "orjson-3.10.7-cp311-none-win_amd64.whl", hash = "sha256:eb8d384a24778abf29afb8e41d68fdd9a156cf6e5390c04cc07bbc24b89e98b5"}, - {file = "orjson-3.10.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44a96f2d4c3af51bfac6bc4ef7b182aa33f2f054fd7f34cc0ee9a320d051d41f"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ac14cd57df0572453543f8f2575e2d01ae9e790c21f57627803f5e79b0d3c3"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bdbb61dcc365dd9be94e8f7df91975edc9364d6a78c8f7adb69c1cdff318ec93"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b48b3db6bb6e0a08fa8c83b47bc169623f801e5cc4f24442ab2b6617da3b5313"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23820a1563a1d386414fef15c249040042b8e5d07b40ab3fe3efbfbbcbcb8864"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0c6a008e91d10a2564edbb6ee5069a9e66df3fbe11c9a005cb411f441fd2c09"}, - {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d352ee8ac1926d6193f602cbe36b1643bbd1bbcb25e3c1a657a4390f3000c9a5"}, - {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d2d9f990623f15c0ae7ac608103c33dfe1486d2ed974ac3f40b693bad1a22a7b"}, - {file = "orjson-3.10.7-cp312-none-win32.whl", hash = "sha256:7c4c17f8157bd520cdb7195f75ddbd31671997cbe10aee559c2d613592e7d7eb"}, - {file = "orjson-3.10.7-cp312-none-win_amd64.whl", hash = "sha256:1d9c0e733e02ada3ed6098a10a8ee0052dd55774de3d9110d29868d24b17faa1"}, - {file = "orjson-3.10.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:77d325ed866876c0fa6492598ec01fe30e803272a6e8b10e992288b009cbe149"}, - {file = "orjson-3.10.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ea2c232deedcb605e853ae1db2cc94f7390ac776743b699b50b071b02bea6fe"}, - {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3dcfbede6737fdbef3ce9c37af3fb6142e8e1ebc10336daa05872bfb1d87839c"}, - {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11748c135f281203f4ee695b7f80bb1358a82a63905f9f0b794769483ea854ad"}, - {file = "orjson-3.10.7-cp313-none-win32.whl", hash = "sha256:a7e19150d215c7a13f39eb787d84db274298d3f83d85463e61d277bbd7f401d2"}, - {file = "orjson-3.10.7-cp313-none-win_amd64.whl", hash = "sha256:eef44224729e9525d5261cc8d28d6b11cafc90e6bd0be2157bde69a52ec83024"}, - {file = "orjson-3.10.7-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6ea2b2258eff652c82652d5e0f02bd5e0463a6a52abb78e49ac288827aaa1469"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:430ee4d85841e1483d487e7b81401785a5dfd69db5de01314538f31f8fbf7ee1"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4b6146e439af4c2472c56f8540d799a67a81226e11992008cb47e1267a9b3225"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:084e537806b458911137f76097e53ce7bf5806dda33ddf6aaa66a028f8d43a23"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4829cf2195838e3f93b70fd3b4292156fc5e097aac3739859ac0dcc722b27ac0"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1193b2416cbad1a769f868b1749535d5da47626ac29445803dae7cc64b3f5c98"}, - {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4e6c3da13e5a57e4b3dca2de059f243ebec705857522f188f0180ae88badd354"}, - {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c31008598424dfbe52ce8c5b47e0752dca918a4fdc4a2a32004efd9fab41d866"}, - {file = "orjson-3.10.7-cp38-none-win32.whl", hash = "sha256:7122a99831f9e7fe977dc45784d3b2edc821c172d545e6420c375e5a935f5a1c"}, - {file = "orjson-3.10.7-cp38-none-win_amd64.whl", hash = "sha256:a763bc0e58504cc803739e7df040685816145a6f3c8a589787084b54ebc9f16e"}, - {file = "orjson-3.10.7-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e76be12658a6fa376fcd331b1ea4e58f5a06fd0220653450f0d415b8fd0fbe20"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed350d6978d28b92939bfeb1a0570c523f6170efc3f0a0ef1f1df287cd4f4960"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:144888c76f8520e39bfa121b31fd637e18d4cc2f115727865fdf9fa325b10412"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09b2d92fd95ad2402188cf51573acde57eb269eddabaa60f69ea0d733e789fe9"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b24a579123fa884f3a3caadaed7b75eb5715ee2b17ab5c66ac97d29b18fe57f"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591bcfe7512353bd609875ab38050efe3d55e18934e2f18950c108334b4ff"}, - {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f4db56635b58cd1a200b0a23744ff44206ee6aa428185e2b6c4a65b3197abdcd"}, - {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0fa5886854673222618638c6df7718ea7fe2f3f2384c452c9ccedc70b4a510a5"}, - {file = "orjson-3.10.7-cp39-none-win32.whl", hash = "sha256:8272527d08450ab16eb405f47e0f4ef0e5ff5981c3d82afe0efd25dcbef2bcd2"}, - {file = "orjson-3.10.7-cp39-none-win_amd64.whl", hash = "sha256:974683d4618c0c7dbf4f69c95a979734bf183d0658611760017f6e70a145af58"}, - {file = "orjson-3.10.7.tar.gz", hash = "sha256:75ef0640403f945f3a1f9f6400686560dbfb0fb5b16589ad62cd477043c4eee3"}, -] - -[[package]] -name = "packaging" -version = "24.1" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, -] - -[[package]] -name = "paginate" -version = "0.5.7" -description = "Divides large result sets into pages for easier browsing" -optional = false -python-versions = "*" -files = [ - {file = "paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591"}, - {file = "paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945"}, -] - -[package.extras] -dev = ["pytest", "tox"] -lint = ["black"] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "peewee" -version = "3.17.6" -description = "a little orm" -optional = false -python-versions = "*" -files = [ - {file = "peewee-3.17.6.tar.gz", hash = "sha256:cea5592c6f4da1592b7cff8eaf655be6648a1f5857469e30037bf920c03fb8fb"}, -] - -[[package]] -name = "phx-class-registry" -version = "5.0.0" -description = "Factory+Registry pattern for Python classes" -optional = false -python-versions = "<4.0,>=3.10" -files = [ - {file = "phx_class_registry-5.0.0-py3-none-any.whl", hash = "sha256:6e0644f779c7d793a96090d938fe4c396f3274dd57563dc1c57ea245b5c07f89"}, - {file = "phx_class_registry-5.0.0.tar.gz", hash = "sha256:a57ab8c2eca03e0daf06e0dd840ea26b72e2e51b7b7509015b3df7c0d537ee73"}, -] - -[[package]] -name = "pillow" -version = "10.4.0" -description = "Python Imaging Library (Fork)" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, - {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc"}, - {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e"}, - {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46"}, - {file = "pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984"}, - {file = "pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141"}, - {file = "pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"}, - {file = "pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c"}, - {file = "pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319"}, - {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d"}, - {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696"}, - {file = "pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496"}, - {file = "pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91"}, - {file = "pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22"}, - {file = "pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94"}, - {file = "pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a"}, - {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b"}, - {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9"}, - {file = "pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42"}, - {file = "pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a"}, - {file = "pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9"}, - {file = "pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3"}, - {file = "pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc"}, - {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a"}, - {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309"}, - {file = "pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060"}, - {file = "pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea"}, - {file = "pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d"}, - {file = "pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736"}, - {file = "pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd"}, - {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84"}, - {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0"}, - {file = "pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e"}, - {file = "pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab"}, - {file = "pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d"}, - {file = "pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c"}, - {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1"}, - {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df"}, - {file = "pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef"}, - {file = "pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5"}, - {file = "pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3"}, - {file = "pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06"}, -] - -[package.extras] -docs = ["furo", "olefile", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] -fpx = ["olefile"] -mic = ["olefile"] -tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] -typing = ["typing-extensions"] -xmp = ["defusedxml"] - -[[package]] -name = "pipx" -version = "1.7.1" -description = "Install and Run Python Applications in Isolated Environments" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pipx-1.7.1-py3-none-any.whl", hash = "sha256:3933c43bb344e649cb28e10d357e0967ce8572f1c19caf90cf39ae95c2a0afaf"}, - {file = "pipx-1.7.1.tar.gz", hash = "sha256:762de134e16a462be92645166d225ecef446afaef534917f5f70008d63584360"}, -] - -[package.dependencies] -argcomplete = ">=1.9.4" -colorama = {version = ">=0.4.4", markers = "sys_platform == \"win32\""} -packaging = ">=20" -platformdirs = ">=2.1" -userpath = ">=1.6,<1.9 || >1.9" - -[[package]] -name = "platformdirs" -version = "4.2.2" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.8" -files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] - -[[package]] -name = "psutil" -version = "6.0.0" -description = "Cross-platform lib for process and system monitoring in Python." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -files = [ - {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, - {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, - {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, - {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, - {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, - {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, - {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, - {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, - {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, - {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, - {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, - {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, - {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, - {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, -] - -[package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] - -[[package]] -name = "py-dactyl" -version = "2.0.4" -description = "An easy to use Python wrapper for the Pterodactyl Panel API." -optional = false -python-versions = ">=3.4" -files = [ - {file = "py-dactyl-2.0.4.tar.gz", hash = "sha256:a16e13a37ee7743b07931f17a9a049e6a22f3fe0c4475e661684deea5f510e77"}, - {file = "py_dactyl-2.0.4-py3-none-any.whl", hash = "sha256:7868d528d9a8080c68f49e87418e3ca8a853db2bdff835cf40045400ce6d31b3"}, -] - -[package.dependencies] -requests = ">=2.21.0" - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pydantic" -version = "2.9.2" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"}, - {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.23.4" -typing-extensions = {version = ">=4.6.1", markers = "python_version < \"3.13\""} - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata"] - -[[package]] -name = "pydantic-core" -version = "2.23.4" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"}, - {file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"}, - {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"}, - {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"}, - {file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"}, - {file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"}, - {file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"}, - {file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"}, - {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"}, - {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"}, - {file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"}, - {file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"}, - {file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"}, - {file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"}, - {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"}, - {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"}, - {file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"}, - {file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"}, - {file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"}, - {file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"}, - {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"}, - {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"}, - {file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"}, - {file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"}, - {file = "pydantic_core-2.23.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555"}, - {file = "pydantic_core-2.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12"}, - {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2"}, - {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb"}, - {file = "pydantic_core-2.23.4-cp38-none-win32.whl", hash = "sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6"}, - {file = "pydantic_core-2.23.4-cp38-none-win_amd64.whl", hash = "sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556"}, - {file = "pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a"}, - {file = "pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55"}, - {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040"}, - {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605"}, - {file = "pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6"}, - {file = "pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e"}, - {file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pygments" -version = "2.18.0" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, - {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, -] - -[package.extras] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pylint" -version = "3.3.0" -description = "python code static checker" -optional = false -python-versions = ">=3.9.0" -files = [ - {file = "pylint-3.3.0-py3-none-any.whl", hash = "sha256:02dce1845f68974b9b03045894eb3bf05a8b3c7da9fd10af4de3c91e69eb92f1"}, - {file = "pylint-3.3.0.tar.gz", hash = "sha256:c685fe3c061ee5fb0ce7c29436174ab84a2f525fce2a268b1986e921e083fe22"}, -] - -[package.dependencies] -astroid = ">=3.3.3,<=3.4.0-dev0" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -dill = {version = ">=0.3.6", markers = "python_version >= \"3.11\""} -isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" -mccabe = ">=0.6,<0.8" -platformdirs = ">=2.2.0" -tomlkit = ">=0.10.1" - -[package.extras] -spelling = ["pyenchant (>=3.2,<4.0)"] -testutils = ["gitpython (>3)"] - -[[package]] -name = "pymdown-extensions" -version = "10.9" -description = "Extension pack for Python Markdown." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pymdown_extensions-10.9-py3-none-any.whl", hash = "sha256:d323f7e90d83c86113ee78f3fe62fc9dee5f56b54d912660703ea1816fed5626"}, - {file = "pymdown_extensions-10.9.tar.gz", hash = "sha256:6ff740bcd99ec4172a938970d42b96128bdc9d4b9bcad72494f29921dc69b753"}, -] - -[package.dependencies] -markdown = ">=3.6" -pyyaml = "*" - -[package.extras] -extra = ["pygments (>=2.12)"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pytz" -version = "2024.2" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -files = [ - {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, - {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "pyyaml-env-tag" -version = "0.1" -description = "A custom YAML tag for referencing environment variables in YAML files. " -optional = false -python-versions = ">=3.6" -files = [ - {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, - {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, -] - -[package.dependencies] -pyyaml = "*" - -[[package]] -name = "rapidfuzz" -version = "3.9.6" -description = "rapid fuzzy string matching" -optional = false -python-versions = ">=3.8" -files = [ - {file = "rapidfuzz-3.9.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7ed0d0b9c85720f0ae33ac5efc8dc3f60c1489dad5c29d735fbdf2f66f0431f"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f3deff6ab7017ed21b9aec5874a07ad13e6b2a688af055837f88b743c7bfd947"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3f9fc060160507b2704f7d1491bd58453d69689b580cbc85289335b14fe8ca"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e86c2b3827fa6169ad6e7d4b790ce02a20acefb8b78d92fa4249589bbc7a2c"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f982e1aafb4bd8207a5e073b1efef9e68a984e91330e1bbf364f9ed157ed83f0"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9196a51d0ec5eaaaf5bca54a85b7b1e666fc944c332f68e6427503af9fb8c49e"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb5a514064e02585b1cc09da2fe406a6dc1a7e5f3e92dd4f27c53e5f1465ec81"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e3a4244f65dbc3580b1275480118c3763f9dc29fc3dd96610560cb5e140a4d4a"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f6ebb910a702e41641e1e1dada3843bc11ba9107a33c98daef6945a885a40a07"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:624fbe96115fb39addafa288d583b5493bc76dab1d34d0ebba9987d6871afdf9"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1c59f1c1507b7a557cf3c410c76e91f097460da7d97e51c985343798e9df7a3c"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f6f0256cb27b6a0fb2e1918477d1b56473cd04acfa245376a342e7c15806a396"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-win32.whl", hash = "sha256:24d473d00d23a30a85802b502b417a7f5126019c3beec91a6739fe7b95388b24"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-win_amd64.whl", hash = "sha256:248f6d2612e661e2b5f9a22bbd5862a1600e720da7bb6ad8a55bb1548cdfa423"}, - {file = "rapidfuzz-3.9.6-cp310-cp310-win_arm64.whl", hash = "sha256:e03fdf0e74f346ed7e798135df5f2a0fb8d6b96582b00ebef202dcf2171e1d1d"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:52e4675f642fbc85632f691b67115a243cd4d2a47bdcc4a3d9a79e784518ff97"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1f93a2f13038700bd245b927c46a2017db3dcd4d4ff94687d74b5123689b873b"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b70500bca460264b8141d8040caee22e9cf0418c5388104ff0c73fb69ee28f"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1e037fb89f714a220f68f902fc6300ab7a33349f3ce8ffae668c3b3a40b0b06"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6792f66d59b86ccfad5e247f2912e255c85c575789acdbad8e7f561412ffed8a"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68d9cffe710b67f1969cf996983608cee4490521d96ea91d16bd7ea5dc80ea98"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63daaeeea76da17fa0bbe7fb05cba8ed8064bb1a0edf8360636557f8b6511961"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d214e063bffa13e3b771520b74f674b22d309b5720d4df9918ff3e0c0f037720"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ed443a2062460f44c0346cb9d269b586496b808c2419bbd6057f54061c9b9c75"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:5b0c9b227ee0076fb2d58301c505bb837a290ae99ee628beacdb719f0626d749"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:82c9722b7dfaa71e8b61f8c89fed0482567fb69178e139fe4151fc71ed7df782"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c18897c95c0a288347e29537b63608a8f63a5c3cb6da258ac46fcf89155e723e"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-win32.whl", hash = "sha256:3e910cf08944da381159587709daaad9e59d8ff7bca1f788d15928f3c3d49c2a"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-win_amd64.whl", hash = "sha256:59c4a61fab676d37329fc3a671618a461bfeef53a4d0b8b12e3bc24a14e166f8"}, - {file = "rapidfuzz-3.9.6-cp311-cp311-win_arm64.whl", hash = "sha256:8b4afea244102332973377fddbe54ce844d0916e1c67a5123432291717f32ffa"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:70591b28b218fff351b88cdd7f2359a01a71f9f7f5a2e465ce3715ed4b3c422b"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee2d8355c7343c631a03e57540ea06e8717c19ecf5ff64ea07e0498f7f161457"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:708fb675de0f47b9635d1cc6fbbf80d52cb710d0a1abbfae5c84c46e3abbddc3"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d66c247c2d3bb7a9b60567c395a15a929d0ebcc5f4ceedb55bfa202c38c6e0c"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15146301b32e6e3d2b7e8146db1a26747919d8b13690c7f83a4cb5dc111b3a08"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7a03da59b6c7c97e657dd5cd4bcaab5fe4a2affd8193958d6f4d938bee36679"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d2c2fe19e392dbc22695b6c3b2510527e2b774647e79936bbde49db7742d6f1"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:91aaee4c94cb45930684f583ffc4e7c01a52b46610971cede33586cf8a04a12e"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3f5702828c10768f9281180a7ff8597da1e5002803e1304e9519dd0f06d79a85"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ccd1763b608fb4629a0b08f00b3c099d6395e67c14e619f6341b2c8429c2f310"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc7a0d4b2cb166bc46d02c8c9f7551cde8e2f3c9789df3827309433ee9771163"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7496f53d40560a58964207b52586783633f371683834a8f719d6d965d223a2eb"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-win32.whl", hash = "sha256:5eb1a9272ca71bc72be5415c2fa8448a6302ea4578e181bb7da9db855b367df0"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-win_amd64.whl", hash = "sha256:0d21fc3c0ca507a1180152a6dbd129ebaef48facde3f943db5c1055b6e6be56a"}, - {file = "rapidfuzz-3.9.6-cp312-cp312-win_arm64.whl", hash = "sha256:43bb27a57c29dc5fa754496ba6a1a508480d21ae99ac0d19597646c16407e9f3"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:83a5ac6547a9d6eedaa212975cb8f2ce2aa07e6e30833b40e54a52b9f9999aa4"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:10f06139142ecde67078ebc9a745965446132b998f9feebffd71acdf218acfcc"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74720c3f24597f76c7c3e2c4abdff55f1664f4766ff5b28aeaa689f8ffba5fab"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2bce52b5c150878e558a0418c2b637fb3dbb6eb38e4eb27d24aa839920483e"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1611199f178793ca9a060c99b284e11f6d7d124998191f1cace9a0245334d219"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0308b2ad161daf502908a6e21a57c78ded0258eba9a8f5e2545e2dafca312507"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eda91832201b86e3b70835f91522587725bec329ec68f2f7faf5124091e5ca7"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ece873c093aedd87fc07c2a7e333d52e458dc177016afa1edaf157e82b6914d8"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d97d3c9d209d5c30172baea5966f2129e8a198fec4a1aeb2f92abb6e82a2edb1"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6c4550d0db4931f5ebe9f0678916d1b06f06f5a99ba0b8a48b9457fd8959a7d4"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b6b8dd4af6324fc325d9483bec75ecf9be33e590928c9202d408e4eafff6a0a6"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:16122ae448bc89e2bea9d81ce6cb0f751e4e07da39bd1e70b95cae2493857853"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-win32.whl", hash = "sha256:71cc168c305a4445109cd0d4925406f6e66bcb48fde99a1835387c58af4ecfe9"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-win_amd64.whl", hash = "sha256:59ee78f2ecd53fef8454909cda7400fe2cfcd820f62b8a5d4dfe930102268054"}, - {file = "rapidfuzz-3.9.6-cp313-cp313-win_arm64.whl", hash = "sha256:58b4ce83f223605c358ae37e7a2d19a41b96aa65b1fede99cc664c9053af89ac"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9f469dbc9c4aeaac7dd005992af74b7dff94aa56a3ea063ce64e4b3e6736dd2f"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a9ed7ad9adb68d0fe63a156fe752bbf5f1403ed66961551e749641af2874da92"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39ffe48ffbeedf78d120ddfb9d583f2ca906712159a4e9c3c743c9f33e7b1775"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8502ccdea9084d54b6f737d96a3b60a84e3afed9d016686dc979b49cdac71613"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6a4bec4956e06b170ca896ba055d08d4c457dac745548172443982956a80e118"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c0488b1c273be39e109ff885ccac0448b2fa74dea4c4dc676bcf756c15f16d6"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0542c036cb6acf24edd2c9e0411a67d7ba71e29e4d3001a082466b86fc34ff30"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0a96b52c9f26857bf009e270dcd829381e7a634f7ddd585fa29b87d4c82146d9"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:6edd3cd7c4aa8c68c716d349f531bd5011f2ca49ddade216bb4429460151559f"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:50b2fb55d7ed58c66d49c9f954acd8fc4a3f0e9fd0ff708299bd8abb68238d0e"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:32848dfe54391636b84cda1823fd23e5a6b1dbb8be0e9a1d80e4ee9903820994"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:29146cb7a1bf69c87e928b31bffa54f066cb65639d073b36e1425f98cccdebc6"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-win32.whl", hash = "sha256:aed13e5edacb0ecadcc304cc66e93e7e77ff24f059c9792ee602c0381808e10c"}, - {file = "rapidfuzz-3.9.6-cp38-cp38-win_amd64.whl", hash = "sha256:af440e36b828922256d0b4d79443bf2cbe5515fc4b0e9e96017ec789b36bb9fc"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:efa674b407424553024522159296690d99d6e6b1192cafe99ca84592faff16b4"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0b40ff76ee19b03ebf10a0a87938f86814996a822786c41c3312d251b7927849"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16a6c7997cb5927ced6f617122eb116ba514ec6b6f60f4803e7925ef55158891"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3f42504bdc8d770987fc3d99964766d42b2a03e4d5b0f891decdd256236bae0"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9462aa2be9f60b540c19a083471fdf28e7cf6434f068b631525b5e6251b35e"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1629698e68f47609a73bf9e73a6da3a4cac20bc710529215cbdf111ab603665b"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68bc7621843d8e9a7fd1b1a32729465bf94b47b6fb307d906da168413331f8d6"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c6254c50f15bc2fcc33cb93a95a81b702d9e6590f432a7f7822b8c7aba9ae288"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:7e535a114fa575bc143e175e4ca386a467ec8c42909eff500f5f0f13dc84e3e0"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d50acc0e9d67e4ba7a004a14c42d1b1e8b6ca1c515692746f4f8e7948c673167"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fa742ec60bec53c5a211632cf1d31b9eb5a3c80f1371a46a23ac25a1fa2ab209"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c256fa95d29cbe5aa717db790b231a9a5b49e5983d50dc9df29d364a1db5e35b"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-win32.whl", hash = "sha256:89acbf728b764421036c173a10ada436ecca22999851cdc01d0aa904c70d362d"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-win_amd64.whl", hash = "sha256:c608fcba8b14d86c04cb56b203fed31a96e8a1ebb4ce99e7b70313c5bf8cf497"}, - {file = "rapidfuzz-3.9.6-cp39-cp39-win_arm64.whl", hash = "sha256:d41c00ded0e22e9dba88ff23ebe0dc9d2a5f21ba2f88e185ea7374461e61daa9"}, - {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a65c2f63218ea2dedd56fc56361035e189ca123bd9c9ce63a9bef6f99540d681"}, - {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:680dc78a5f889d3b89f74824b89fe357f49f88ad10d2c121e9c3ad37bac1e4eb"}, - {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8ca862927a0b05bd825e46ddf82d0724ea44b07d898ef639386530bf9b40f15"}, - {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2116fa1fbff21fa52cd46f3cfcb1e193ba1d65d81f8b6e123193451cd3d6c15e"}, - {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dcb7d9afd740370a897c15da61d3d57a8d54738d7c764a99cedb5f746d6a003"}, - {file = "rapidfuzz-3.9.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1a5bd6401bb489e14cbb5981c378d53ede850b7cc84b2464cad606149cc4e17d"}, - {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:29fda70b9d03e29df6fc45cc27cbcc235534b1b0b2900e0a3ae0b43022aaeef5"}, - {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:88144f5f52ae977df9352029488326afadd7a7f42c6779d486d1f82d43b2b1f2"}, - {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:715aeaabafba2709b9dd91acb2a44bad59d60b4616ef90c08f4d4402a3bbca60"}, - {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af26ebd3714224fbf9bebbc27bdbac14f334c15f5d7043699cd694635050d6ca"}, - {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101bd2df438861a005ed47c032631b7857dfcdb17b82beeeb410307983aac61d"}, - {file = "rapidfuzz-3.9.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2185e8e29809b97ad22a7f99281d1669a89bdf5fa1ef4ef1feca36924e675367"}, - {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9e53c72d08f0e9c6e4a369e52df5971f311305b4487690c62e8dd0846770260c"}, - {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a0cb157162f0cdd62e538c7bd298ff669847fc43a96422811d5ab933f4c16c3a"}, - {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bb5ff2bd48132ed5e7fbb8f619885facb2e023759f2519a448b2c18afe07e5d"}, - {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6dc37f601865e8407e3a8037ffbc3afe0b0f837b2146f7632bd29d087385babe"}, - {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a657eee4b94668faf1fa2703bdd803654303f7e468eb9ba10a664d867ed9e779"}, - {file = "rapidfuzz-3.9.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:51be6ab5b1d5bb32abd39718f2a5e3835502e026a8272d139ead295c224a6f5e"}, - {file = "rapidfuzz-3.9.6.tar.gz", hash = "sha256:5cf2a7d621e4515fee84722e93563bf77ff2cbe832a77a48b81f88f9e23b9e8d"}, -] - -[package.extras] -full = ["numpy"] - -[[package]] -name = "red-commons" -version = "1.0.0" -description = "Common utilities used by multiple projects maintained by Cog Creators." -optional = false -python-versions = ">=3.8" -files = [ - {file = "Red-Commons-1.0.0.tar.gz", hash = "sha256:b9bcc55c72801c33eb0c77aaf48041d018bfb5f1293053cff8a3e10e4d33e52d"}, - {file = "red_commons-1.0.0-py3-none-any.whl", hash = "sha256:7007b70abfe8e2c9a8e03f8b60810ab1201c4d8274974e0c3842d972cb25af44"}, -] - -[package.extras] -dev = ["black (==22.1.0)", "flake8 (==4.0.1)", "isort (==5.10.1)"] - -[[package]] -name = "red-discordbot" -version = "3.5.13" -description = "A highly customisable Discord bot" -optional = false -python-versions = "<3.12,>=3.8.1" -files = [ - {file = "Red_DiscordBot-3.5.13-py3-none-any.whl", hash = "sha256:bd598a91c7504503b03b0d10f8ad1f230403fbab981a78f00461be61d458c285"}, - {file = "red_discordbot-3.5.13.tar.gz", hash = "sha256:7708dcc8203f2487616e95eba2aa1a6e5d78fbb03975c0b96587b0548c0f5d5b"}, -] - -[package.dependencies] -aiohttp = "3.9.5" -aiohttp-json-rpc = "0.13.3" -aiosignal = "1.3.1" -apsw = "3.46.1.0" -attrs = "24.2.0" -babel = "2.16.0" -brotli = "1.1.0" -click = "8.1.7" -colorama = {version = "0.4.6", markers = "sys_platform == \"win32\""} -discord-py = "2.4.0" -distro = {version = "1.9.0", markers = "sys_platform == \"linux\""} -frozenlist = "1.4.1" -idna = "3.8" -markdown = "3.7" -markdown-it-py = "3.0.0" -mdurl = "0.1.2" -multidict = "6.0.5" -orjson = "3.10.7" -packaging = "24.1" -platformdirs = "4.2.2" -psutil = "6.0.0" -pygments = "2.18.0" -python-dateutil = "2.9.0.post0" -pyyaml = "6.0.2" -rapidfuzz = "3.9.6" -red-commons = "1.0.0" -red-lavalink = "0.11.0" -rich = "13.8.0" -schema = "0.7.7" -six = "1.16.0" -typing-extensions = "4.12.2" -uvloop = {version = "0.20.0", markers = "sys_platform != \"win32\" and platform_python_implementation == \"CPython\""} -yarl = "1.9.4" - -[package.extras] -all = ["async-timeout (==4.0.3)", "asyncpg (==0.29.0)"] -dev = ["alabaster (==0.7.13)", "astroid (==3.2.4)", "async-timeout (==4.0.3)", "asyncpg (==0.29.0)", "black (==23.12.1)", "certifi (==2024.7.4)", "charset-normalizer (==3.3.2)", "dill (==0.3.8)", "docutils (==0.20.1)", "exceptiongroup (==1.2.2)", "imagesize (==1.4.1)", "importlib-metadata (==8.4.0)", "iniconfig (==2.0.0)", "isort (==5.13.2)", "jinja2 (==3.1.4)", "markupsafe (==2.1.5)", "mccabe (==0.7.0)", "mypy-extensions (==1.0.0)", "pathspec (==0.12.1)", "pluggy (==1.5.0)", "pylint (==3.2.6)", "pytest (==7.4.4)", "pytest-asyncio (==0.21.2)", "pytest-mock (==3.14.0)", "pytz (==2024.1)", "requests (==2.32.3)", "snowballstemmer (==2.2.0)", "sphinx (==7.1.2)", "sphinx-prompt (==1.7.0)", "sphinx-rtd-theme (==2.0.0)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jquery (==4.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "tomli (==2.0.1)", "tomli (==2.0.1)", "tomlkit (==0.13.2)", "urllib3 (==2.2.2)", "zipp (==3.20.1)"] -doc = ["alabaster (==0.7.13)", "certifi (==2024.7.4)", "charset-normalizer (==3.3.2)", "docutils (==0.20.1)", "imagesize (==1.4.1)", "importlib-metadata (==8.4.0)", "jinja2 (==3.1.4)", "markupsafe (==2.1.5)", "pytz (==2024.1)", "requests (==2.32.3)", "snowballstemmer (==2.2.0)", "sphinx (==7.1.2)", "sphinx-prompt (==1.7.0)", "sphinx-rtd-theme (==2.0.0)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jquery (==4.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "urllib3 (==2.2.2)", "zipp (==3.20.1)"] -postgres = ["async-timeout (==4.0.3)", "asyncpg (==0.29.0)"] -style = ["black (==23.12.1)", "mypy-extensions (==1.0.0)", "pathspec (==0.12.1)", "tomli (==2.0.1)"] -test = ["astroid (==3.2.4)", "dill (==0.3.8)", "exceptiongroup (==1.2.2)", "iniconfig (==2.0.0)", "isort (==5.13.2)", "mccabe (==0.7.0)", "pluggy (==1.5.0)", "pylint (==3.2.6)", "pytest (==7.4.4)", "pytest-asyncio (==0.21.2)", "pytest-mock (==3.14.0)", "tomli (==2.0.1)", "tomlkit (==0.13.2)"] - -[[package]] -name = "red-lavalink" -version = "0.11.0" -description = "Lavalink client library for Red-DiscordBot" -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "Red-Lavalink-0.11.0.tar.gz", hash = "sha256:6ee2671dfc43a96b7e6be4effaa4137024de51bc5681f64a67c125bc3b7d4f99"}, - {file = "Red_Lavalink-0.11.0-py3-none-any.whl", hash = "sha256:f76329eee2ec5e4d77e0e97fe6ba76207efdcc8d963a9c39913cf91057d7920a"}, -] - -[package.dependencies] -aiohttp = ">=3.6.0" -"discord.py" = ">=2.0.0" -Red-Commons = ">=1.0.0,<2" - -[package.extras] -doc = ["sphinx", "sphinx-rtd-theme", "sphinxcontrib-trio"] -test = ["pytest (>=7)", "pytest-asyncio (>=0.19)"] - -[[package]] -name = "regex" -version = "2024.9.11" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.8" -files = [ - {file = "regex-2024.9.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1494fa8725c285a81d01dc8c06b55287a1ee5e0e382d8413adc0a9197aac6408"}, - {file = "regex-2024.9.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0e12c481ad92d129c78f13a2a3662317e46ee7ef96c94fd332e1c29131875b7d"}, - {file = "regex-2024.9.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16e13a7929791ac1216afde26f712802e3df7bf0360b32e4914dca3ab8baeea5"}, - {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46989629904bad940bbec2106528140a218b4a36bb3042d8406980be1941429c"}, - {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a906ed5e47a0ce5f04b2c981af1c9acf9e8696066900bf03b9d7879a6f679fc8"}, - {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a091b0550b3b0207784a7d6d0f1a00d1d1c8a11699c1a4d93db3fbefc3ad35"}, - {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ddcd9a179c0a6fa8add279a4444015acddcd7f232a49071ae57fa6e278f1f71"}, - {file = "regex-2024.9.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b41e1adc61fa347662b09398e31ad446afadff932a24807d3ceb955ed865cc8"}, - {file = "regex-2024.9.11-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ced479f601cd2f8ca1fd7b23925a7e0ad512a56d6e9476f79b8f381d9d37090a"}, - {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:635a1d96665f84b292e401c3d62775851aedc31d4f8784117b3c68c4fcd4118d"}, - {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c0256beda696edcf7d97ef16b2a33a8e5a875affd6fa6567b54f7c577b30a137"}, - {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3ce4f1185db3fbde8ed8aa223fc9620f276c58de8b0d4f8cc86fd1360829edb6"}, - {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:09d77559e80dcc9d24570da3745ab859a9cf91953062e4ab126ba9d5993688ca"}, - {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a22ccefd4db3f12b526eccb129390942fe874a3a9fdbdd24cf55773a1faab1a"}, - {file = "regex-2024.9.11-cp310-cp310-win32.whl", hash = "sha256:f745ec09bc1b0bd15cfc73df6fa4f726dcc26bb16c23a03f9e3367d357eeedd0"}, - {file = "regex-2024.9.11-cp310-cp310-win_amd64.whl", hash = "sha256:01c2acb51f8a7d6494c8c5eafe3d8e06d76563d8a8a4643b37e9b2dd8a2ff623"}, - {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df"}, - {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268"}, - {file = "regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50"}, - {file = "regex-2024.9.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96"}, - {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1"}, - {file = "regex-2024.9.11-cp311-cp311-win32.whl", hash = "sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9"}, - {file = "regex-2024.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf"}, - {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7"}, - {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231"}, - {file = "regex-2024.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a"}, - {file = "regex-2024.9.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a"}, - {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a"}, - {file = "regex-2024.9.11-cp312-cp312-win32.whl", hash = "sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776"}, - {file = "regex-2024.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009"}, - {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784"}, - {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36"}, - {file = "regex-2024.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6"}, - {file = "regex-2024.9.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554"}, - {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8"}, - {file = "regex-2024.9.11-cp313-cp313-win32.whl", hash = "sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8"}, - {file = "regex-2024.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f"}, - {file = "regex-2024.9.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:35f4a6f96aa6cb3f2f7247027b07b15a374f0d5b912c0001418d1d55024d5cb4"}, - {file = "regex-2024.9.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:55b96e7ce3a69a8449a66984c268062fbaa0d8ae437b285428e12797baefce7e"}, - {file = "regex-2024.9.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb130fccd1a37ed894824b8c046321540263013da72745d755f2d35114b81a60"}, - {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:323c1f04be6b2968944d730e5c2091c8c89767903ecaa135203eec4565ed2b2b"}, - {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be1c8ed48c4c4065ecb19d882a0ce1afe0745dfad8ce48c49586b90a55f02366"}, - {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5b029322e6e7b94fff16cd120ab35a253236a5f99a79fb04fda7ae71ca20ae8"}, - {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6fff13ef6b5f29221d6904aa816c34701462956aa72a77f1f151a8ec4f56aeb"}, - {file = "regex-2024.9.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:587d4af3979376652010e400accc30404e6c16b7df574048ab1f581af82065e4"}, - {file = "regex-2024.9.11-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:079400a8269544b955ffa9e31f186f01d96829110a3bf79dc338e9910f794fca"}, - {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f9268774428ec173654985ce55fc6caf4c6d11ade0f6f914d48ef4719eb05ebb"}, - {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:23f9985c8784e544d53fc2930fc1ac1a7319f5d5332d228437acc9f418f2f168"}, - {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2941333154baff9838e88aa71c1d84f4438189ecc6021a12c7573728b5838e"}, - {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e93f1c331ca8e86fe877a48ad64e77882c0c4da0097f2212873a69bbfea95d0c"}, - {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:846bc79ee753acf93aef4184c040d709940c9d001029ceb7b7a52747b80ed2dd"}, - {file = "regex-2024.9.11-cp38-cp38-win32.whl", hash = "sha256:c94bb0a9f1db10a1d16c00880bdebd5f9faf267273b8f5bd1878126e0fbde771"}, - {file = "regex-2024.9.11-cp38-cp38-win_amd64.whl", hash = "sha256:2b08fce89fbd45664d3df6ad93e554b6c16933ffa9d55cb7e01182baaf971508"}, - {file = "regex-2024.9.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:07f45f287469039ffc2c53caf6803cd506eb5f5f637f1d4acb37a738f71dd066"}, - {file = "regex-2024.9.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4838e24ee015101d9f901988001038f7f0d90dc0c3b115541a1365fb439add62"}, - {file = "regex-2024.9.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6edd623bae6a737f10ce853ea076f56f507fd7726bee96a41ee3d68d347e4d16"}, - {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c69ada171c2d0e97a4b5aa78fbb835e0ffbb6b13fc5da968c09811346564f0d3"}, - {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02087ea0a03b4af1ed6ebab2c54d7118127fee8d71b26398e8e4b05b78963199"}, - {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69dee6a020693d12a3cf892aba4808fe168d2a4cef368eb9bf74f5398bfd4ee8"}, - {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:297f54910247508e6e5cae669f2bc308985c60540a4edd1c77203ef19bfa63ca"}, - {file = "regex-2024.9.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ecea58b43a67b1b79805f1a0255730edaf5191ecef84dbc4cc85eb30bc8b63b9"}, - {file = "regex-2024.9.11-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:eab4bb380f15e189d1313195b062a6aa908f5bd687a0ceccd47c8211e9cf0d4a"}, - {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0cbff728659ce4bbf4c30b2a1be040faafaa9eca6ecde40aaff86f7889f4ab39"}, - {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:54c4a097b8bc5bb0dfc83ae498061d53ad7b5762e00f4adaa23bee22b012e6ba"}, - {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:73d6d2f64f4d894c96626a75578b0bf7d9e56dcda8c3d037a2118fdfe9b1c664"}, - {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:e53b5fbab5d675aec9f0c501274c467c0f9a5d23696cfc94247e1fb56501ed89"}, - {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ffbcf9221e04502fc35e54d1ce9567541979c3fdfb93d2c554f0ca583a19b35"}, - {file = "regex-2024.9.11-cp39-cp39-win32.whl", hash = "sha256:e4c22e1ac1f1ec1e09f72e6c44d8f2244173db7eb9629cc3a346a8d7ccc31142"}, - {file = "regex-2024.9.11-cp39-cp39-win_amd64.whl", hash = "sha256:faa3c142464efec496967359ca99696c896c591c56c53506bac1ad465f66e919"}, - {file = "regex-2024.9.11.tar.gz", hash = "sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd"}, -] - -[[package]] -name = "requests" -version = "2.32.3" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "rich" -version = "13.8.0" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "rich-13.8.0-py3-none-any.whl", hash = "sha256:2e85306a063b9492dffc86278197a60cbece75bcb766022f3436f567cae11bdc"}, - {file = "rich-13.8.0.tar.gz", hash = "sha256:a5ac1f1cd448ade0d59cc3356f7db7a7ccda2c8cbae9c7a90c28ff463d3e91f4"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - -[[package]] -name = "ruff" -version = "0.3.7" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -files = [ - {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0e8377cccb2f07abd25e84fc5b2cbe48eeb0fea9f1719cad7caedb061d70e5ce"}, - {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:15a4d1cc1e64e556fa0d67bfd388fed416b7f3b26d5d1c3e7d192c897e39ba4b"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d28bdf3d7dc71dd46929fafeec98ba89b7c3550c3f0978e36389b5631b793663"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:379b67d4f49774ba679593b232dcd90d9e10f04d96e3c8ce4a28037ae473f7bb"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c060aea8ad5ef21cdfbbe05475ab5104ce7827b639a78dd55383a6e9895b7c51"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ebf8f615dde968272d70502c083ebf963b6781aacd3079081e03b32adfe4d58a"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d48098bd8f5c38897b03604f5428901b65e3c97d40b3952e38637b5404b739a2"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da8a4fda219bf9024692b1bc68c9cff4b80507879ada8769dc7e985755d662ea"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c44e0149f1d8b48c4d5c33d88c677a4aa22fd09b1683d6a7ff55b816b5d074f"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3050ec0af72b709a62ecc2aca941b9cd479a7bf2b36cc4562f0033d688e44fa1"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a29cc38e4c1ab00da18a3f6777f8b50099d73326981bb7d182e54a9a21bb4ff7"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b15cc59c19edca917f51b1956637db47e200b0fc5e6e1878233d3a938384b0b"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e491045781b1e38b72c91247cf4634f040f8d0cb3e6d3d64d38dcf43616650b4"}, - {file = "ruff-0.3.7-py3-none-win32.whl", hash = "sha256:bc931de87593d64fad3a22e201e55ad76271f1d5bfc44e1a1887edd0903c7d9f"}, - {file = "ruff-0.3.7-py3-none-win_amd64.whl", hash = "sha256:5ef0e501e1e39f35e03c2acb1d1238c595b8bb36cf7a170e7c1df1b73da00e74"}, - {file = "ruff-0.3.7-py3-none-win_arm64.whl", hash = "sha256:789e144f6dc7019d1f92a812891c645274ed08af6037d11fc65fcbc183b7d59f"}, - {file = "ruff-0.3.7.tar.gz", hash = "sha256:d5c1aebee5162c2226784800ae031f660c350e7a3402c4d1f8ea4e97e232e3ba"}, -] - -[[package]] -name = "schema" -version = "0.7.7" -description = "Simple data validation library" -optional = false -python-versions = "*" -files = [ - {file = "schema-0.7.7-py2.py3-none-any.whl", hash = "sha256:5d976a5b50f36e74e2157b47097b60002bd4d42e65425fcc9c9befadb4255dde"}, - {file = "schema-0.7.7.tar.gz", hash = "sha256:7da553abd2958a19dc2547c388cde53398b39196175a9be59ea1caf5ab0a1807"}, -] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "smmap" -version = "5.0.1" -description = "A pure Python implementation of a sliding window memory map manager" -optional = false -python-versions = ">=3.7" -files = [ - {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, - {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, -] - -[[package]] -name = "soupsieve" -version = "2.6" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.8" -files = [ - {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, - {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, -] - -[[package]] -name = "sqlite-web" -version = "0.6.4" -description = "Web-based SQLite database browser." -optional = false -python-versions = "*" -files = [ - {file = "sqlite-web-0.6.4.tar.gz", hash = "sha256:e4175dd42f4cdc78ef7c329d56f19243efc8d088a6bdfd4c6703e89d18aac2a5"}, -] - -[package.dependencies] -flask = "*" -peewee = ">=3.0.0" -pygments = "*" - -[[package]] -name = "tinycss2" -version = "1.3.0" -description = "A tiny CSS parser" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tinycss2-1.3.0-py3-none-any.whl", hash = "sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7"}, - {file = "tinycss2-1.3.0.tar.gz", hash = "sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d"}, -] - -[package.dependencies] -webencodings = ">=0.4" - -[package.extras] -doc = ["sphinx", "sphinx_rtd_theme"] -test = ["pytest", "ruff"] - -[[package]] -name = "tomlkit" -version = "0.13.2" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, - {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, -] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "urllib3" -version = "2.2.3" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -files = [ - {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, - {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "userpath" -version = "1.9.2" -description = "Cross-platform tool for adding locations to the user PATH" -optional = false -python-versions = ">=3.7" -files = [ - {file = "userpath-1.9.2-py3-none-any.whl", hash = "sha256:2cbf01a23d655a1ff8fc166dfb78da1b641d1ceabf0fe5f970767d380b14e89d"}, - {file = "userpath-1.9.2.tar.gz", hash = "sha256:6c52288dab069257cc831846d15d48133522455d4677ee69a9781f11dbefd815"}, -] - -[package.dependencies] -click = "*" - -[[package]] -name = "uvloop" -version = "0.20.0" -description = "Fast implementation of asyncio event loop on top of libuv" -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "uvloop-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9ebafa0b96c62881d5cafa02d9da2e44c23f9f0cd829f3a32a6aff771449c996"}, - {file = "uvloop-0.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:35968fc697b0527a06e134999eef859b4034b37aebca537daeb598b9d45a137b"}, - {file = "uvloop-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b16696f10e59d7580979b420eedf6650010a4a9c3bd8113f24a103dfdb770b10"}, - {file = "uvloop-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b04d96188d365151d1af41fa2d23257b674e7ead68cfd61c725a422764062ae"}, - {file = "uvloop-0.20.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:94707205efbe809dfa3a0d09c08bef1352f5d3d6612a506f10a319933757c006"}, - {file = "uvloop-0.20.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:89e8d33bb88d7263f74dc57d69f0063e06b5a5ce50bb9a6b32f5fcbe655f9e73"}, - {file = "uvloop-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e50289c101495e0d1bb0bfcb4a60adde56e32f4449a67216a1ab2750aa84f037"}, - {file = "uvloop-0.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e237f9c1e8a00e7d9ddaa288e535dc337a39bcbf679f290aee9d26df9e72bce9"}, - {file = "uvloop-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:746242cd703dc2b37f9d8b9f173749c15e9a918ddb021575a0205ec29a38d31e"}, - {file = "uvloop-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82edbfd3df39fb3d108fc079ebc461330f7c2e33dbd002d146bf7c445ba6e756"}, - {file = "uvloop-0.20.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:80dc1b139516be2077b3e57ce1cb65bfed09149e1d175e0478e7a987863b68f0"}, - {file = "uvloop-0.20.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f44af67bf39af25db4c1ac27e82e9665717f9c26af2369c404be865c8818dcf"}, - {file = "uvloop-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4b75f2950ddb6feed85336412b9a0c310a2edbcf4cf931aa5cfe29034829676d"}, - {file = "uvloop-0.20.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:77fbc69c287596880ecec2d4c7a62346bef08b6209749bf6ce8c22bbaca0239e"}, - {file = "uvloop-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6462c95f48e2d8d4c993a2950cd3d31ab061864d1c226bbf0ee2f1a8f36674b9"}, - {file = "uvloop-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:649c33034979273fa71aa25d0fe120ad1777c551d8c4cd2c0c9851d88fcb13ab"}, - {file = "uvloop-0.20.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a609780e942d43a275a617c0839d85f95c334bad29c4c0918252085113285b5"}, - {file = "uvloop-0.20.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aea15c78e0d9ad6555ed201344ae36db5c63d428818b4b2a42842b3870127c00"}, - {file = "uvloop-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0e94b221295b5e69de57a1bd4aeb0b3a29f61be6e1b478bb8a69a73377db7ba"}, - {file = "uvloop-0.20.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fee6044b64c965c425b65a4e17719953b96e065c5b7e09b599ff332bb2744bdf"}, - {file = "uvloop-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:265a99a2ff41a0fd56c19c3838b29bf54d1d177964c300dad388b27e84fd7847"}, - {file = "uvloop-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b10c2956efcecb981bf9cfb8184d27d5d64b9033f917115a960b83f11bfa0d6b"}, - {file = "uvloop-0.20.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e7d61fe8e8d9335fac1bf8d5d82820b4808dd7a43020c149b63a1ada953d48a6"}, - {file = "uvloop-0.20.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2beee18efd33fa6fdb0976e18475a4042cd31c7433c866e8a09ab604c7c22ff2"}, - {file = "uvloop-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8c36fdf3e02cec92aed2d44f63565ad1522a499c654f07935c8f9d04db69e95"}, - {file = "uvloop-0.20.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0fac7be202596c7126146660725157d4813aa29a4cc990fe51346f75ff8fde7"}, - {file = "uvloop-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d0fba61846f294bce41eb44d60d58136090ea2b5b99efd21cbdf4e21927c56a"}, - {file = "uvloop-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95720bae002ac357202e0d866128eb1ac82545bcf0b549b9abe91b5178d9b541"}, - {file = "uvloop-0.20.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:36c530d8fa03bfa7085af54a48f2ca16ab74df3ec7108a46ba82fd8b411a2315"}, - {file = "uvloop-0.20.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e97152983442b499d7a71e44f29baa75b3b02e65d9c44ba53b10338e98dedb66"}, - {file = "uvloop-0.20.0.tar.gz", hash = "sha256:4603ca714a754fc8d9b197e325db25b2ea045385e8a3ad05d3463de725fdf469"}, -] - -[package.extras] -docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] -test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] - -[[package]] -name = "watchdog" -version = "5.0.2" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.9" -files = [ - {file = "watchdog-5.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d961f4123bb3c447d9fcdcb67e1530c366f10ab3a0c7d1c0c9943050936d4877"}, - {file = "watchdog-5.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72990192cb63872c47d5e5fefe230a401b87fd59d257ee577d61c9e5564c62e5"}, - {file = "watchdog-5.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bec703ad90b35a848e05e1b40bf0050da7ca28ead7ac4be724ae5ac2653a1a0"}, - {file = "watchdog-5.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dae7a1879918f6544201d33666909b040a46421054a50e0f773e0d870ed7438d"}, - {file = "watchdog-5.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c4a440f725f3b99133de610bfec93d570b13826f89616377715b9cd60424db6e"}, - {file = "watchdog-5.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8b2918c19e0d48f5f20df458c84692e2a054f02d9df25e6c3c930063eca64c1"}, - {file = "watchdog-5.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:aa9cd6e24126d4afb3752a3e70fce39f92d0e1a58a236ddf6ee823ff7dba28ee"}, - {file = "watchdog-5.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f627c5bf5759fdd90195b0c0431f99cff4867d212a67b384442c51136a098ed7"}, - {file = "watchdog-5.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d7594a6d32cda2b49df3fd9abf9b37c8d2f3eab5df45c24056b4a671ac661619"}, - {file = "watchdog-5.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba32efcccfe2c58f4d01115440d1672b4eb26cdd6fc5b5818f1fb41f7c3e1889"}, - {file = "watchdog-5.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:963f7c4c91e3f51c998eeff1b3fb24a52a8a34da4f956e470f4b068bb47b78ee"}, - {file = "watchdog-5.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8c47150aa12f775e22efff1eee9f0f6beee542a7aa1a985c271b1997d340184f"}, - {file = "watchdog-5.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:14dd4ed023d79d1f670aa659f449bcd2733c33a35c8ffd88689d9d243885198b"}, - {file = "watchdog-5.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b84bff0391ad4abe25c2740c7aec0e3de316fdf7764007f41e248422a7760a7f"}, - {file = "watchdog-5.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e8d5ff39f0a9968952cce548e8e08f849141a4fcc1290b1c17c032ba697b9d7"}, - {file = "watchdog-5.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fb223456db6e5f7bd9bbd5cd969f05aae82ae21acc00643b60d81c770abd402b"}, - {file = "watchdog-5.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9814adb768c23727a27792c77812cf4e2fd9853cd280eafa2bcfa62a99e8bd6e"}, - {file = "watchdog-5.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:901ee48c23f70193d1a7bc2d9ee297df66081dd5f46f0ca011be4f70dec80dab"}, - {file = "watchdog-5.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:638bcca3d5b1885c6ec47be67bf712b00a9ab3d4b22ec0881f4889ad870bc7e8"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:5597c051587f8757798216f2485e85eac583c3b343e9aa09127a3a6f82c65ee8"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:53ed1bf71fcb8475dd0ef4912ab139c294c87b903724b6f4a8bd98e026862e6d"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:29e4a2607bd407d9552c502d38b45a05ec26a8e40cc7e94db9bb48f861fa5abc"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:b6dc8f1d770a8280997e4beae7b9a75a33b268c59e033e72c8a10990097e5fde"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:d2ab34adc9bf1489452965cdb16a924e97d4452fcf88a50b21859068b50b5c3b"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:7d1aa7e4bb0f0c65a1a91ba37c10e19dabf7eaaa282c5787e51371f090748f4b"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:726eef8f8c634ac6584f86c9c53353a010d9f311f6c15a034f3800a7a891d941"}, - {file = "watchdog-5.0.2-py3-none-win32.whl", hash = "sha256:bda40c57115684d0216556671875e008279dea2dc00fcd3dde126ac8e0d7a2fb"}, - {file = "watchdog-5.0.2-py3-none-win_amd64.whl", hash = "sha256:d010be060c996db725fbce7e3ef14687cdcc76f4ca0e4339a68cc4532c382a73"}, - {file = "watchdog-5.0.2-py3-none-win_ia64.whl", hash = "sha256:3960136b2b619510569b90f0cd96408591d6c251a75c97690f4553ca88889769"}, - {file = "watchdog-5.0.2.tar.gz", hash = "sha256:dcebf7e475001d2cdeb020be630dc5b687e9acdd60d16fea6bb4508e7b94cf76"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[[package]] -name = "webencodings" -version = "0.5.1" -description = "Character encoding aliases for legacy web content" -optional = false -python-versions = "*" -files = [ - {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, - {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, -] - -[[package]] -name = "websockets" -version = "12.0" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -optional = false -python-versions = ">=3.8" -files = [ - {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, - {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, - {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, - {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, - {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, - {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, - {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, - {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, - {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, - {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, - {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, - {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, - {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, - {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, - {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, - {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, - {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, - {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, - {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, - {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, - {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, - {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, - {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, - {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, - {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, - {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, - {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, - {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, - {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, - {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, - {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, - {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, - {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, -] - -[[package]] -name = "werkzeug" -version = "3.0.4" -description = "The comprehensive WSGI web application library." -optional = false -python-versions = ">=3.8" -files = [ - {file = "werkzeug-3.0.4-py3-none-any.whl", hash = "sha256:02c9eb92b7d6c06f31a782811505d2157837cea66aaede3e217c7c27c039476c"}, - {file = "werkzeug-3.0.4.tar.gz", hash = "sha256:34f2371506b250df4d4f84bfe7b0921e4762525762bbd936614909fe25cd7306"}, -] - -[package.dependencies] -MarkupSafe = ">=2.1.1" - -[package.extras] -watchdog = ["watchdog (>=2.3)"] - -[[package]] -name = "yarl" -version = "1.9.4" -description = "Yet another URL library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, - {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, - {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, - {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, - {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, - {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, - {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, - {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, - {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, - {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, - {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, - {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, - {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, - {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, - {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, - {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" - -[metadata] -lock-version = "2.0" -python-versions = ">=3.11,<3.12" -content-hash = "263e8505112c96a51e4fe34cfbdad48fe597fb2abd7821fecf3c8c81f2152a23" -- 2.45.3 From 25a70b925e4e030de52f50c1a26fdb6bc8e8a5eb Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 25 Sep 2024 12:07:53 -0400 Subject: [PATCH 351/376] docs(pterodactyl): link to the pelican-eggs repository instead of some random fork Signed-off-by: cswimr --- .docs/pterodactyl/installing-red.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.docs/pterodactyl/installing-red.md b/.docs/pterodactyl/installing-red.md index 3f26e7b..8567e0e 100644 --- a/.docs/pterodactyl/installing-red.md +++ b/.docs/pterodactyl/installing-red.md @@ -10,7 +10,7 @@ There are a few caveats to running an instance of Red on Pterodactyl. - You will not receive any support from the Red developers. - The built-in Audio cog will not work. -- Depending on your host, you might have to request a [`tmpfs` size increase](https://github.com/ign-gg/Pterodactyl-Eggs/tree/master/bots/discord/redbot#additional-requirements). +- Depending on your host, you might have to request a [`tmpfs` size increase](https://github.com/pelican-eggs/eggs/tree/master/bots/discord/redbot#additional-requirements). If these are unacceptable to you, you should [install Red normally](https://docs.discord.red/en/stable/install_guides/index.html). /// -- 2.45.3 From 6060c7805677b52680761db3192e0e0aec807089 Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 10 Oct 2024 16:01:54 -0400 Subject: [PATCH 352/376] (repo): switch to uv Signed-off-by: cswimr --- pyproject.toml | 73 ++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 327602c..0480d5d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,49 +1,46 @@ -[tool.poetry] +[project] name = "seacogs" version = "0.1.0" description = "My assorted cogs for Red-DiscordBot." -authors = ["cswimr"] license = "MPL 2" readme = "README.md" -package-mode = false +requires-python = ">=3.11" +authors = [ + { name = "cswimr", email = "seaswimmerthefsh@gmail.com" }, +] +dependencies = [ + "aiosqlite>=0.20.0", + "beautifulsoup4>=4.12.3", + "colorthief>=0.2.1", + "markdownify>=0.13.1", + "numpy>=2.1.2", + "phx-class-registry>=5.0.0", + "pillow>=10.4.0", + "py-dactyl", + "pydantic>=2.9.2", + "red-discordbot>=3.5.13", + "websockets>=13.1", +] -[tool.poetry.dependencies] -python = ">=3.11,<3.12" -Red-DiscordBot = "^3.5.9" -py-dactyl = "^2.0.4" -websockets = "^12.0" -pillow = "^10.3.0" -numpy = "^1.26.4" -pydantic = "^2.7.1" -colorthief = "^0.2.1" -beautifulsoup4 = "^4.12.3" -markdownify = "^0.12.1" -aiosqlite = "^0.20.0" -phx-class-registry = "^5.0.0" +[project.optional-dependencies] +documentation = [ + "mkdocs>=1.6.1", + "mkdocs-git-authors-plugin>=0.9.0", + "mkdocs-git-revision-date-localized-plugin>=1.2.9", + "mkdocs-material[imaging]>=9.5.40", + "mkdocstrings[python]>=0.26.1", + "mkdocs-redirects>=1.2.1", +] -[tool.poetry.group.dev] -optional = true +[tool.uv] +dev-dependencies = [ + "pylint>=3.3.1", + "ruff>=0.6.9", + "sqlite-web>=0.6.4", +] -[tool.poetry.group.dev.dependencies] -ruff = "^0.3.1" -pylint = "^3.1.0" -pipx = "^1.5.0" -sqlite-web = "^0.6.4" - -[tool.poetry.group.docs] -optional = true - -[tool.poetry.group.docs.dependencies] -mkdocs = "1.5.3" -mkdocstrings = {extras = ["python"], version = "0.24.0"} -mkdocs-git-authors-plugin = "0.7.2" -mkdocs-git-revision-date-localized-plugin = "1.2.2" -mkdocs-material = {extras = ["imaging"], version = "^9.5.2"} -mkdocs-redirects = "^1.2.1" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" +[tool.uv.sources] +py-dactyl = { git = "https://github.com/cswimr/pydactyl" } [tool.ruff] # Exclude a variety of commonly ignored directories. -- 2.45.3 From d2c4b19610eabf0d19bc2a2556031405969401a3 Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 10 Oct 2024 16:03:50 -0400 Subject: [PATCH 353/376] feat(workflow): move to uv --- .forgejo/workflows/workflow.yaml | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index 3c23538..600988e 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -1,39 +1,46 @@ name: Actions on: push: - branches: - - 'main' pull_request: jobs: - Lint Code (Ruff & Pylint): + lint: + name: Lint Code (Ruff & Pylint) runs-on: docker - container: www.coastalcommits.com/cswimr/actions:seacogs + container: www.coastalcommits.com/cswimr/actions:uv steps: - name: Checkout uses: actions/checkout@v3 + - name: Install python + run: uv python install 3.11 + - name: Install dependencies - run: poetry install --with dev --no-root + run: uv sync - name: Analysing code with Ruff - run: ./.venv/bin/ruff check $(git ls-files '*.py') + run: uv run ruff check $(git ls-files '*.py') continue-on-error: true - name: Analysing code with Pylint - run: ./.venv/bin/pylint --rcfile=.forgejo/workflows/config/.pylintrc $(git ls-files '*.py') + run: uv run pylint --rcfile=.forgejo/workflows/config/.pylintrc $(git ls-files '*.py') - Build Documentation (MkDocs): + docs: + name: Build Documentation (MkDocs) + if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: docker - container: www.coastalcommits.com/cswimr/actions:seacogs + container: www.coastalcommits.com/cswimr/actions:docs steps: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 0 + - name: Install python + run: uv python install 3.11 + - name: Install dependencies - run: poetry install --with docs --no-root + run: uv sync --no-dev --extra=documentation - name: Set environment variables uses: actions/env@v2 @@ -42,7 +49,7 @@ jobs: run: | export SITE_URL="https://$CI_ACTION_REF_NAME_SLUG.seacogs.coastalcommits.com" export EDIT_URI="src/branch/$CI_ACTION_REF_NAME/.docs" - ./.venv/bin/mkdocs build -v + uv run mkdocs build -v - name: Deploy documentation run: | -- 2.45.3 From 2ecc2cd318b463da4e2570bb5f0132deddfd38ee Mon Sep 17 00:00:00 2001 From: cswimr Date: Thu, 10 Oct 2024 16:08:39 -0400 Subject: [PATCH 354/376] chore(repo): add uv.lock file --- uv.lock | 1826 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1826 insertions(+) create mode 100644 uv.lock diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..0570982 --- /dev/null +++ b/uv.lock @@ -0,0 +1,1826 @@ +version = 1 +requires-python = ">=3.11" +resolution-markers = [ + "python_full_version < '3.12'", + "python_full_version == '3.12.*'", + "python_full_version >= '3.13'", +] + +[[package]] +name = "aiohttp" +version = "3.9.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiosignal" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/a4/e3679773ea7eb5b37a2c998e25b017cc5349edf6ba2739d1f32855cfb11b/aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551", size = 7504841 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/f5/aa23d04a1bb57e5f51108a6473964a2618cc83e608e23e3543031aa2bb3a/aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342", size = 599387 }, + { url = "https://files.pythonhosted.org/packages/97/e7/575ca16871071313a7a7a03fa055f0c3d52f77eb8583b373ac17fc87ec15/aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d", size = 402427 }, + { url = "https://files.pythonhosted.org/packages/4e/78/266be6e31daad1a2dc99c777dfb12b62044691ec573b6e48409a0d804fc7/aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424", size = 390243 }, + { url = "https://files.pythonhosted.org/packages/73/f1/084f82069428b87d2b5c1e3e2d1d51911981f4cccd94c5c3691f10061c99/aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee", size = 1312924 }, + { url = "https://files.pythonhosted.org/packages/1f/d6/412156ea1aa44a5cc95421db85b0c7a5d1ee3ba71efad04db84305ca1968/aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2", size = 1349620 }, + { url = "https://files.pythonhosted.org/packages/3f/42/376e5e4b6f167358e1e8c6a78cae64ca49d30d6edecbab80796dbb838855/aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233", size = 1387070 }, + { url = "https://files.pythonhosted.org/packages/24/99/e76e65ca811100b445d3c8af9764b27c5180ca11a15af694366424896647/aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595", size = 1297781 }, + { url = "https://files.pythonhosted.org/packages/01/af/8da680fa69632f413860d3f4dcace47f7fc50486fe920ec43447ffaccee7/aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6", size = 1257586 }, + { url = "https://files.pythonhosted.org/packages/90/ae/a0741922ef3e99e71faa18ddf1a3a00309dd01107d3dc51f46bedd30e5c6/aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d", size = 1319016 }, + { url = "https://files.pythonhosted.org/packages/ef/bd/61671d071518ac18875c1471cf5f6e210f48c855bdfc9e6cbe47134e2921/aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323", size = 1268646 }, + { url = "https://files.pythonhosted.org/packages/ea/d1/0e1d60543d68583ed5b87f4d2eb1c72e54c68933e7799e649de04ffbb6b0/aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9", size = 1350674 }, + { url = "https://files.pythonhosted.org/packages/46/60/4f5225360aebb03d9fbf2a26c79fa01c6da326eeb160d212050990a7f658/aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771", size = 1394599 }, + { url = "https://files.pythonhosted.org/packages/6b/99/c742967d54091496a5675ae9faa910765f572e7863461ccc7fb22a1501e2/aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75", size = 1302531 }, + { url = "https://files.pythonhosted.org/packages/a7/a5/e8e0e4bf0adb3ebd3773ebb0fb006d4e4850d1a9eef0a911482eba883814/aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6", size = 350613 }, + { url = "https://files.pythonhosted.org/packages/a4/69/0d415c6d8450842652ce01b29f43416a0f30122b75899de01485623c7850/aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a", size = 370792 }, + { url = "https://files.pythonhosted.org/packages/5e/25/c6bd6cb160a4dc81f83adbc9bdd6758f01932a6c81a3e4ac707746e7855e/aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678", size = 595330 }, + { url = "https://files.pythonhosted.org/packages/18/5f/f6428eb55244d44e1c674c8c823ae1567136ac1d2f8b128e194dd4febbe1/aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c", size = 395974 }, + { url = "https://files.pythonhosted.org/packages/78/28/2080ed3140b7d25c406f77fe2d5776edd9c7a25228f7f905d7058a6e2d61/aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f", size = 392399 }, + { url = "https://files.pythonhosted.org/packages/d3/c0/cd9d02e1b9e1b1073c94f7692ffe69067987c4acc0252bbc0c7645360d37/aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4", size = 1322648 }, + { url = "https://files.pythonhosted.org/packages/f2/fb/d65d58230e9ed5cfed886b0c433634bfb14cbe183125e84de909559e29e7/aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c", size = 1362078 }, + { url = "https://files.pythonhosted.org/packages/a6/39/ca4fc97af53167ff6c8888a59002b17447bddd8dd474ae0f0e778446cfe7/aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa", size = 1404667 }, + { url = "https://files.pythonhosted.org/packages/dd/0a/526c8480bd846b9155c624c7e54db94733fc6b381dfd748cc8dd69c994b0/aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58", size = 1317772 }, + { url = "https://files.pythonhosted.org/packages/0c/ea/8e1bd13e39b3f4c37889b8480f04ed398e07017f5709d66d4e1d0dee39fe/aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf", size = 1269636 }, + { url = "https://files.pythonhosted.org/packages/2a/ac/7c00027510f42a21c0a905f2472d9afef7ea276573357829bfe8c12883d4/aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f", size = 1324957 }, + { url = "https://files.pythonhosted.org/packages/e3/f5/e0c216a12b2490cbecd79e9b7671f4e50dfc72e9a52347943aabe6f5bc44/aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81", size = 1267548 }, + { url = "https://files.pythonhosted.org/packages/88/31/e55083b026428324cde827c04bdfbc837c131f9d3ee38d28c766614b09ef/aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a", size = 1353136 }, + { url = "https://files.pythonhosted.org/packages/54/8e/72d1ddd6e653b6d4b7b1fece7619287d3319bae10ad3a7f12d956bcc9e96/aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a", size = 1400946 }, + { url = "https://files.pythonhosted.org/packages/5c/f1/f61b397a0eaf01d197e610b0f56935b0002d688f27d73af2882b282fc2f8/aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da", size = 1319358 }, + { url = "https://files.pythonhosted.org/packages/d1/5d/8cb20df780921adf9f436f214350729b12873742abd697c981229c554acc/aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59", size = 347602 }, + { url = "https://files.pythonhosted.org/packages/a0/00/cdbda8b406ce7b656b9cb765f8134b1edb999f816f54e47347d2bc67f4bf/aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888", size = 369012 }, +] + +[[package]] +name = "aiohttp-json-rpc" +version = "0.13.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/53/98/11d7a28734cbea1dd5ceb3e6603402169541a4f1a429b810988680975293/aiohttp-json-rpc-0.13.3.tar.gz", hash = "sha256:6237a104478c22c6ef96c7227a01d6832597b414e4b79a52d85593356a169e99", size = 28657 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/a3/82986305dc5e917bd05c530bd2ec951aff82a63afb6ae512f3c56046cc94/aiohttp_json_rpc-0.13.3-py3-none-any.whl", hash = "sha256:4fbd197aced61bd2df7ae3237ead7d3e08833c2ccf48b8581e1828c95ebee680", size = 30720 }, +] + +[[package]] +name = "aiosignal" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ae/67/0952ed97a9793b4958e5736f6d2b346b414a2cd63e82d05940032f45b32f/aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", size = 19422 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17", size = 7617 }, +] + +[[package]] +name = "aiosqlite" +version = "0.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0d/3a/22ff5415bf4d296c1e92b07fd746ad42c96781f13295a074d58e77747848/aiosqlite-0.20.0.tar.gz", hash = "sha256:6d35c8c256637f4672f843c31021464090805bf925385ac39473fb16eaaca3d7", size = 21691 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/c4/c93eb22025a2de6b83263dfe3d7df2e19138e345bca6f18dba7394120930/aiosqlite-0.20.0-py3-none-any.whl", hash = "sha256:36a1deaca0cac40ebe32aac9977a6e2bbc7f5189f23f4a54d5908986729e5bd6", size = 15564 }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, +] + +[[package]] +name = "apsw" +version = "3.46.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/9f/29be0326b2178cfe10d6d45de83163c70cd0b4985502f398fe32791943e2/apsw-3.46.1.0.tar.gz", hash = "sha256:96e3dfad1fd0cc77a778aa6b27468292041a8e9cb1f2dcf06bd773762c9b0c0c", size = 403954 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/64/772661433d50473bf09b4f3e777cb5580dd29093461138e897f57402be51/apsw-3.46.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8acacf3a0187cbd4c82c9eaa2c7e2704c13997a351efdffbdfa69ea1778bda1f", size = 1330000 }, + { url = "https://files.pythonhosted.org/packages/09/08/2311678a00314fcf3c007d1b17780c0ba19084c09afca89c082353785616/apsw-3.46.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2fcc5fd76a4a21fb1cc1694495e221206a46d932c675ba5dda8f070262347e0b", size = 1252124 }, + { url = "https://files.pythonhosted.org/packages/51/01/bf171dec627935691bcf8e900151031ad9b50689d488d9ef2069f5179aa2/apsw-3.46.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca319360995762fbed9e7d252c3ae4ea84af2d7bc1aef21adbcb4e088a416373", size = 5332494 }, + { url = "https://files.pythonhosted.org/packages/5e/1d/be64af8c3043d2d39bab4fc6bfc55aadfa24bffc3d8bf522908b9b831a92/apsw-3.46.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42036093f8b7dd66bbb18b717ef6dfa62c4a2acd9bcdf05fdf5caedf77a47c01", size = 5380153 }, + { url = "https://files.pythonhosted.org/packages/00/32/d9ebff5ecc7fd0100e7cb62dbbebc9edbd70d3812c4cc811ee823ec1c33c/apsw-3.46.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4d54efc7d7d58b782dc84f29c5d25d190984dec20d8233484d3b092ded1241e1", size = 5264455 }, + { url = "https://files.pythonhosted.org/packages/f9/46/ebe89b57f229a0db9eb44eafa87077a1b23881d3f366dc035047327dbeac/apsw-3.46.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3864151c23edd3a232e059925bd37044e2c1b90f20ba1d0b46005d0e5d97d10d", size = 5361349 }, + { url = "https://files.pythonhosted.org/packages/a2/72/25955d7d36264e705d8be86fdc49b1ff4a5438a8a9ff8ce78f9a806b10d1/apsw-3.46.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3e42ebb5997fcd6234cdb888f641ca37a7e9d03c13c4f2e1e0ac66151a182e79", size = 5351742 }, + { url = "https://files.pythonhosted.org/packages/56/9c/a15ed769f3b5f5012e9216598ed6db333c74bfbe3b197a217aa67c46094a/apsw-3.46.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7ea887719b60d48ac569eb42594f7dd772ab2b2287aaae9c9a007789467aa26a", size = 5423667 }, + { url = "https://files.pythonhosted.org/packages/a6/ed/a1f3437764ae69efebff2b64de0e9e7e3169fe0e44b52763cb808dbb74c3/apsw-3.46.1.0-cp311-cp311-win32.whl", hash = "sha256:67754bc4c0b2dda1a112f0adfdd6d25c2f724d8c086decb9690349056f799eed", size = 1030732 }, + { url = "https://files.pythonhosted.org/packages/8c/05/d3a57fd6da3093f12b1e92e93cf1a036e0293879198697fe2b500bfd8a17/apsw-3.46.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fef6891bc388d92ac8208db2e6f5cd90bd75a64930147f515f2e28526a278c81", size = 1203793 }, + { url = "https://files.pythonhosted.org/packages/4f/54/efebcf27cedd308a6e39d4b159450544965913679e03b9f1afac96765d90/apsw-3.46.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a892c3dccbb2f96611a0707fb4cf1573c88a4a2898b45f013a202557f602faa8", size = 1330291 }, + { url = "https://files.pythonhosted.org/packages/fb/c9/6382df13216f524a8e4d37298d6dfe3a5ba0b67a4be91082ce4858a75b5f/apsw-3.46.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e01e2cf7faae0d86540e9c638778c98cdd14b365136d9b11d2a0a7dfe4893f3", size = 1251560 }, + { url = "https://files.pythonhosted.org/packages/89/82/4f6409346583232d49bbbe14ce0dd006ff9552c9e4e3f32dc132deb8fbe9/apsw-3.46.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf96999557f5ccc5c8424b0c8637447652994e26b4fe87b72626def24c53dcf1", size = 5322282 }, + { url = "https://files.pythonhosted.org/packages/83/e2/ddb1cbe4d6e348e601c58e1d0b65b8f7bbc5b436c5820deb43e602eb918a/apsw-3.46.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925c01733c0de8adf7f3cbf299e4bcb38961b62de4436f8704e5ff9800523a7c", size = 5363048 }, + { url = "https://files.pythonhosted.org/packages/f0/c9/86a6ae3248773abe08b168c24a08fc02b4cbd55fcf013a604bc50191e908/apsw-3.46.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:979f1fca9ec09c1e8bd466ad17fde25dffb06ea621bd8b7c08e404d042c4d362", size = 5252462 }, + { url = "https://files.pythonhosted.org/packages/93/47/02a42f5889f897c4358b2c2c61c88eea80ba21dbdbd79f218a301aeb282b/apsw-3.46.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e02c614ca3afceb6c80349485dd2d49fea584a885794ca732513d8aa746781d7", size = 5352619 }, + { url = "https://files.pythonhosted.org/packages/c4/08/e989cc8b419de48c9eb07c23b780a70786ecee3bfc4525936c2fb4006ae4/apsw-3.46.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c9c130253eba2f70547253f54db05d0e6aa41962d9d712b9e1b8efba1ea2990b", size = 5333787 }, + { url = "https://files.pythonhosted.org/packages/50/15/7a1d05f1424f8bfb0f4d6bc070d97c2a416e94aca57d653a6b81d7c260eb/apsw-3.46.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:999f8fc2607a98ecfddb9d266bd746ae9a08dfa67841700ccfb0108a9cfe9104", size = 5407568 }, + { url = "https://files.pythonhosted.org/packages/76/57/ce935c45e21f95faf956e8cd0c04a583324e226f1838980c5d344a9fb2ac/apsw-3.46.1.0-cp312-cp312-win32.whl", hash = "sha256:0f864580269c5cfe7aed899057a6e76f06940d2bc4134c2e32d36aadad0b3e29", size = 1030498 }, + { url = "https://files.pythonhosted.org/packages/fa/39/a99ddf2fd49ae794885d22f0ec9e7be56ad4794a393bfbe395b9711d9dc5/apsw-3.46.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:fb770bbe185d3cd6609bb245e22108490c81a025e3be82cd278116b5e21cbbee", size = 1202387 }, + { url = "https://files.pythonhosted.org/packages/01/91/1dad0195b08a035b48fa278d3ccea1336d48e3b8a5a8be5bc0ebdc4cd5c1/apsw-3.46.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8113139847f1ad7023a2b8ab8cee15ceec2406c9fbc6709c64a029947485bc23", size = 1329935 }, + { url = "https://files.pythonhosted.org/packages/00/45/38c7f64d4d6567bc989fde6d39498c6cc6d4540c2094a38fd803662d1f06/apsw-3.46.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:038e9550dc24413a12fde36492ab275410c35982e97d33cc5fd7c18325bbc9e1", size = 1249843 }, + { url = "https://files.pythonhosted.org/packages/72/43/dc5ed5a6ad6caad5874496f6ef5b31bfa309d0dc10435f0581486e63c419/apsw-3.46.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1779f6d512d07b1fa914d268c42ac47170fd41aeae3352c3ce1c5c9f410496b9", size = 5323599 }, + { url = "https://files.pythonhosted.org/packages/3d/3c/9b5ef3e9edb7b4864ae6365cad8c5b26c6490552d1b7a9896e6dd8c37f48/apsw-3.46.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b2497696ccb5ac928ba3bbae988a82e00d0be3242b7bdd0553ce4447bdcc73b", size = 5375717 }, + { url = "https://files.pythonhosted.org/packages/df/eb/09435de9918e2f4ff05c812ccbc6f3d857fa35835303c1028e92f0b3c630/apsw-3.46.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b182bafe729822f7a934d081d9190b76e0dae1f5f098efa7430fcdd38e3a315", size = 5263638 }, + { url = "https://files.pythonhosted.org/packages/1f/8a/d1be6a390d8b524bbacfe6b2d59d94391275a38dda87cc815fed7299511a/apsw-3.46.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d08cf0df8f58b4bdf8c0b7a4c8e70f2a8840be631f40dae848b384636a22fe0d", size = 5357278 }, + { url = "https://files.pythonhosted.org/packages/11/f8/b51d9b4bacec54fcafa042c24e58e2f349cc5eedcaab31e06f4862c6bcf5/apsw-3.46.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7d37e2f6e1a22bb1a82905237b4d433124ccc53a62f918b9cf7c42c6e49241d0", size = 5335671 }, + { url = "https://files.pythonhosted.org/packages/a7/35/6a7cfdb1275a2c84f5cf5e108f49da7c491bb20b8aa6e48e8dd5d6f84dc3/apsw-3.46.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3d49e1996c13661011505cd53502e580c63062eafeebaebcd80ec34b435475c4", size = 5416144 }, + { url = "https://files.pythonhosted.org/packages/aa/8c/91264d7fcc0e70a9c09aefac0794ee9aad2006ffd0183061fb1f462fe9bb/apsw-3.46.1.0-cp313-cp313-win32.whl", hash = "sha256:42039f5d650ef1bb12e1304aebe47338c20bead38b41bae0f22f98e78cc6855c", size = 1029293 }, + { url = "https://files.pythonhosted.org/packages/cc/d2/9a917ea97c2a13978e97c854d49d286060f028ad172d9958f33cb8e29e14/apsw-3.46.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c37abd9f344aefa11c3fe213738c1db4fe49bacef1aee360087fa1ac840b1c4", size = 1200893 }, +] + +[[package]] +name = "astroid" +version = "3.3.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/38/1e/326fb1d3d83a3bb77c9f9be29d31f2901e35acb94b0605c3f2e5085047f9/astroid-3.3.5.tar.gz", hash = "sha256:5cfc40ae9f68311075d27ef68a4841bdc5cc7f6cf86671b49f00607d30188e2d", size = 397229 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/30/624365383fa4a40329c0f0bbbc151abc4a64e30dfc110fc8f6e2afcd02bb/astroid-3.3.5-py3-none-any.whl", hash = "sha256:a9d1c946ada25098d790e079ba2a1b112157278f3fb7e718ae6a9252f5835dc8", size = 274586 }, +] + +[[package]] +name = "async-timeout" +version = "4.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/87/d6/21b30a550dafea84b1b8eee21b5e23fa16d010ae006011221f33dcd8d7f8/async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", size = 8345 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/fa/e01228c2938de91d47b307831c62ab9e4001e747789d0b05baf779a6488c/async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028", size = 5721 }, +] + +[[package]] +name = "attrs" +version = "24.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/0f/aafca9af9315aee06a89ffde799a10a582fe8de76c563ee80bbcdc08b3fb/attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346", size = 792678 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2", size = 63001 }, +] + +[[package]] +name = "babel" +version = "2.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/74/f1bc80f23eeba13393b7222b11d95ca3af2c1e28edca18af487137eefed9/babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316", size = 9348104 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/20/bc79bc575ba2e2a7f70e8a1155618bb1301eaa5132a8271373a6903f73f8/babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b", size = 9587599 }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/ca/824b1195773ce6166d388573fc106ce56d4a805bd7427b624e063596ec58/beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051", size = 581181 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed", size = 147925 }, +] + +[[package]] +name = "blinker" +version = "1.8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/57/a6a1721eff09598fb01f3c7cda070c1b6a0f12d63c83236edf79a440abcc/blinker-1.8.2.tar.gz", hash = "sha256:8f77b09d3bf7c795e969e9486f39c2c5e9c39d4ee07424be2bc594ece9642d83", size = 23161 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/2a/10164ed1f31196a2f7f3799368a821765c62851ead0e630ab52b8e14b4d0/blinker-1.8.2-py3-none-any.whl", hash = "sha256:1779309f71bf239144b9399d06ae925637cf6634cf6bd131104184531bf67c01", size = 9456 }, +] + +[[package]] +name = "brotli" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2f/c2/f9e977608bdf958650638c3f1e28f85a1b075f075ebbe77db8555463787b/Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724", size = 7372270 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/12/ad41e7fadd5db55459c4c401842b47f7fee51068f86dd2894dd0dcfc2d2a/Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc", size = 873068 }, + { url = "https://files.pythonhosted.org/packages/95/4e/5afab7b2b4b61a84e9c75b17814198ce515343a44e2ed4488fac314cd0a9/Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6", size = 446244 }, + { url = "https://files.pythonhosted.org/packages/9d/e6/f305eb61fb9a8580c525478a4a34c5ae1a9bcb12c3aee619114940bc513d/Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd", size = 2906500 }, + { url = "https://files.pythonhosted.org/packages/3e/4f/af6846cfbc1550a3024e5d3775ede1e00474c40882c7bf5b37a43ca35e91/Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf", size = 2943950 }, + { url = "https://files.pythonhosted.org/packages/b3/e7/ca2993c7682d8629b62630ebf0d1f3bb3d579e667ce8e7ca03a0a0576a2d/Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61", size = 2918527 }, + { url = "https://files.pythonhosted.org/packages/b3/96/da98e7bedc4c51104d29cc61e5f449a502dd3dbc211944546a4cc65500d3/Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327", size = 2845489 }, + { url = "https://files.pythonhosted.org/packages/e8/ef/ccbc16947d6ce943a7f57e1a40596c75859eeb6d279c6994eddd69615265/Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd", size = 2914080 }, + { url = "https://files.pythonhosted.org/packages/80/d6/0bd38d758d1afa62a5524172f0b18626bb2392d717ff94806f741fcd5ee9/Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9", size = 2813051 }, + { url = "https://files.pythonhosted.org/packages/14/56/48859dd5d129d7519e001f06dcfbb6e2cf6db92b2702c0c2ce7d97e086c1/Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265", size = 2938172 }, + { url = "https://files.pythonhosted.org/packages/3d/77/a236d5f8cd9e9f4348da5acc75ab032ab1ab2c03cc8f430d24eea2672888/Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8", size = 2933023 }, + { url = "https://files.pythonhosted.org/packages/e7/71/8f161dee223c7ff7fea9d44893fba953ce97cf2c3c33f78ba260a91bcff5/Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50", size = 333169 }, + { url = "https://files.pythonhosted.org/packages/02/8a/fece0ee1057643cb2a5bbf59682de13f1725f8482b2c057d4e799d7ade75/Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1", size = 357253 }, + { url = "https://files.pythonhosted.org/packages/06/88/564958cedce636d0f1bed313381dfc4b4e3d3f6015a63dae6146e1b8c65c/Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", size = 873081 }, + { url = "https://files.pythonhosted.org/packages/58/79/b7026a8bb65da9a6bb7d14329fd2bd48d2b7f86d7329d5cc8ddc6a90526f/Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", size = 446244 }, + { url = "https://files.pythonhosted.org/packages/e5/18/c18c32ecea41b6c0004e15606e274006366fe19436b6adccc1ae7b2e50c2/Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", size = 2906505 }, + { url = "https://files.pythonhosted.org/packages/08/c8/69ec0496b1ada7569b62d85893d928e865df29b90736558d6c98c2031208/Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91", size = 2944152 }, + { url = "https://files.pythonhosted.org/packages/ab/fb/0517cea182219d6768113a38167ef6d4eb157a033178cc938033a552ed6d/Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408", size = 2919252 }, + { url = "https://files.pythonhosted.org/packages/c7/53/73a3431662e33ae61a5c80b1b9d2d18f58dfa910ae8dd696e57d39f1a2f5/Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0", size = 2845955 }, + { url = "https://files.pythonhosted.org/packages/55/ac/bd280708d9c5ebdbf9de01459e625a3e3803cce0784f47d633562cf40e83/Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc", size = 2914304 }, + { url = "https://files.pythonhosted.org/packages/76/58/5c391b41ecfc4527d2cc3350719b02e87cb424ef8ba2023fb662f9bf743c/Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", size = 2814452 }, + { url = "https://files.pythonhosted.org/packages/c7/4e/91b8256dfe99c407f174924b65a01f5305e303f486cc7a2e8a5d43c8bec3/Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", size = 2938751 }, + { url = "https://files.pythonhosted.org/packages/5a/a6/e2a39a5d3b412938362bbbeba5af904092bf3f95b867b4a3eb856104074e/Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", size = 2933757 }, + { url = "https://files.pythonhosted.org/packages/5f/3b/4e3fd1893eb3bbfef8e5a80d4508bec17a57bb92d586c85c12d28666bb13/Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", size = 333276 }, + { url = "https://files.pythonhosted.org/packages/3d/d5/942051b45a9e883b5b6e98c041698b1eb2012d25e5948c58d6bf85b1bb43/Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", size = 357255 }, +] + +[[package]] +name = "cairocffi" +version = "1.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/70/c5/1a4dc131459e68a173cbdab5fad6b524f53f9c1ef7861b7698e998b837cc/cairocffi-1.7.1.tar.gz", hash = "sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b", size = 88096 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/d8/ba13451aa6b745c49536e87b6bf8f629b950e84bd0e8308f7dc6883b67e2/cairocffi-1.7.1-py3-none-any.whl", hash = "sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f", size = 75611 }, +] + +[[package]] +name = "cairosvg" +version = "2.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cairocffi" }, + { name = "cssselect2" }, + { name = "defusedxml" }, + { name = "pillow" }, + { name = "tinycss2" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d5/e6/ec5900b724e3c44af7f6f51f719919137284e5da4aabe96508baec8a1b40/CairoSVG-2.7.1.tar.gz", hash = "sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0", size = 8399085 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/a5/1866b42151f50453f1a0d28fc4c39f5be5f412a2e914f33449c42daafdf1/CairoSVG-2.7.1-py3-none-any.whl", hash = "sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b", size = 43235 }, +] + +[[package]] +name = "certifi" +version = "2024.8.30" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9", size = 168507 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", size = 167321 }, +] + +[[package]] +name = "cffi" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264 }, + { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651 }, + { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259 }, + { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200 }, + { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235 }, + { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721 }, + { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242 }, + { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999 }, + { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242 }, + { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604 }, + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, + { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, + { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, + { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", size = 106620 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c", size = 193339 }, + { url = "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944", size = 124366 }, + { url = "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee", size = 118874 }, + { url = "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c", size = 138243 }, + { url = "https://files.pythonhosted.org/packages/e2/29/d227805bff72ed6d6cb1ce08eec707f7cfbd9868044893617eb331f16295/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6", size = 148676 }, + { url = "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea", size = 141289 }, + { url = "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc", size = 142585 }, + { url = "https://files.pythonhosted.org/packages/3b/a0/a68980ab8a1f45a36d9745d35049c1af57d27255eff8c907e3add84cf68f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5", size = 144408 }, + { url = "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594", size = 139076 }, + { url = "https://files.pythonhosted.org/packages/fb/9d/9c13753a5a6e0db4a0a6edb1cef7aee39859177b64e1a1e748a6e3ba62c2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c", size = 146874 }, + { url = "https://files.pythonhosted.org/packages/75/d2/0ab54463d3410709c09266dfb416d032a08f97fd7d60e94b8c6ef54ae14b/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365", size = 150871 }, + { url = "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129", size = 148546 }, + { url = "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236", size = 143048 }, + { url = "https://files.pythonhosted.org/packages/01/f8/38842422988b795220eb8038745d27a675ce066e2ada79516c118f291f07/charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99", size = 94389 }, + { url = "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27", size = 101752 }, + { url = "https://files.pythonhosted.org/packages/d3/0b/4b7a70987abf9b8196845806198975b6aab4ce016632f817ad758a5aa056/charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6", size = 194445 }, + { url = "https://files.pythonhosted.org/packages/50/89/354cc56cf4dd2449715bc9a0f54f3aef3dc700d2d62d1fa5bbea53b13426/charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf", size = 125275 }, + { url = "https://files.pythonhosted.org/packages/fa/44/b730e2a2580110ced837ac083d8ad222343c96bb6b66e9e4e706e4d0b6df/charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db", size = 119020 }, + { url = "https://files.pythonhosted.org/packages/9d/e4/9263b8240ed9472a2ae7ddc3e516e71ef46617fe40eaa51221ccd4ad9a27/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1", size = 139128 }, + { url = "https://files.pythonhosted.org/packages/6b/e3/9f73e779315a54334240353eaea75854a9a690f3f580e4bd85d977cb2204/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03", size = 149277 }, + { url = "https://files.pythonhosted.org/packages/1a/cf/f1f50c2f295312edb8a548d3fa56a5c923b146cd3f24114d5adb7e7be558/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284", size = 142174 }, + { url = "https://files.pythonhosted.org/packages/16/92/92a76dc2ff3a12e69ba94e7e05168d37d0345fa08c87e1fe24d0c2a42223/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15", size = 143838 }, + { url = "https://files.pythonhosted.org/packages/a4/01/2117ff2b1dfc61695daf2babe4a874bca328489afa85952440b59819e9d7/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8", size = 146149 }, + { url = "https://files.pythonhosted.org/packages/f6/9b/93a332b8d25b347f6839ca0a61b7f0287b0930216994e8bf67a75d050255/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2", size = 140043 }, + { url = "https://files.pythonhosted.org/packages/ab/f6/7ac4a01adcdecbc7a7587767c776d53d369b8b971382b91211489535acf0/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719", size = 148229 }, + { url = "https://files.pythonhosted.org/packages/9d/be/5708ad18161dee7dc6a0f7e6cf3a88ea6279c3e8484844c0590e50e803ef/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631", size = 151556 }, + { url = "https://files.pythonhosted.org/packages/5a/bb/3d8bc22bacb9eb89785e83e6723f9888265f3a0de3b9ce724d66bd49884e/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b", size = 149772 }, + { url = "https://files.pythonhosted.org/packages/f7/fa/d3fc622de05a86f30beea5fc4e9ac46aead4731e73fd9055496732bcc0a4/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565", size = 144800 }, + { url = "https://files.pythonhosted.org/packages/9a/65/bdb9bc496d7d190d725e96816e20e2ae3a6fa42a5cac99c3c3d6ff884118/charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7", size = 94836 }, + { url = "https://files.pythonhosted.org/packages/3e/67/7b72b69d25b89c0b3cea583ee372c43aa24df15f0e0f8d3982c57804984b/charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9", size = 102187 }, + { url = "https://files.pythonhosted.org/packages/f3/89/68a4c86f1a0002810a27f12e9a7b22feb198c59b2f05231349fbce5c06f4/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114", size = 194617 }, + { url = "https://files.pythonhosted.org/packages/4f/cd/8947fe425e2ab0aa57aceb7807af13a0e4162cd21eee42ef5b053447edf5/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed", size = 125310 }, + { url = "https://files.pythonhosted.org/packages/5b/f0/b5263e8668a4ee9becc2b451ed909e9c27058337fda5b8c49588183c267a/charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250", size = 119126 }, + { url = "https://files.pythonhosted.org/packages/ff/6e/e445afe4f7fda27a533f3234b627b3e515a1b9429bc981c9a5e2aa5d97b6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920", size = 139342 }, + { url = "https://files.pythonhosted.org/packages/a1/b2/4af9993b532d93270538ad4926c8e37dc29f2111c36f9c629840c57cd9b3/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64", size = 149383 }, + { url = "https://files.pythonhosted.org/packages/fb/6f/4e78c3b97686b871db9be6f31d64e9264e889f8c9d7ab33c771f847f79b7/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23", size = 142214 }, + { url = "https://files.pythonhosted.org/packages/2b/c9/1c8fe3ce05d30c87eff498592c89015b19fade13df42850aafae09e94f35/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc", size = 144104 }, + { url = "https://files.pythonhosted.org/packages/ee/68/efad5dcb306bf37db7db338338e7bb8ebd8cf38ee5bbd5ceaaaa46f257e6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d", size = 146255 }, + { url = "https://files.pythonhosted.org/packages/0c/75/1ed813c3ffd200b1f3e71121c95da3f79e6d2a96120163443b3ad1057505/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88", size = 140251 }, + { url = "https://files.pythonhosted.org/packages/7d/0d/6f32255c1979653b448d3c709583557a4d24ff97ac4f3a5be156b2e6a210/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90", size = 148474 }, + { url = "https://files.pythonhosted.org/packages/ac/a0/c1b5298de4670d997101fef95b97ac440e8c8d8b4efa5a4d1ef44af82f0d/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b", size = 151849 }, + { url = "https://files.pythonhosted.org/packages/04/4f/b3961ba0c664989ba63e30595a3ed0875d6790ff26671e2aae2fdc28a399/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d", size = 149781 }, + { url = "https://files.pythonhosted.org/packages/d8/90/6af4cd042066a4adad58ae25648a12c09c879efa4849c705719ba1b23d8c/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482", size = 144970 }, + { url = "https://files.pythonhosted.org/packages/cc/67/e5e7e0cbfefc4ca79025238b43cdf8a2037854195b37d6417f3d0895c4c2/charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67", size = 94973 }, + { url = "https://files.pythonhosted.org/packages/65/97/fc9bbc54ee13d33dc54a7fcf17b26368b18505500fc01e228c27b5222d80/charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b", size = 102308 }, + { url = "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", size = 49446 }, +] + +[[package]] +name = "click" +version = "8.1.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "platform_system == 'Windows'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "colorthief" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pillow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b6/b2/b55b741f7a7d1299d23e1c635f00f6c57ea4d2e9b76d09e1fc5ea3ca9921/colorthief-0.2.1.tar.gz", hash = "sha256:079cb0c95bdd669c4643e2f7494de13b0b6029d5cdbe2d74d5d3c3386bd57221", size = 6164 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/18/be03b7058e65f9df479b14e7af4e73945ce311e07aaad45cf2536e14791a/colorthief-0.2.1-py2.py3-none-any.whl", hash = "sha256:b04fc8ce5cf9c888768745e29cb19b7b688d5711af6fba26e8057debabec56b9", size = 6134 }, +] + +[[package]] +name = "cssselect2" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tinycss2" }, + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/fc/326cb6f988905998f09bb54a3f5d98d4462ba119363c0dfad29750d48c09/cssselect2-0.7.0.tar.gz", hash = "sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a", size = 35888 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/3a/e39436efe51894243ff145a37c4f9a030839b97779ebcc4f13b3ba21c54e/cssselect2-0.7.0-py3-none-any.whl", hash = "sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969", size = 15586 }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604 }, +] + +[[package]] +name = "dill" +version = "0.3.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/43/86fe3f9e130c4137b0f1b50784dd70a5087b911fe07fa81e53e0c4c47fea/dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c", size = 187000 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a", size = 119418 }, +] + +[[package]] +name = "discord-py" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/39/af/80cab4015722d3bee175509b7249a11d5adf77b5ff4c27f268558079d149/discord_py-2.4.0.tar.gz", hash = "sha256:d07cb2a223a185873a1d0ee78b9faa9597e45b3f6186df21a95cec1e9bcdc9a5", size = 1027707 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/10/3c44e9331a5ec3bae8b2919d51f611a5b94e179563b1b89eb6423a8f43eb/discord.py-2.4.0-py3-none-any.whl", hash = "sha256:b8af6711c70f7e62160bfbecb55be699b5cb69d007426759ab8ab06b1bd77d1d", size = 1125988 }, +] + +[[package]] +name = "distro" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277 }, +] + +[[package]] +name = "flask" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "blinker" }, + { name = "click" }, + { name = "itsdangerous" }, + { name = "jinja2" }, + { name = "werkzeug" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/41/e1/d104c83026f8d35dfd2c261df7d64738341067526406b40190bc063e829a/flask-3.0.3.tar.gz", hash = "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842", size = 676315 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/80/ffe1da13ad9300f87c93af113edd0638c75138c42a0994becfacac078c06/flask-3.0.3-py3-none-any.whl", hash = "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3", size = 101735 }, +] + +[[package]] +name = "frozenlist" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/3d/2102257e7acad73efc4a0c306ad3953f68c504c16982bbdfee3ad75d8085/frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b", size = 37820 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/bc/8d33f2d84b9368da83e69e42720cff01c5e199b5a868ba4486189a4d8fa9/frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0", size = 97060 }, + { url = "https://files.pythonhosted.org/packages/af/b2/904500d6a162b98a70e510e743e7ea992241b4f9add2c8063bf666ca21df/frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49", size = 55347 }, + { url = "https://files.pythonhosted.org/packages/5b/9c/f12b69997d3891ddc0d7895999a00b0c6a67f66f79498c0e30f27876435d/frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced", size = 53374 }, + { url = "https://files.pythonhosted.org/packages/ac/6e/e0322317b7c600ba21dec224498c0c5959b2bce3865277a7c0badae340a9/frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0", size = 273288 }, + { url = "https://files.pythonhosted.org/packages/a7/76/180ee1b021568dad5b35b7678616c24519af130ed3fa1e0f1ed4014e0f93/frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106", size = 284737 }, + { url = "https://files.pythonhosted.org/packages/05/08/40159d706a6ed983c8aca51922a93fc69f3c27909e82c537dd4054032674/frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068", size = 280267 }, + { url = "https://files.pythonhosted.org/packages/e0/18/9f09f84934c2b2aa37d539a322267939770362d5495f37783440ca9c1b74/frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2", size = 258778 }, + { url = "https://files.pythonhosted.org/packages/b3/c9/0bc5ee7e1f5cc7358ab67da0b7dfe60fbd05c254cea5c6108e7d1ae28c63/frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19", size = 272276 }, + { url = "https://files.pythonhosted.org/packages/12/5d/147556b73a53ad4df6da8bbb50715a66ac75c491fdedac3eca8b0b915345/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82", size = 272424 }, + { url = "https://files.pythonhosted.org/packages/83/61/2087bbf24070b66090c0af922685f1d0596c24bb3f3b5223625bdeaf03ca/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec", size = 260881 }, + { url = "https://files.pythonhosted.org/packages/a8/be/a235bc937dd803258a370fe21b5aa2dd3e7bfe0287a186a4bec30c6cccd6/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a", size = 282327 }, + { url = "https://files.pythonhosted.org/packages/5d/e7/b2469e71f082948066b9382c7b908c22552cc705b960363c390d2e23f587/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74", size = 281502 }, + { url = "https://files.pythonhosted.org/packages/db/1b/6a5b970e55dffc1a7d0bb54f57b184b2a2a2ad0b7bca16a97ca26d73c5b5/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2", size = 272292 }, + { url = "https://files.pythonhosted.org/packages/1a/05/ebad68130e6b6eb9b287dacad08ea357c33849c74550c015b355b75cc714/frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17", size = 44446 }, + { url = "https://files.pythonhosted.org/packages/b3/21/c5aaffac47fd305d69df46cfbf118768cdf049a92ee6b0b5cb029d449dcf/frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825", size = 50459 }, + { url = "https://files.pythonhosted.org/packages/b4/db/4cf37556a735bcdb2582f2c3fa286aefde2322f92d3141e087b8aeb27177/frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae", size = 93937 }, + { url = "https://files.pythonhosted.org/packages/46/03/69eb64642ca8c05f30aa5931d6c55e50b43d0cd13256fdd01510a1f85221/frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb", size = 53656 }, + { url = "https://files.pythonhosted.org/packages/3f/ab/c543c13824a615955f57e082c8a5ee122d2d5368e80084f2834e6f4feced/frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b", size = 51868 }, + { url = "https://files.pythonhosted.org/packages/a9/b8/438cfd92be2a124da8259b13409224d9b19ef8f5a5b2507174fc7e7ea18f/frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86", size = 280652 }, + { url = "https://files.pythonhosted.org/packages/54/72/716a955521b97a25d48315c6c3653f981041ce7a17ff79f701298195bca3/frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480", size = 286739 }, + { url = "https://files.pythonhosted.org/packages/65/d8/934c08103637567084568e4d5b4219c1016c60b4d29353b1a5b3587827d6/frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09", size = 289447 }, + { url = "https://files.pythonhosted.org/packages/70/bb/d3b98d83ec6ef88f9bd63d77104a305d68a146fd63a683569ea44c3085f6/frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a", size = 265466 }, + { url = "https://files.pythonhosted.org/packages/0b/f2/b8158a0f06faefec33f4dff6345a575c18095a44e52d4f10c678c137d0e0/frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd", size = 281530 }, + { url = "https://files.pythonhosted.org/packages/ea/a2/20882c251e61be653764038ece62029bfb34bd5b842724fff32a5b7a2894/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6", size = 281295 }, + { url = "https://files.pythonhosted.org/packages/4c/f9/8894c05dc927af2a09663bdf31914d4fb5501653f240a5bbaf1e88cab1d3/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1", size = 268054 }, + { url = "https://files.pythonhosted.org/packages/37/ff/a613e58452b60166507d731812f3be253eb1229808e59980f0405d1eafbf/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b", size = 286904 }, + { url = "https://files.pythonhosted.org/packages/cc/6e/0091d785187f4c2020d5245796d04213f2261ad097e0c1cf35c44317d517/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e", size = 290754 }, + { url = "https://files.pythonhosted.org/packages/a5/c2/e42ad54bae8bcffee22d1e12a8ee6c7717f7d5b5019261a8c861854f4776/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8", size = 282602 }, + { url = "https://files.pythonhosted.org/packages/b6/61/56bad8cb94f0357c4bc134acc30822e90e203b5cb8ff82179947de90c17f/frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89", size = 44063 }, + { url = "https://files.pythonhosted.org/packages/3e/dc/96647994a013bc72f3d453abab18340b7f5e222b7b7291e3697ca1fcfbd5/frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5", size = 50452 }, + { url = "https://files.pythonhosted.org/packages/83/10/466fe96dae1bff622021ee687f68e5524d6392b0a2f80d05001cd3a451ba/frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7", size = 11552 }, +] + +[[package]] +name = "ghp-import" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034 }, +] + +[[package]] +name = "gitdb" +version = "4.0.11" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "smmap" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/0d/bbb5b5ee188dec84647a4664f3e11b06ade2bde568dbd489d9d64adef8ed/gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b", size = 394469 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/5b/8f0c4a5bb9fd491c277c21eff7ccae71b47d43c4446c9d0c6cff2fe8c2c4/gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", size = 62721 }, +] + +[[package]] +name = "gitpython" +version = "3.1.43" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "gitdb" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b6/a1/106fd9fa2dd989b6fb36e5893961f82992cf676381707253e0bf93eb1662/GitPython-3.1.43.tar.gz", hash = "sha256:35f314a9f878467f5453cc1fee295c3e18e52f1b99f10f6cf5b1682e968a9e7c", size = 214149 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/bd/cc3a402a6439c15c3d4294333e13042b915bbeab54edc457c723931fed3f/GitPython-3.1.43-py3-none-any.whl", hash = "sha256:eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff", size = 207337 }, +] + +[[package]] +name = "griffe" +version = "1.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/37/813e72a3458fa3d996cf6bcc6a0caa919d16540f873366b0d328d51d684a/griffe-1.3.2.tar.gz", hash = "sha256:1ec50335aa507ed2445f2dd45a15c9fa3a45f52c9527e880571dfc61912fd60c", size = 382540 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/49/39967633dd3c5f06fde83fec140228671a7344289ece0cfdd3cbe4798d69/griffe-1.3.2-py3-none-any.whl", hash = "sha256:2e34b5e46507d615915c8e6288bb1a2234bd35dee44d01e40a2bc2f25bd4d10c", size = 126992 }, +] + +[[package]] +name = "idna" +version = "3.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/ac/e349c5e6d4543326c6883ee9491e3921e0d07b55fdf3cce184b40d63e72a/idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603", size = 189467 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/7e/d71db821f177828df9dea8c42ac46473366f191be53080e552e628aad991/idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac", size = 66894 }, +] + +[[package]] +name = "importlib-metadata" +version = "8.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/bd/fa8ce65b0a7d4b6d143ec23b0f5fd3f7ab80121078c465bc02baeaab22dc/importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5", size = 54320 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/14/362d31bf1076b21e1bcdcb0dc61944822ff263937b804a79231df2774d28/importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1", size = 26269 }, +] + +[[package]] +name = "isort" +version = "5.13.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/87/f9/c1eb8635a24e87ade2efce21e3ce8cd6b8630bb685ddc9cdaca1349b2eb5/isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109", size = 175303 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/b3/8def84f539e7d2289a02f0524b944b15d7c75dab7628bedf1c4f0992029c/isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6", size = 92310 }, +] + +[[package]] +name = "itsdangerous" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234 }, +] + +[[package]] +name = "jinja2" +version = "3.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 }, +] + +[[package]] +name = "markdown" +version = "3.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/28/3af612670f82f4c056911fbbbb42760255801b3068c48de792d354ff4472/markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2", size = 357086 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/08/83871f3c50fc983b88547c196d11cf8c3340e37c32d2e9d6152abe2c61f7/Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803", size = 106349 }, +] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, +] + +[[package]] +name = "markdownify" +version = "0.13.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/5a/bd1b685ee9efbfb0b22774a30188dfb4048c64e8a6c80a65a7f207af4ea1/markdownify-0.13.1.tar.gz", hash = "sha256:ab257f9e6bd4075118828a28c9d02f8a4bfeb7421f558834aa79b2dfeb32a098", size = 13609 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/e9/6e2757a670b8c48bc48eff1c20cb9d71f1476e844038bdbdb76f17e6a12b/markdownify-0.13.1-py3-none-any.whl", hash = "sha256:1d181d43d20902bcc69d7be85b5316ed174d0dda72ff56e14ae4c95a4a407d22", size = 10800 }, +] + +[[package]] +name = "markupsafe" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/d2/38ff920762f2247c3af5cbbbbc40756f575d9692d381d7c520f45deb9b8f/markupsafe-3.0.1.tar.gz", hash = "sha256:3e683ee4f5d0fa2dde4db77ed8dd8a876686e3fc417655c2ece9a90576905344", size = 20249 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/af/2f5d88a7fc7226bd34c6e15f6061246ad8cff979da9f19d11bdd0addd8e2/MarkupSafe-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad", size = 14387 }, + { url = "https://files.pythonhosted.org/packages/8d/43/fd588ef5d192308c5e05974bac659bf6ae29c202b7ea2c4194bcf01eacee/MarkupSafe-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b954093679d5750495725ea6f88409946d69cfb25ea7b4c846eef5044194f583", size = 12410 }, + { url = "https://files.pythonhosted.org/packages/58/26/78f161d602fb03804118905e5faacafc0ec592bbad71aaee62537529813a/MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:973a371a55ce9ed333a3a0f8e0bcfae9e0d637711534bcb11e130af2ab9334e7", size = 24006 }, + { url = "https://files.pythonhosted.org/packages/ae/1d/7d5ec8bcfd9c2db235d720fa51d818b7e2abc45250ce5f53dd6cb60409ca/MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b", size = 23303 }, + { url = "https://files.pythonhosted.org/packages/26/ce/703ca3b03a709e3bd1fbffa407789e56b9fa664456538092617dd665fc1d/MarkupSafe-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d98e66a24497637dd31ccab090b34392dddb1f2f811c4b4cd80c230205c074a3", size = 23205 }, + { url = "https://files.pythonhosted.org/packages/88/60/40be0493decabc2344b12d3a709fd6ccdd15a5ebaee1e8d878315d107ad3/MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ad91738f14eb8da0ff82f2acd0098b6257621410dcbd4df20aaa5b4233d75a50", size = 23684 }, + { url = "https://files.pythonhosted.org/packages/6d/f8/8fd52a66e8f62a9add62b4a0b5a3ab4092027437f2ef027f812d94ae91cf/MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7044312a928a66a4c2a22644147bc61a199c1709712069a344a3fb5cfcf16915", size = 23472 }, + { url = "https://files.pythonhosted.org/packages/d4/0b/998b17b9e06ea45ad1646fea586f1b83d02dfdb14d47dd2fd81fba5a08c9/MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a4792d3b3a6dfafefdf8e937f14906a51bd27025a36f4b188728a73382231d91", size = 23388 }, + { url = "https://files.pythonhosted.org/packages/5a/57/b6b7aa23b2e26d68d601718f8ce3161fbdaf967b31752c7dec52bef828c9/MarkupSafe-3.0.1-cp311-cp311-win32.whl", hash = "sha256:fa7d686ed9883f3d664d39d5a8e74d3c5f63e603c2e3ff0abcba23eac6542635", size = 15106 }, + { url = "https://files.pythonhosted.org/packages/fc/b5/20cb1d714596acb553c810009c8004c809823947da63e13c19a7decfcb6c/MarkupSafe-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ba25a71ebf05b9bb0e2ae99f8bc08a07ee8e98c612175087112656ca0f5c8bf", size = 15542 }, + { url = "https://files.pythonhosted.org/packages/45/6d/72ed58d42a12bd9fc288dbff6dd8d03ea973a232ac0538d7f88d105b5251/MarkupSafe-3.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8ae369e84466aa70f3154ee23c1451fda10a8ee1b63923ce76667e3077f2b0c4", size = 14322 }, + { url = "https://files.pythonhosted.org/packages/86/f5/241238f89cdd6461ac9f521af8389f9a48fab97e4f315c69e9e0d52bc919/MarkupSafe-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40f1e10d51c92859765522cbd79c5c8989f40f0419614bcdc5015e7b6bf97fc5", size = 12380 }, + { url = "https://files.pythonhosted.org/packages/27/94/79751928bca5841416d8ca02e22198672e021d5c7120338e2a6e3771f8fc/MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a4cb365cb49b750bdb60b846b0c0bc49ed62e59a76635095a179d440540c346", size = 24099 }, + { url = "https://files.pythonhosted.org/packages/10/6e/1b8070bbfc467429c7983cd5ffd4ec57e1d501763d974c7caaa0a9a79f4c/MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee3941769bd2522fe39222206f6dd97ae83c442a94c90f2b7a25d847d40f4729", size = 23249 }, + { url = "https://files.pythonhosted.org/packages/66/50/9389ae6cdff78d7481a2a2641830b5eb1d1f62177550e73355a810a889c9/MarkupSafe-3.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62fada2c942702ef8952754abfc1a9f7658a4d5460fabe95ac7ec2cbe0d02abc", size = 23149 }, + { url = "https://files.pythonhosted.org/packages/16/02/5dddff5366fde47133186efb847fa88bddef85914bbe623e25cfeccb3517/MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c2d64fdba74ad16138300815cfdc6ab2f4647e23ced81f59e940d7d4a1469d9", size = 23864 }, + { url = "https://files.pythonhosted.org/packages/f3/f1/700ee6655561cfda986e03f7afc309e3738918551afa7dedd99225586227/MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fb532dd9900381d2e8f48172ddc5a59db4c445a11b9fab40b3b786da40d3b56b", size = 23440 }, + { url = "https://files.pythonhosted.org/packages/fb/3e/d26623ac7f16709823b4c80e0b4a1c9196eeb46182a6c1d47b5e0c8434f4/MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0f84af7e813784feb4d5e4ff7db633aba6c8ca64a833f61d8e4eade234ef0c38", size = 23610 }, + { url = "https://files.pythonhosted.org/packages/51/04/1f8da0810c39cb9fcff96b6baed62272c97065e9cf11471965a161439e20/MarkupSafe-3.0.1-cp312-cp312-win32.whl", hash = "sha256:cbf445eb5628981a80f54087f9acdbf84f9b7d862756110d172993b9a5ae81aa", size = 15113 }, + { url = "https://files.pythonhosted.org/packages/eb/24/a36dc37365bdd358b1e583cc40475593e36ab02cb7da6b3d0b9c05b0da7a/MarkupSafe-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:a10860e00ded1dd0a65b83e717af28845bb7bd16d8ace40fe5531491de76b79f", size = 15611 }, + { url = "https://files.pythonhosted.org/packages/b1/60/4572a8aa1beccbc24b133aa0670781a5d2697f4fa3fecf0a87b46383174b/MarkupSafe-3.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e81c52638315ff4ac1b533d427f50bc0afc746deb949210bc85f05d4f15fd772", size = 14325 }, + { url = "https://files.pythonhosted.org/packages/38/42/849915b99a765ec104bfd07ee933de5fc9c58fa9570efa7db81717f495d8/MarkupSafe-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:312387403cd40699ab91d50735ea7a507b788091c416dd007eac54434aee51da", size = 12373 }, + { url = "https://files.pythonhosted.org/packages/ef/82/4caaebd963c6d60b28e4445f38841d24f8b49bc10594a09956c9d73bfc08/MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ae99f31f47d849758a687102afdd05bd3d3ff7dbab0a8f1587981b58a76152a", size = 24059 }, + { url = "https://files.pythonhosted.org/packages/20/15/6b319be2f79fcfa3173f479d69f4e950b5c9b642db4f22cf73ae5ade745f/MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c97ff7fedf56d86bae92fa0a646ce1a0ec7509a7578e1ed238731ba13aabcd1c", size = 23211 }, + { url = "https://files.pythonhosted.org/packages/9d/3f/8963bdf4962feb2154475acb7dc350f04217b5e0be7763a39b432291e229/MarkupSafe-3.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7420ceda262dbb4b8d839a4ec63d61c261e4e77677ed7c66c99f4e7cb5030dd", size = 23095 }, + { url = "https://files.pythonhosted.org/packages/af/93/f770bc70953d32de0c6ce4bcb76271512123a1ead91aaef625a020c5bfaf/MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45d42d132cff577c92bfba536aefcfea7e26efb975bd455db4e6602f5c9f45e7", size = 23901 }, + { url = "https://files.pythonhosted.org/packages/11/92/1e5a33aa0a1190161238628fb68eb1bc5e67b56a5c89f0636328704b463a/MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c8817557d0de9349109acb38b9dd570b03cc5014e8aabf1cbddc6e81005becd", size = 23463 }, + { url = "https://files.pythonhosted.org/packages/0d/fe/657efdfe385d2a3a701f2c4fcc9577c63c438aeefdd642d0d956c4ecd225/MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a54c43d3ec4cf2a39f4387ad044221c66a376e58c0d0e971d47c475ba79c6b5", size = 23569 }, + { url = "https://files.pythonhosted.org/packages/cf/24/587dea40304046ace60f846cedaebc0d33d967a3ce46c11395a10e7a78ba/MarkupSafe-3.0.1-cp313-cp313-win32.whl", hash = "sha256:c91b394f7601438ff79a4b93d16be92f216adb57d813a78be4446fe0f6bc2d8c", size = 15117 }, + { url = "https://files.pythonhosted.org/packages/32/8f/d8961d633f26a011b4fe054f3bfff52f673423b8c431553268741dfb089e/MarkupSafe-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:fe32482b37b4b00c7a52a07211b479653b7fe4f22b2e481b9a9b099d8a430f2f", size = 15613 }, + { url = "https://files.pythonhosted.org/packages/9e/93/d6367ffbcd0c5c371370767f768eaa32af60bc411245b8517e383c6a2b12/MarkupSafe-3.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:17b2aea42a7280db02ac644db1d634ad47dcc96faf38ab304fe26ba2680d359a", size = 14563 }, + { url = "https://files.pythonhosted.org/packages/4a/37/f813c3835747dec08fe19ac9b9eced01fdf93a4b3e626521675dc7f423a9/MarkupSafe-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:852dc840f6d7c985603e60b5deaae1d89c56cb038b577f6b5b8c808c97580f1d", size = 12505 }, + { url = "https://files.pythonhosted.org/packages/72/bf/800b4d1580298ca91ccd6c95915bbd147142dad1b8cf91d57b93b28670dd/MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0778de17cff1acaeccc3ff30cd99a3fd5c50fc58ad3d6c0e0c4c58092b859396", size = 25358 }, + { url = "https://files.pythonhosted.org/packages/fd/78/26e209abc8f0a379f031f0acc151231974e5b153d7eda5759d17d8f329f2/MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:800100d45176652ded796134277ecb13640c1a537cad3b8b53da45aa96330453", size = 23797 }, + { url = "https://files.pythonhosted.org/packages/09/e1/918496a9390891756efee818880e71c1bbaf587f4dc8ede3f3852357310a/MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d06b24c686a34c86c8c1fba923181eae6b10565e4d80bdd7bc1c8e2f11247aa4", size = 23743 }, + { url = "https://files.pythonhosted.org/packages/cd/c6/26f576cd58d6c2decd9045e4e3f3c5dbc01ea6cb710916e7bbb6ebd95b6b/MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:33d1c36b90e570ba7785dacd1faaf091203d9942bc036118fab8110a401eb1a8", size = 25076 }, + { url = "https://files.pythonhosted.org/packages/b5/fa/10b24fb3b0e15fe5389dc88ecc6226ede08297e0ba7130610efbe0cdfb27/MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:beeebf760a9c1f4c07ef6a53465e8cfa776ea6a2021eda0d0417ec41043fe984", size = 24037 }, + { url = "https://files.pythonhosted.org/packages/c8/81/4b3f5537d9f6cc4f5c80d6c4b78af9a5247fd37b5aba95807b2cbc336b9a/MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bbde71a705f8e9e4c3e9e33db69341d040c827c7afa6789b14c6e16776074f5a", size = 24015 }, + { url = "https://files.pythonhosted.org/packages/5f/07/8e8dcecd53216c5e01a51e84c32a2bce166690ed19c184774b38cd41921d/MarkupSafe-3.0.1-cp313-cp313t-win32.whl", hash = "sha256:82b5dba6eb1bcc29cc305a18a3c5365d2af06ee71b123216416f7e20d2a84e5b", size = 15213 }, + { url = "https://files.pythonhosted.org/packages/0d/87/4c364e0f109eea2402079abecbe33fef4f347b551a11423d1f4e187ea497/MarkupSafe-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:730d86af59e0e43ce277bb83970530dd223bf7f2a838e086b50affa6ec5f9295", size = 15741 }, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350 }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, +] + +[[package]] +name = "mergedeep" +version = "1.3.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354 }, +] + +[[package]] +name = "mkdocs" +version = "1.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "ghp-import" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "markupsafe" }, + { name = "mergedeep" }, + { name = "mkdocs-get-deps" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "pyyaml" }, + { name = "pyyaml-env-tag" }, + { name = "watchdog" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/c6/bbd4f061bd16b378247f12953ffcb04786a618ce5e904b8c5a01a0309061/mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2", size = 3889159 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e", size = 3864451 }, +] + +[[package]] +name = "mkdocs-autorefs" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown" }, + { name = "markupsafe" }, + { name = "mkdocs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/ae/0f1154c614d6a8b8a36fff084e5b82af3a15f7d2060cf0dcdb1c53297a71/mkdocs_autorefs-1.2.0.tar.gz", hash = "sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f", size = 40262 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/26/4d39d52ea2219604053a4d05b98e90d6a335511cc01806436ec4886b1028/mkdocs_autorefs-1.2.0-py3-none-any.whl", hash = "sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f", size = 16522 }, +] + +[[package]] +name = "mkdocs-get-deps" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mergedeep" }, + { name = "platformdirs" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/f5/ed29cd50067784976f25ed0ed6fcd3c2ce9eb90650aa3b2796ddf7b6870b/mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c", size = 10239 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521 }, +] + +[[package]] +name = "mkdocs-git-authors-plugin" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mkdocs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/03/99e18d62964d268eb9a866f42c9d53b43cde903a7fb436da85e396945a02/mkdocs_git_authors_plugin-0.9.0.tar.gz", hash = "sha256:6161f63b87064481a48d9ad01c23e43c3e758930c3a9cc167fe482909ceb9eac", size = 20268 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/ad/a6e0ce34a1d9abe35844cdc3a64028d3df7bfe24b143021f7fcaa26adfdd/mkdocs_git_authors_plugin-0.9.0-py3-none-any.whl", hash = "sha256:380730a05eeb947a7e84be05fdb1c5ae2a7bc70fd9f6eda941f187c87ae37052", size = 19204 }, +] + +[[package]] +name = "mkdocs-git-revision-date-localized-plugin" +version = "1.2.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "gitpython" }, + { name = "mkdocs" }, + { name = "pytz" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/79/56c755035c893af33c3ba29c5100835d10cd98b4b6943f8d1c22a7d56936/mkdocs_git_revision_date_localized_plugin-1.2.9.tar.gz", hash = "sha256:df9a50873fba3a42ce9123885f8c53d589e90ef6c2443fe3280ef1e8d33c8f65", size = 384360 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/05/0edbbd3a0be3033c44d5cd9f1ac7646da2e7e3911513cc56a25aac9266a4/mkdocs_git_revision_date_localized_plugin-1.2.9-py3-none-any.whl", hash = "sha256:dea5c8067c23df30275702a1708885500fadf0abfb595b60e698bffc79c7a423", size = 22475 }, +] + +[[package]] +name = "mkdocs-material" +version = "9.5.40" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "colorama" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "mkdocs" }, + { name = "mkdocs-material-extensions" }, + { name = "paginate" }, + { name = "pygments" }, + { name = "pymdown-extensions" }, + { name = "regex" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b8/2b/6f9e0b9573a4acfa15834a30eca48ad578fe6ab46afa072df5ff05103a86/mkdocs_material-9.5.40.tar.gz", hash = "sha256:b69d70e667ec51fc41f65e006a3184dd00d95b2439d982cb1586e4c018943156", size = 3963129 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/ad/f8039114a23cfb02213f133a1dc8865522128a0b2cb251a7e717de8aa979/mkdocs_material-9.5.40-py3-none-any.whl", hash = "sha256:8e7a16ada34e79a7b6459ff2602584222f522c738b6a023d1bea853d5049da6f", size = 8670419 }, +] + +[package.optional-dependencies] +imaging = [ + { name = "cairosvg" }, + { name = "pillow" }, +] + +[[package]] +name = "mkdocs-material-extensions" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728 }, +] + +[[package]] +name = "mkdocs-redirects" +version = "1.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mkdocs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/6a/50edd7ad78042b25c379aac7e8fa9cc34c6f55e3d2c03eb28814a9446617/mkdocs-redirects-1.2.1.tar.gz", hash = "sha256:9420066d70e2a6bb357adf86e67023dcdca1857f97f07c7fe450f8f1fb42f861", size = 6653 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/9d/93a881fc5a23c50a4dd4a41dfd3d2a8403aa1dac52370ef43b7b336577a0/mkdocs_redirects-1.2.1-py3-none-any.whl", hash = "sha256:497089f9e0219e7389304cffefccdfa1cac5ff9509f2cb706f4c9b221726dffb", size = 6024 }, +] + +[[package]] +name = "mkdocstrings" +version = "0.26.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "markupsafe" }, + { name = "mkdocs" }, + { name = "mkdocs-autorefs" }, + { name = "platformdirs" }, + { name = "pymdown-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e6/bf/170ff04de72227f715d67da32950c7b8434449f3805b2ec3dd1085db4d7c/mkdocstrings-0.26.1.tar.gz", hash = "sha256:bb8b8854d6713d5348ad05b069a09f3b79edbc6a0f33a34c6821141adb03fe33", size = 92677 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/cc/8ba127aaee5d1e9046b0d33fa5b3d17da95a9d705d44902792e0569257fd/mkdocstrings-0.26.1-py3-none-any.whl", hash = "sha256:29738bfb72b4608e8e55cc50fb8a54f325dc7ebd2014e4e3881a49892d5983cf", size = 29643 }, +] + +[package.optional-dependencies] +python = [ + { name = "mkdocstrings-python" }, +] + +[[package]] +name = "mkdocstrings-python" +version = "1.11.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "griffe" }, + { name = "mkdocs-autorefs" }, + { name = "mkdocstrings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/ba/534c934cd0a809f51c91332d6ed278782ee4126b8ba8db02c2003f162b47/mkdocstrings_python-1.11.1.tar.gz", hash = "sha256:8824b115c5359304ab0b5378a91f6202324a849e1da907a3485b59208b797322", size = 166890 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/f2/2a2c48fda645ac6bbe73bcc974587a579092b6868e6ff8bc6d177f4db38a/mkdocstrings_python-1.11.1-py3-none-any.whl", hash = "sha256:a21a1c05acef129a618517bb5aae3e33114f569b11588b1e7af3e9d4061a71af", size = 109297 }, +] + +[[package]] +name = "multidict" +version = "6.0.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/79/722ca999a3a09a63b35aac12ec27dfa8e5bb3a38b0f857f7a1a209a88836/multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da", size = 59867 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/da/b10ea65b850b54f44a6479177c6987f456bc2d38f8dc73009b78afcf0ede/multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba", size = 50815 }, + { url = "https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e", size = 30269 }, + { url = "https://files.pythonhosted.org/packages/02/c1/b15ecceb6ffa5081ed2ed450aea58d65b0e0358001f2b426705f9f41f4c2/multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd", size = 30500 }, + { url = "https://files.pythonhosted.org/packages/3f/e1/7fdd0f39565df3af87d6c2903fb66a7d529fbd0a8a066045d7a5b6ad1145/multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3", size = 130751 }, + { url = "https://files.pythonhosted.org/packages/76/bc/9f593f9e38c6c09bbf0344b56ad67dd53c69167937c2edadee9719a5e17d/multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf", size = 138185 }, + { url = "https://files.pythonhosted.org/packages/28/32/d7799a208701d537b92705f46c777ded812a6dc139c18d8ed599908f6b1c/multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29", size = 133585 }, + { url = "https://files.pythonhosted.org/packages/52/ec/be54a3ad110f386d5bd7a9a42a4ff36b3cd723ebe597f41073a73ffa16b8/multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed", size = 128684 }, + { url = "https://files.pythonhosted.org/packages/36/e1/a680eabeb71e25d4733276d917658dfa1cd3a99b1223625dbc247d266c98/multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733", size = 120994 }, + { url = "https://files.pythonhosted.org/packages/ef/08/08f4f44a8a43ea4cee13aa9cdbbf4a639af8db49310a0637ca389c4cf817/multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f", size = 159689 }, + { url = "https://files.pythonhosted.org/packages/aa/a9/46cdb4cb40bbd4b732169413f56b04a6553460b22bd914f9729c9ba63761/multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4", size = 150611 }, + { url = "https://files.pythonhosted.org/packages/e9/32/35668bb3e6ab2f12f4e4f7f4000f72f714882a94f904d4c3633fbd036753/multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1", size = 164444 }, + { url = "https://files.pythonhosted.org/packages/fa/10/f1388a91552af732d8ec48dab928abc209e732767e9e8f92d24c3544353c/multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc", size = 160158 }, + { url = "https://files.pythonhosted.org/packages/14/c3/f602601f1819983e018156e728e57b3f19726cb424b543667faab82f6939/multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e", size = 156072 }, + { url = "https://files.pythonhosted.org/packages/82/a6/0290af8487326108c0d03d14f8a0b8b1001d71e4494df5f96ab0c88c0b88/multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c", size = 25731 }, + { url = "https://files.pythonhosted.org/packages/88/aa/ea217cb18325aa05cb3e3111c19715f1e97c50a4a900cbc20e54648de5f5/multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea", size = 28176 }, + { url = "https://files.pythonhosted.org/packages/90/9c/7fda9c0defa09538c97b1f195394be82a1f53238536f70b32eb5399dfd4e/multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e", size = 49575 }, + { url = "https://files.pythonhosted.org/packages/be/21/d6ca80dd1b9b2c5605ff7475699a8ff5dc6ea958cd71fb2ff234afc13d79/multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b", size = 29638 }, + { url = "https://files.pythonhosted.org/packages/9c/18/9565f32c19d186168731e859692dfbc0e98f66a1dcf9e14d69c02a78b75a/multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5", size = 29874 }, + { url = "https://files.pythonhosted.org/packages/4e/4e/3815190e73e6ef101b5681c174c541bf972a1b064e926e56eea78d06e858/multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450", size = 129914 }, + { url = "https://files.pythonhosted.org/packages/0c/08/bb47f886457e2259aefc10044e45c8a1b62f0c27228557e17775869d0341/multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496", size = 134589 }, + { url = "https://files.pythonhosted.org/packages/d5/2f/952f79b5f0795cf4e34852fc5cf4dfda6166f63c06c798361215b69c131d/multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a", size = 133259 }, + { url = "https://files.pythonhosted.org/packages/24/1f/af976383b0b772dd351210af5b60ff9927e3abb2f4a103e93da19a957da0/multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226", size = 130779 }, + { url = "https://files.pythonhosted.org/packages/fc/b1/b0a7744be00b0f5045c7ed4e4a6b8ee6bde4672b2c620474712299df5979/multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271", size = 120125 }, + { url = "https://files.pythonhosted.org/packages/d0/bf/2a1d667acf11231cdf0b97a6cd9f30e7a5cf847037b5cf6da44884284bd0/multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb", size = 167095 }, + { url = "https://files.pythonhosted.org/packages/5e/e8/ad6ee74b1a2050d3bc78f566dabcc14c8bf89cbe87eecec866c011479815/multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef", size = 155823 }, + { url = "https://files.pythonhosted.org/packages/45/7c/06926bb91752c52abca3edbfefac1ea90d9d1bc00c84d0658c137589b920/multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24", size = 170233 }, + { url = "https://files.pythonhosted.org/packages/3c/29/3dd36cf6b9c5abba8b97bba84eb499a168ba59c3faec8829327b3887d123/multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6", size = 169035 }, + { url = "https://files.pythonhosted.org/packages/60/47/9a0f43470c70bbf6e148311f78ef5a3d4996b0226b6d295bdd50fdcfe387/multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda", size = 166229 }, + { url = "https://files.pythonhosted.org/packages/1d/23/c1b7ae7a0b8a3e08225284ef3ecbcf014b292a3ee821bc4ed2185fd4ce7d/multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5", size = 25840 }, + { url = "https://files.pythonhosted.org/packages/4a/68/66fceb758ad7a88993940dbdf3ac59911ba9dc46d7798bf6c8652f89f853/multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556", size = 27905 }, + { url = "https://files.pythonhosted.org/packages/fa/a2/17e1e23c6be0a916219c5292f509360c345b5fa6beeb50d743203c27532c/multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7", size = 9729 }, +] + +[[package]] +name = "numpy" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/d1/8a730ea07f4a37d94f9172f4ce1d81064b7a64766b460378be278952de75/numpy-2.1.2.tar.gz", hash = "sha256:13532a088217fa624c99b843eeb54640de23b3414b14aa66d023805eb731066c", size = 18878063 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/9c/9a6ec3ae89cd0648d419781284308f2956d2a61d932b5ac9682c956a171b/numpy-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b42a1a511c81cc78cbc4539675713bbcf9d9c3913386243ceff0e9429ca892fe", size = 21154845 }, + { url = "https://files.pythonhosted.org/packages/02/69/9f05c4ecc75fabf297b17743996371b4c3dfc4d92e15c5c38d8bb3db8d74/numpy-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:faa88bc527d0f097abdc2c663cddf37c05a1c2f113716601555249805cf573f1", size = 13789409 }, + { url = "https://files.pythonhosted.org/packages/34/4e/f95c99217bf77bbfaaf660d693c10bd0dc03b6032d19316d316088c9e479/numpy-2.1.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:c82af4b2ddd2ee72d1fc0c6695048d457e00b3582ccde72d8a1c991b808bb20f", size = 5352097 }, + { url = "https://files.pythonhosted.org/packages/06/13/f5d87a497c16658e9af8920449b0b5692b469586b8231340c672962071c5/numpy-2.1.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:13602b3174432a35b16c4cfb5de9a12d229727c3dd47a6ce35111f2ebdf66ff4", size = 6891195 }, + { url = "https://files.pythonhosted.org/packages/6c/89/691ac07429ac061b344d5e37fa8e94be51a6017734aea15f2d9d7c6d119a/numpy-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ebec5fd716c5a5b3d8dfcc439be82a8407b7b24b230d0ad28a81b61c2f4659a", size = 13895153 }, + { url = "https://files.pythonhosted.org/packages/23/69/538317f0d925095537745f12aced33be1570bbdc4acde49b33748669af96/numpy-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2b49c3c0804e8ecb05d59af8386ec2f74877f7ca8fd9c1e00be2672e4d399b1", size = 16338306 }, + { url = "https://files.pythonhosted.org/packages/af/03/863fe7062c2106d3c151f7df9353f2ae2237c1dd6900f127a3eb1f24cb1b/numpy-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2cbba4b30bf31ddbe97f1c7205ef976909a93a66bb1583e983adbd155ba72ac2", size = 16710893 }, + { url = "https://files.pythonhosted.org/packages/70/77/0ad9efe25482009873f9660d29a40a8c41a6f0e8b541195e3c95c70684c5/numpy-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8e00ea6fc82e8a804433d3e9cedaa1051a1422cb6e443011590c14d2dea59146", size = 14398048 }, + { url = "https://files.pythonhosted.org/packages/3e/0f/e785fe75544db9f2b0bb1c181e13ceff349ce49753d807fd9672916aa06d/numpy-2.1.2-cp311-cp311-win32.whl", hash = "sha256:5006b13a06e0b38d561fab5ccc37581f23c9511879be7693bd33c7cd15ca227c", size = 6533458 }, + { url = "https://files.pythonhosted.org/packages/d4/96/450054662295125af861d48d2c4bc081dadcf1974a879b2104613157aa62/numpy-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:f1eb068ead09f4994dec71c24b2844f1e4e4e013b9629f812f292f04bd1510d9", size = 12870896 }, + { url = "https://files.pythonhosted.org/packages/a0/7d/554a6838f37f3ada5a55f25173c619d556ae98092a6e01afb6e710501d70/numpy-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7bf0a4f9f15b32b5ba53147369e94296f5fffb783db5aacc1be15b4bf72f43b", size = 20848077 }, + { url = "https://files.pythonhosted.org/packages/b0/29/cb48a402ea879e645b16218718f3f7d9588a77d674a9dcf22e4c43487636/numpy-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b1d0fcae4f0949f215d4632be684a539859b295e2d0cb14f78ec231915d644db", size = 13493242 }, + { url = "https://files.pythonhosted.org/packages/56/44/f899b0581766c230da42f751b7b8896d096640b19b312164c267e48d36cb/numpy-2.1.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:f751ed0a2f250541e19dfca9f1eafa31a392c71c832b6bb9e113b10d050cb0f1", size = 5089219 }, + { url = "https://files.pythonhosted.org/packages/79/8f/b987070d45161a7a4504afc67ed38544ed2c0ed5576263599a0402204a9c/numpy-2.1.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:bd33f82e95ba7ad632bc57837ee99dba3d7e006536200c4e9124089e1bf42426", size = 6620167 }, + { url = "https://files.pythonhosted.org/packages/c4/a7/af3329fda3c3ec31d9b650e42bbcd3422fc62a765cbb1405fde4177a0996/numpy-2.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b8cde4f11f0a975d1fd59373b32e2f5a562ade7cde4f85b7137f3de8fbb29a0", size = 13604905 }, + { url = "https://files.pythonhosted.org/packages/9b/b4/e3c7e6fab0f77fff6194afa173d1f2342073d91b1d3b4b30b17c3fb4407a/numpy-2.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d95f286b8244b3649b477ac066c6906fbb2905f8ac19b170e2175d3d799f4df", size = 16041825 }, + { url = "https://files.pythonhosted.org/packages/e9/50/6828e66a78aa03147c111f84d55f33ce2dde547cb578d6744a3b06a0124b/numpy-2.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ab4754d432e3ac42d33a269c8567413bdb541689b02d93788af4131018cbf366", size = 16409541 }, + { url = "https://files.pythonhosted.org/packages/bf/72/66af7916d9c3c6dbfbc8acdd4930c65461e1953374a2bc43d00f948f004a/numpy-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e585c8ae871fd38ac50598f4763d73ec5497b0de9a0ab4ef5b69f01c6a046142", size = 14081134 }, + { url = "https://files.pythonhosted.org/packages/dc/5a/59a67d84f33fe00ae74f0b5b69dd4f93a586a4aba7f7e19b54b2133db038/numpy-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9c6c754df29ce6a89ed23afb25550d1c2d5fdb9901d9c67a16e0b16eaf7e2550", size = 6237784 }, + { url = "https://files.pythonhosted.org/packages/4c/79/73735a6a5dad6059c085f240a4e74c9270feccd2bc66e4d31b5ca01d329c/numpy-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:456e3b11cb79ac9946c822a56346ec80275eaf2950314b249b512896c0d2505e", size = 12568254 }, + { url = "https://files.pythonhosted.org/packages/16/72/716fa1dbe92395a9a623d5049203ff8ddb0cfce65b9df9117c3696ccc011/numpy-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a84498e0d0a1174f2b3ed769b67b656aa5460c92c9554039e11f20a05650f00d", size = 20834690 }, + { url = "https://files.pythonhosted.org/packages/1e/fb/3e85a39511586053b5c6a59a643879e376fae22230ebfef9cfabb0e032e2/numpy-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4d6ec0d4222e8ffdab1744da2560f07856421b367928026fb540e1945f2eeeaf", size = 13507474 }, + { url = "https://files.pythonhosted.org/packages/35/eb/5677556d9ba13436dab51e129f98d4829d95cd1b6bd0e199c14485a4bdb9/numpy-2.1.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:259ec80d54999cc34cd1eb8ded513cb053c3bf4829152a2e00de2371bd406f5e", size = 5074742 }, + { url = "https://files.pythonhosted.org/packages/3e/c5/6c5ef5ba41b65a7e51bed50dbf3e1483eb578055633dd013e811a28e96a1/numpy-2.1.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:675c741d4739af2dc20cd6c6a5c4b7355c728167845e3c6b0e824e4e5d36a6c3", size = 6606787 }, + { url = "https://files.pythonhosted.org/packages/08/ac/f2f29dd4fd325b379c7dc932a0ebab22f0e031dbe80b2f6019b291a3a544/numpy-2.1.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b2d4e667895cc55e3ff2b56077e4c8a5604361fc21a042845ea3ad67465aa8", size = 13601333 }, + { url = "https://files.pythonhosted.org/packages/44/26/63f5f4e5089654dfb858f4892215ed968cd1a68e6f4a83f9961f84f855cb/numpy-2.1.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43cca367bf94a14aca50b89e9bc2061683116cfe864e56740e083392f533ce7a", size = 16038090 }, + { url = "https://files.pythonhosted.org/packages/1d/21/015e0594de9c3a8d5edd24943d2bd23f102ec71aec026083f822f86497e2/numpy-2.1.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:76322dcdb16fccf2ac56f99048af32259dcc488d9b7e25b51e5eca5147a3fb98", size = 16410865 }, + { url = "https://files.pythonhosted.org/packages/df/01/c1bcf9e6025d79077fbf3f3ee503b50aa7bfabfcd8f4b54f5829f4c00f3f/numpy-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:32e16a03138cabe0cb28e1007ee82264296ac0983714094380b408097a418cfe", size = 14078077 }, + { url = "https://files.pythonhosted.org/packages/ba/06/db9d127d63bd11591770ba9f3d960f8041e0f895184b9351d4b1b5b56983/numpy-2.1.2-cp313-cp313-win32.whl", hash = "sha256:242b39d00e4944431a3cd2db2f5377e15b5785920421993770cddb89992c3f3a", size = 6234904 }, + { url = "https://files.pythonhosted.org/packages/a9/96/9f61f8f95b6e0ea0aa08633b704c75d1882bdcb331bdf8bfd63263b25b00/numpy-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:f2ded8d9b6f68cc26f8425eda5d3877b47343e68ca23d0d0846f4d312ecaa445", size = 12561910 }, + { url = "https://files.pythonhosted.org/packages/36/b8/033f627821784a48e8f75c218033471eebbaacdd933f8979c79637a1b44b/numpy-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ffef621c14ebb0188a8633348504a35c13680d6da93ab5cb86f4e54b7e922b5", size = 20857719 }, + { url = "https://files.pythonhosted.org/packages/96/46/af5726fde5b74ed83f2f17a73386d399319b7ed4d51279fb23b721d0816d/numpy-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ad369ed238b1959dfbade9018a740fb9392c5ac4f9b5173f420bd4f37ba1f7a0", size = 13518826 }, + { url = "https://files.pythonhosted.org/packages/db/6e/8ce677edf36da1c4dae80afe5529f47690697eb55b4864673af260ccea7b/numpy-2.1.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d82075752f40c0ddf57e6e02673a17f6cb0f8eb3f587f63ca1eaab5594da5b17", size = 5115036 }, + { url = "https://files.pythonhosted.org/packages/6a/ba/3cce44fb1b8438042c11847048812a776f75ee0e7070179c22e4cfbf420c/numpy-2.1.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:1600068c262af1ca9580a527d43dc9d959b0b1d8e56f8a05d830eea39b7c8af6", size = 6628641 }, + { url = "https://files.pythonhosted.org/packages/59/c8/e722998720ccbd35ffbcf1d1b8ed0aa2304af88d3f1c38e06ebf983599b3/numpy-2.1.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a26ae94658d3ba3781d5e103ac07a876b3e9b29db53f68ed7df432fd033358a8", size = 13574803 }, + { url = "https://files.pythonhosted.org/packages/7c/8e/fc1fdd83a55476765329ac2913321c4aed5b082a7915095628c4ca30ea72/numpy-2.1.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13311c2db4c5f7609b462bc0f43d3c465424d25c626d95040f073e30f7570e35", size = 16021174 }, + { url = "https://files.pythonhosted.org/packages/2a/b6/a790742aa88067adb4bd6c89a946778c1417d4deaeafce3ca928f26d4c52/numpy-2.1.2-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:2abbf905a0b568706391ec6fa15161fad0fb5d8b68d73c461b3c1bab6064dd62", size = 16400117 }, + { url = "https://files.pythonhosted.org/packages/48/6f/129e3c17e3befe7fefdeaa6890f4c4df3f3cf0831aa053802c3862da67aa/numpy-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ef444c57d664d35cac4e18c298c47d7b504c66b17c2ea91312e979fcfbdfb08a", size = 14066202 }, +] + +[[package]] +name = "orjson" +version = "3.10.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9e/03/821c8197d0515e46ea19439f5c5d5fd9a9889f76800613cfac947b5d7845/orjson-3.10.7.tar.gz", hash = "sha256:75ef0640403f945f3a1f9f6400686560dbfb0fb5b16589ad62cd477043c4eee3", size = 5056450 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/c9/dd286c97c2f478d43839bd859ca4d9820e2177d4e07a64c516dc3e018062/orjson-3.10.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7db8539039698ddfb9a524b4dd19508256107568cdad24f3682d5773e60504a2", size = 251312 }, + { url = "https://files.pythonhosted.org/packages/b9/72/d90bd11e83a0e9623b3803b079478a93de8ec4316c98fa66110d594de5fa/orjson-3.10.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:480f455222cb7a1dea35c57a67578848537d2602b46c464472c995297117fa09", size = 148125 }, + { url = "https://files.pythonhosted.org/packages/9d/b6/ed61e87f327a4cbb2075ed0716e32ba68cb029aa654a68c3eb27803050d8/orjson-3.10.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a9c9b168b3a19e37fe2778c0003359f07822c90fdff8f98d9d2a91b3144d8e0", size = 147278 }, + { url = "https://files.pythonhosted.org/packages/66/9f/e6a11b5d1ad11e9dc869d938707ef93ff5ed20b53d6cda8b5e2ac532a9d2/orjson-3.10.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8de062de550f63185e4c1c54151bdddfc5625e37daf0aa1e75d2a1293e3b7d9a", size = 152954 }, + { url = "https://files.pythonhosted.org/packages/92/ee/702d5e8ccd42dc2b9d1043f22daa1ba75165616aa021dc19fb0c5a726ce8/orjson-3.10.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6b0dd04483499d1de9c8f6203f8975caf17a6000b9c0c54630cef02e44ee624e", size = 163953 }, + { url = "https://files.pythonhosted.org/packages/d3/cb/55205f3f1ee6ba80c0a9a18ca07423003ca8de99192b18be30f1f31b4cdd/orjson-3.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b58d3795dafa334fc8fd46f7c5dc013e6ad06fd5b9a4cc98cb1456e7d3558bd6", size = 141895 }, + { url = "https://files.pythonhosted.org/packages/bb/ab/1185e472f15c00d37d09c395e478803ed0eae7a3a3d055a5f3885e1ea136/orjson-3.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33cfb96c24034a878d83d1a9415799a73dc77480e6c40417e5dda0710d559ee6", size = 170169 }, + { url = "https://files.pythonhosted.org/packages/53/b9/10abe9089bdb08cd4218cc45eb7abfd787c82cf301cecbfe7f141542d7f4/orjson-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e724cebe1fadc2b23c6f7415bad5ee6239e00a69f30ee423f319c6af70e2a5c0", size = 167808 }, + { url = "https://files.pythonhosted.org/packages/8a/ad/26b40ccef119dcb0f4a39745ffd7d2d319152c1a52859b1ebbd114eca19c/orjson-3.10.7-cp311-none-win32.whl", hash = "sha256:82763b46053727a7168d29c772ed5c870fdae2f61aa8a25994c7984a19b1021f", size = 143010 }, + { url = "https://files.pythonhosted.org/packages/e7/63/5f4101e4895b78ada568f4cf8f870dd594139ca2e75e654e373da78b03b0/orjson-3.10.7-cp311-none-win_amd64.whl", hash = "sha256:eb8d384a24778abf29afb8e41d68fdd9a156cf6e5390c04cc07bbc24b89e98b5", size = 137307 }, + { url = "https://files.pythonhosted.org/packages/14/7c/b4ecc2069210489696a36e42862ccccef7e49e1454a3422030ef52881b01/orjson-3.10.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44a96f2d4c3af51bfac6bc4ef7b182aa33f2f054fd7f34cc0ee9a320d051d41f", size = 251409 }, + { url = "https://files.pythonhosted.org/packages/60/84/e495edb919ef0c98d054a9b6d05f2700fdeba3886edd58f1c4dfb25d514a/orjson-3.10.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ac14cd57df0572453543f8f2575e2d01ae9e790c21f57627803f5e79b0d3c3", size = 147913 }, + { url = "https://files.pythonhosted.org/packages/c5/27/e40bc7d79c4afb7e9264f22320c285d06d2c9574c9c682ba0f1be3012833/orjson-3.10.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bdbb61dcc365dd9be94e8f7df91975edc9364d6a78c8f7adb69c1cdff318ec93", size = 147390 }, + { url = "https://files.pythonhosted.org/packages/30/be/fd646fb1a461de4958a6eacf4ecf064b8d5479c023e0e71cc89b28fa91ac/orjson-3.10.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b48b3db6bb6e0a08fa8c83b47bc169623f801e5cc4f24442ab2b6617da3b5313", size = 152973 }, + { url = "https://files.pythonhosted.org/packages/b1/00/414f8d4bc5ec3447e27b5c26b4e996e4ef08594d599e79b3648f64da060c/orjson-3.10.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23820a1563a1d386414fef15c249040042b8e5d07b40ab3fe3efbfbbcbcb8864", size = 164039 }, + { url = "https://files.pythonhosted.org/packages/a0/6b/34e6904ac99df811a06e42d8461d47b6e0c9b86e2fe7ee84934df6e35f0d/orjson-3.10.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0c6a008e91d10a2564edbb6ee5069a9e66df3fbe11c9a005cb411f441fd2c09", size = 142035 }, + { url = "https://files.pythonhosted.org/packages/17/7e/254189d9b6df89660f65aec878d5eeaa5b1ae371bd2c458f85940445d36f/orjson-3.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d352ee8ac1926d6193f602cbe36b1643bbd1bbcb25e3c1a657a4390f3000c9a5", size = 169941 }, + { url = "https://files.pythonhosted.org/packages/02/1a/d11805670c29d3a1b29fc4bd048dc90b094784779690592efe8c9f71249a/orjson-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d2d9f990623f15c0ae7ac608103c33dfe1486d2ed974ac3f40b693bad1a22a7b", size = 167994 }, + { url = "https://files.pythonhosted.org/packages/20/5f/03d89b007f9d6733dc11bc35d64812101c85d6c4e9c53af9fa7e7689cb11/orjson-3.10.7-cp312-none-win32.whl", hash = "sha256:7c4c17f8157bd520cdb7195f75ddbd31671997cbe10aee559c2d613592e7d7eb", size = 143130 }, + { url = "https://files.pythonhosted.org/packages/c6/9d/9b9fb6c60b8a0e04031ba85414915e19ecea484ebb625402d968ea45b8d5/orjson-3.10.7-cp312-none-win_amd64.whl", hash = "sha256:1d9c0e733e02ada3ed6098a10a8ee0052dd55774de3d9110d29868d24b17faa1", size = 137326 }, + { url = "https://files.pythonhosted.org/packages/15/05/121af8a87513c56745d01ad7cf215c30d08356da9ad882ebe2ba890824cd/orjson-3.10.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:77d325ed866876c0fa6492598ec01fe30e803272a6e8b10e992288b009cbe149", size = 251331 }, + { url = "https://files.pythonhosted.org/packages/73/7f/8d6ccd64a6f8bdbfe6c9be7c58aeb8094aa52a01fbbb2cda42ff7e312bd7/orjson-3.10.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ea2c232deedcb605e853ae1db2cc94f7390ac776743b699b50b071b02bea6fe", size = 142012 }, + { url = "https://files.pythonhosted.org/packages/04/65/f2a03fd1d4f0308f01d372e004c049f7eb9bc5676763a15f20f383fa9c01/orjson-3.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3dcfbede6737fdbef3ce9c37af3fb6142e8e1ebc10336daa05872bfb1d87839c", size = 169920 }, + { url = "https://files.pythonhosted.org/packages/e2/1c/3ef8d83d7c6a619ad3d69a4d5318591b4ce5862e6eda7c26bbe8208652ca/orjson-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11748c135f281203f4ee695b7f80bb1358a82a63905f9f0b794769483ea854ad", size = 167916 }, + { url = "https://files.pythonhosted.org/packages/f2/0d/820a640e5a7dfbe525e789c70871ebb82aff73b0c7bf80082653f86b9431/orjson-3.10.7-cp313-none-win32.whl", hash = "sha256:a7e19150d215c7a13f39eb787d84db274298d3f83d85463e61d277bbd7f401d2", size = 143089 }, + { url = "https://files.pythonhosted.org/packages/1a/72/a424db9116c7cad2950a8f9e4aeb655a7b57de988eb015acd0fcd1b4609b/orjson-3.10.7-cp313-none-win_amd64.whl", hash = "sha256:eef44224729e9525d5261cc8d28d6b11cafc90e6bd0be2157bde69a52ec83024", size = 137081 }, +] + +[[package]] +name = "packaging" +version = "24.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/51/65/50db4dda066951078f0a96cf12f4b9ada6e4b811516bf0262c0f4f7064d4/packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", size = 148788 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124", size = 53985 }, +] + +[[package]] +name = "paginate" +version = "0.5.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746 }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, +] + +[[package]] +name = "peewee" +version = "3.17.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/be/e9c886b4601a19f4c34a1b75c5fe8b98a2115dd964251a76b24c977c369d/peewee-3.17.6.tar.gz", hash = "sha256:cea5592c6f4da1592b7cff8eaf655be6648a1f5857469e30037bf920c03fb8fb", size = 2954075 } + +[[package]] +name = "phx-class-registry" +version = "5.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/b0/dfe7eee3715a522e0507c5d81daab52d4348ee2672fa77c721617dbb6319/phx_class_registry-5.0.0.tar.gz", hash = "sha256:a57ab8c2eca03e0daf06e0dd840ea26b72e2e51b7b7509015b3df7c0d537ee73", size = 32284 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/e5/9384dd7f575ade7a14ae4371d6b4eafd997f18577d3e93ccd0e055389b0b/phx_class_registry-5.0.0-py3-none-any.whl", hash = "sha256:6e0644f779c7d793a96090d938fe4c396f3274dd57563dc1c57ea245b5c07f89", size = 14850 }, +] + +[[package]] +name = "pillow" +version = "10.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/74/ad3d526f3bf7b6d3f408b73fde271ec69dfac8b81341a318ce825f2b3812/pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", size = 46555059 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c", size = 3509265 }, + { url = "https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be", size = 3375655 }, + { url = "https://files.pythonhosted.org/packages/73/d5/c4011a76f4207a3c151134cd22a1415741e42fa5ddecec7c0182887deb3d/pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3", size = 4340304 }, + { url = "https://files.pythonhosted.org/packages/ac/10/c67e20445a707f7a610699bba4fe050583b688d8cd2d202572b257f46600/pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6", size = 4452804 }, + { url = "https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe", size = 4365126 }, + { url = "https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319", size = 4533541 }, + { url = "https://files.pythonhosted.org/packages/f4/7c/01b8dbdca5bc6785573f4cee96e2358b0918b7b2c7b60d8b6f3abf87a070/pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d", size = 4471616 }, + { url = "https://files.pythonhosted.org/packages/c8/57/2899b82394a35a0fbfd352e290945440e3b3785655a03365c0ca8279f351/pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696", size = 4600802 }, + { url = "https://files.pythonhosted.org/packages/4d/d7/a44f193d4c26e58ee5d2d9db3d4854b2cfb5b5e08d360a5e03fe987c0086/pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496", size = 2235213 }, + { url = "https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91", size = 2554498 }, + { url = "https://files.pythonhosted.org/packages/d4/c8/310ac16ac2b97e902d9eb438688de0d961660a87703ad1561fd3dfbd2aa0/pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22", size = 2243219 }, + { url = "https://files.pythonhosted.org/packages/05/cb/0353013dc30c02a8be34eb91d25e4e4cf594b59e5a55ea1128fde1e5f8ea/pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94", size = 3509350 }, + { url = "https://files.pythonhosted.org/packages/e7/cf/5c558a0f247e0bf9cec92bff9b46ae6474dd736f6d906315e60e4075f737/pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597", size = 3374980 }, + { url = "https://files.pythonhosted.org/packages/84/48/6e394b86369a4eb68b8a1382c78dc092245af517385c086c5094e3b34428/pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80", size = 4343799 }, + { url = "https://files.pythonhosted.org/packages/3b/f3/a8c6c11fa84b59b9df0cd5694492da8c039a24cd159f0f6918690105c3be/pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca", size = 4459973 }, + { url = "https://files.pythonhosted.org/packages/7d/1b/c14b4197b80150fb64453585247e6fb2e1d93761fa0fa9cf63b102fde822/pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef", size = 4370054 }, + { url = "https://files.pythonhosted.org/packages/55/77/40daddf677897a923d5d33329acd52a2144d54a9644f2a5422c028c6bf2d/pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a", size = 4539484 }, + { url = "https://files.pythonhosted.org/packages/40/54/90de3e4256b1207300fb2b1d7168dd912a2fb4b2401e439ba23c2b2cabde/pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b", size = 4477375 }, + { url = "https://files.pythonhosted.org/packages/13/24/1bfba52f44193860918ff7c93d03d95e3f8748ca1de3ceaf11157a14cf16/pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9", size = 4608773 }, + { url = "https://files.pythonhosted.org/packages/55/04/5e6de6e6120451ec0c24516c41dbaf80cce1b6451f96561235ef2429da2e/pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42", size = 2235690 }, + { url = "https://files.pythonhosted.org/packages/74/0a/d4ce3c44bca8635bd29a2eab5aa181b654a734a29b263ca8efe013beea98/pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a", size = 2554951 }, + { url = "https://files.pythonhosted.org/packages/b5/ca/184349ee40f2e92439be9b3502ae6cfc43ac4b50bc4fc6b3de7957563894/pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9", size = 2243427 }, + { url = "https://files.pythonhosted.org/packages/c3/00/706cebe7c2c12a6318aabe5d354836f54adff7156fd9e1bd6c89f4ba0e98/pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3", size = 3525685 }, + { url = "https://files.pythonhosted.org/packages/cf/76/f658cbfa49405e5ecbfb9ba42d07074ad9792031267e782d409fd8fe7c69/pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb", size = 3374883 }, + { url = "https://files.pythonhosted.org/packages/46/2b/99c28c4379a85e65378211971c0b430d9c7234b1ec4d59b2668f6299e011/pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70", size = 4339837 }, + { url = "https://files.pythonhosted.org/packages/f1/74/b1ec314f624c0c43711fdf0d8076f82d9d802afd58f1d62c2a86878e8615/pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be", size = 4455562 }, + { url = "https://files.pythonhosted.org/packages/4a/2a/4b04157cb7b9c74372fa867096a1607e6fedad93a44deeff553ccd307868/pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0", size = 4366761 }, + { url = "https://files.pythonhosted.org/packages/ac/7b/8f1d815c1a6a268fe90481232c98dd0e5fa8c75e341a75f060037bd5ceae/pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc", size = 4536767 }, + { url = "https://files.pythonhosted.org/packages/e5/77/05fa64d1f45d12c22c314e7b97398ffb28ef2813a485465017b7978b3ce7/pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a", size = 4477989 }, + { url = "https://files.pythonhosted.org/packages/12/63/b0397cfc2caae05c3fb2f4ed1b4fc4fc878f0243510a7a6034ca59726494/pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309", size = 4610255 }, + { url = "https://files.pythonhosted.org/packages/7b/f9/cfaa5082ca9bc4a6de66ffe1c12c2d90bf09c309a5f52b27759a596900e7/pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", size = 2235603 }, + { url = "https://files.pythonhosted.org/packages/01/6a/30ff0eef6e0c0e71e55ded56a38d4859bf9d3634a94a88743897b5f96936/pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", size = 2554972 }, + { url = "https://files.pythonhosted.org/packages/48/2c/2e0a52890f269435eee38b21c8218e102c621fe8d8df8b9dd06fabf879ba/pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", size = 2243375 }, +] + +[[package]] +name = "platformdirs" +version = "4.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/52/0763d1d976d5c262df53ddda8d8d4719eedf9594d046f117c25a27261a19/platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3", size = 20916 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/13/2aa1f0e1364feb2c9ef45302f387ac0bd81484e9c9a4c5688a322fbdfd08/platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee", size = 18146 }, +] + +[[package]] +name = "psutil" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/c7/8c6872f7372eb6a6b2e4708b88419fb46b857f7a2e1892966b851cc79fc9/psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2", size = 508067 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0", size = 250961 }, + { url = "https://files.pythonhosted.org/packages/35/56/72f86175e81c656a01c4401cd3b1c923f891b31fbcebe98985894176d7c9/psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0", size = 287478 }, + { url = "https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd", size = 290455 }, + { url = "https://files.pythonhosted.org/packages/cd/5f/60038e277ff0a9cc8f0c9ea3d0c5eb6ee1d2470ea3f9389d776432888e47/psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132", size = 292046 }, + { url = "https://files.pythonhosted.org/packages/8b/20/2ff69ad9c35c3df1858ac4e094f20bd2374d33c8643cf41da8fd7cdcb78b/psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d", size = 253560 }, + { url = "https://files.pythonhosted.org/packages/73/44/561092313ae925f3acfaace6f9ddc4f6a9c748704317bad9c8c8f8a36a79/psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3", size = 257399 }, + { url = "https://files.pythonhosted.org/packages/7c/06/63872a64c312a24fb9b4af123ee7007a306617da63ff13bcc1432386ead7/psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0", size = 251988 }, +] + +[[package]] +name = "py-dactyl" +version = "2.0.4" +source = { git = "https://github.com/cswimr/pydactyl#a8ad40c21b3fe2248451fd85a1146b32d29f10df" } +dependencies = [ + { name = "requests" }, +] + +[[package]] +name = "pycparser" +version = "2.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 }, +] + +[[package]] +name = "pydantic" +version = "2.9.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a9/b7/d9e3f12af310e1120c21603644a1cd86f59060e040ec5c3a80b8f05fae30/pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f", size = 769917 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/e4/ba44652d562cbf0bf320e0f3810206149c8a4e99cdbf66da82e97ab53a15/pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12", size = 434928 }, +] + +[[package]] +name = "pydantic-core" +version = "2.23.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e2/aa/6b6a9b9f8537b872f552ddd46dd3da230367754b6f707b8e1e963f515ea3/pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863", size = 402156 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/30/890a583cd3f2be27ecf32b479d5d615710bb926d92da03e3f7838ff3e58b/pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8", size = 1865160 }, + { url = "https://files.pythonhosted.org/packages/1d/9a/b634442e1253bc6889c87afe8bb59447f106ee042140bd57680b3b113ec7/pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d", size = 1776777 }, + { url = "https://files.pythonhosted.org/packages/75/9a/7816295124a6b08c24c96f9ce73085032d8bcbaf7e5a781cd41aa910c891/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e", size = 1799244 }, + { url = "https://files.pythonhosted.org/packages/a9/8f/89c1405176903e567c5f99ec53387449e62f1121894aa9fc2c4fdc51a59b/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607", size = 1805307 }, + { url = "https://files.pythonhosted.org/packages/d5/a5/1a194447d0da1ef492e3470680c66048fef56fc1f1a25cafbea4bc1d1c48/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd", size = 2000663 }, + { url = "https://files.pythonhosted.org/packages/13/a5/1df8541651de4455e7d587cf556201b4f7997191e110bca3b589218745a5/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea", size = 2655941 }, + { url = "https://files.pythonhosted.org/packages/44/31/a3899b5ce02c4316865e390107f145089876dff7e1dfc770a231d836aed8/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e", size = 2052105 }, + { url = "https://files.pythonhosted.org/packages/1b/aa/98e190f8745d5ec831f6d5449344c48c0627ac5fed4e5340a44b74878f8e/pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b", size = 1919967 }, + { url = "https://files.pythonhosted.org/packages/ae/35/b6e00b6abb2acfee3e8f85558c02a0822e9a8b2f2d812ea8b9079b118ba0/pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0", size = 1964291 }, + { url = "https://files.pythonhosted.org/packages/13/46/7bee6d32b69191cd649bbbd2361af79c472d72cb29bb2024f0b6e350ba06/pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64", size = 2109666 }, + { url = "https://files.pythonhosted.org/packages/39/ef/7b34f1b122a81b68ed0a7d0e564da9ccdc9a2924c8d6c6b5b11fa3a56970/pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f", size = 1732940 }, + { url = "https://files.pythonhosted.org/packages/2f/76/37b7e76c645843ff46c1d73e046207311ef298d3f7b2f7d8f6ac60113071/pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3", size = 1916804 }, + { url = "https://files.pythonhosted.org/packages/74/7b/8e315f80666194b354966ec84b7d567da77ad927ed6323db4006cf915f3f/pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231", size = 1856459 }, + { url = "https://files.pythonhosted.org/packages/14/de/866bdce10ed808323d437612aca1ec9971b981e1c52e5e42ad9b8e17a6f6/pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee", size = 1770007 }, + { url = "https://files.pythonhosted.org/packages/dc/69/8edd5c3cd48bb833a3f7ef9b81d7666ccddd3c9a635225214e044b6e8281/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87", size = 1790245 }, + { url = "https://files.pythonhosted.org/packages/80/33/9c24334e3af796ce80d2274940aae38dd4e5676298b4398eff103a79e02d/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8", size = 1801260 }, + { url = "https://files.pythonhosted.org/packages/a5/6f/e9567fd90104b79b101ca9d120219644d3314962caa7948dd8b965e9f83e/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327", size = 1996872 }, + { url = "https://files.pythonhosted.org/packages/2d/ad/b5f0fe9e6cfee915dd144edbd10b6e9c9c9c9d7a56b69256d124b8ac682e/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2", size = 2661617 }, + { url = "https://files.pythonhosted.org/packages/06/c8/7d4b708f8d05a5cbfda3243aad468052c6e99de7d0937c9146c24d9f12e9/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36", size = 2071831 }, + { url = "https://files.pythonhosted.org/packages/89/4d/3079d00c47f22c9a9a8220db088b309ad6e600a73d7a69473e3a8e5e3ea3/pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126", size = 1917453 }, + { url = "https://files.pythonhosted.org/packages/e9/88/9df5b7ce880a4703fcc2d76c8c2d8eb9f861f79d0c56f4b8f5f2607ccec8/pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e", size = 1968793 }, + { url = "https://files.pythonhosted.org/packages/e3/b9/41f7efe80f6ce2ed3ee3c2dcfe10ab7adc1172f778cc9659509a79518c43/pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24", size = 2116872 }, + { url = "https://files.pythonhosted.org/packages/63/08/b59b7a92e03dd25554b0436554bf23e7c29abae7cce4b1c459cd92746811/pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84", size = 1738535 }, + { url = "https://files.pythonhosted.org/packages/88/8d/479293e4d39ab409747926eec4329de5b7129beaedc3786eca070605d07f/pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9", size = 1917992 }, + { url = "https://files.pythonhosted.org/packages/ad/ef/16ee2df472bf0e419b6bc68c05bf0145c49247a1095e85cee1463c6a44a1/pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc", size = 1856143 }, + { url = "https://files.pythonhosted.org/packages/da/fa/bc3dbb83605669a34a93308e297ab22be82dfb9dcf88c6cf4b4f264e0a42/pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd", size = 1770063 }, + { url = "https://files.pythonhosted.org/packages/4e/48/e813f3bbd257a712303ebdf55c8dc46f9589ec74b384c9f652597df3288d/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05", size = 1790013 }, + { url = "https://files.pythonhosted.org/packages/b4/e0/56eda3a37929a1d297fcab1966db8c339023bcca0b64c5a84896db3fcc5c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d", size = 1801077 }, + { url = "https://files.pythonhosted.org/packages/04/be/5e49376769bfbf82486da6c5c1683b891809365c20d7c7e52792ce4c71f3/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510", size = 1996782 }, + { url = "https://files.pythonhosted.org/packages/bc/24/e3ee6c04f1d58cc15f37bcc62f32c7478ff55142b7b3e6d42ea374ea427c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6", size = 2661375 }, + { url = "https://files.pythonhosted.org/packages/c1/f8/11a9006de4e89d016b8de74ebb1db727dc100608bb1e6bbe9d56a3cbbcce/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b", size = 2071635 }, + { url = "https://files.pythonhosted.org/packages/7c/45/bdce5779b59f468bdf262a5bc9eecbae87f271c51aef628d8c073b4b4b4c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327", size = 1916994 }, + { url = "https://files.pythonhosted.org/packages/d8/fa/c648308fe711ee1f88192cad6026ab4f925396d1293e8356de7e55be89b5/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6", size = 1968877 }, + { url = "https://files.pythonhosted.org/packages/16/16/b805c74b35607d24d37103007f899abc4880923b04929547ae68d478b7f4/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f", size = 2116814 }, + { url = "https://files.pythonhosted.org/packages/d1/58/5305e723d9fcdf1c5a655e6a4cc2a07128bf644ff4b1d98daf7a9dbf57da/pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769", size = 1738360 }, + { url = "https://files.pythonhosted.org/packages/a5/ae/e14b0ff8b3f48e02394d8acd911376b7b66e164535687ef7dc24ea03072f/pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5", size = 1919411 }, +] + +[[package]] +name = "pygments" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", size = 4891905 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 }, +] + +[[package]] +name = "pylint" +version = "3.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "astroid" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "dill" }, + { name = "isort" }, + { name = "mccabe" }, + { name = "platformdirs" }, + { name = "tomlkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/63/3a/13e90e29777e695d90f422cf4fadb81c999e4755a9089838561bd0590cac/pylint-3.3.1.tar.gz", hash = "sha256:9f3dcc87b1203e612b78d91a896407787e708b3f189b5fa0b307712d49ff0c6e", size = 1516703 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/11/4a3f814eee14593f3cfcf7046bc765bf1646d5c88132c08c45310fc7d85f/pylint-3.3.1-py3-none-any.whl", hash = "sha256:2f846a466dd023513240bc140ad2dd73bfc080a5d85a710afdb728c420a5a2b9", size = 521768 }, +] + +[[package]] +name = "pymdown-extensions" +version = "10.11.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/71/2730a20e9e3752393d78998347f8b1085ef9c417646ea9befbeef221e3c4/pymdown_extensions-10.11.2.tar.gz", hash = "sha256:bc8847ecc9e784a098efd35e20cba772bc5a1b529dfcef9dc1972db9021a1049", size = 830241 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/35/c0edf199257ef0a7d407d29cd51c4e70d1dad4370a5f44deb65a7a5475e2/pymdown_extensions-10.11.2-py3-none-any.whl", hash = "sha256:41cdde0a77290e480cf53892f5c5e50921a7ee3e5cd60ba91bf19837b33badcf", size = 259044 }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, +] + +[[package]] +name = "pytz" +version = "2024.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/31/3c70bf7603cc2dca0f19bdc53b4537a797747a58875b552c8c413d963a3f/pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a", size = 319692 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002 }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612 }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040 }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829 }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167 }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952 }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301 }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638 }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, +] + +[[package]] +name = "pyyaml-env-tag" +version = "0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/8e/da1c6c58f751b70f8ceb1eb25bc25d524e8f14fe16edcce3f4e3ba08629c/pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb", size = 5631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069", size = 3911 }, +] + +[[package]] +name = "rapidfuzz" +version = "3.9.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/b0/e0756b5efe826c1bdf6442777cc924b41258685dcf372ee77399cc10408e/rapidfuzz-3.9.6.tar.gz", hash = "sha256:5cf2a7d621e4515fee84722e93563bf77ff2cbe832a77a48b81f88f9e23b9e8d", size = 1596107 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/55/5ba0016fe8fba98d8ff55832dd7d79f2d6b93fe27be7863ccf3f79366d76/rapidfuzz-3.9.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:52e4675f642fbc85632f691b67115a243cd4d2a47bdcc4a3d9a79e784518ff97", size = 2055435 }, + { url = "https://files.pythonhosted.org/packages/55/23/1d0c51c01fbff028ff5746a388edd610a591e76153fca72f6f7e68b5fc14/rapidfuzz-3.9.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1f93a2f13038700bd245b927c46a2017db3dcd4d4ff94687d74b5123689b873b", size = 1510617 }, + { url = "https://files.pythonhosted.org/packages/28/d6/8dd267f4377d8bf1698d891a28c24d417499724355f6a3541c0b5ab1c35d/rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b70500bca460264b8141d8040caee22e9cf0418c5388104ff0c73fb69ee28f", size = 1559930 }, + { url = "https://files.pythonhosted.org/packages/6a/3e/254fd9e2ce895480bc43a5a11a35d4825b11918d694c959cc0e214d842a9/rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1e037fb89f714a220f68f902fc6300ab7a33349f3ce8ffae668c3b3a40b0b06", size = 5964374 }, + { url = "https://files.pythonhosted.org/packages/d2/cd/3e555024d9168dbd732e919fb0f7d05c3f6809d6ed86042383efeb6f98a0/rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6792f66d59b86ccfad5e247f2912e255c85c575789acdbad8e7f561412ffed8a", size = 1825493 }, + { url = "https://files.pythonhosted.org/packages/32/5f/c47c511e2b174e80ea1091722359b4db7900e4987a4bcacffae6f27237c0/rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68d9cffe710b67f1969cf996983608cee4490521d96ea91d16bd7ea5dc80ea98", size = 1830053 }, + { url = "https://files.pythonhosted.org/packages/e9/85/88f1fd986714887ad4448c7b321c85b9aa5842df9deb606bcdfdfc35fae6/rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63daaeeea76da17fa0bbe7fb05cba8ed8064bb1a0edf8360636557f8b6511961", size = 3384091 }, + { url = "https://files.pythonhosted.org/packages/cc/3f/9a941793dbc419a9e9aad742d8057c8440f191ab3758d1ce2c12e9f27ccd/rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d214e063bffa13e3b771520b74f674b22d309b5720d4df9918ff3e0c0f037720", size = 2458230 }, + { url = "https://files.pythonhosted.org/packages/9d/40/40b75226e0b45ba0212b8ce19996b8970fd3de4748341f6bdd0302b54856/rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ed443a2062460f44c0346cb9d269b586496b808c2419bbd6057f54061c9b9c75", size = 7239493 }, + { url = "https://files.pythonhosted.org/packages/df/62/47401ac22299f70a8231f7e7421b3f804cd716f6a24521ef172dec7afe01/rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:5b0c9b227ee0076fb2d58301c505bb837a290ae99ee628beacdb719f0626d749", size = 2837398 }, + { url = "https://files.pythonhosted.org/packages/59/f2/a3db1b31dc80d906528e03d213a9f9bd8c44547cb1cbf9a3c59649058c2e/rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:82c9722b7dfaa71e8b61f8c89fed0482567fb69178e139fe4151fc71ed7df782", size = 3386617 }, + { url = "https://files.pythonhosted.org/packages/5f/41/2d285edb31f718c81e3433a56142d5e606ba20d0997fcf57774042f79850/rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c18897c95c0a288347e29537b63608a8f63a5c3cb6da258ac46fcf89155e723e", size = 4392081 }, + { url = "https://files.pythonhosted.org/packages/37/7b/d355309d5aa606dd91d91501a64c87db32e3d75b775950a19df8ec0288f0/rapidfuzz-3.9.6-cp311-cp311-win32.whl", hash = "sha256:3e910cf08944da381159587709daaad9e59d8ff7bca1f788d15928f3c3d49c2a", size = 1854906 }, + { url = "https://files.pythonhosted.org/packages/aa/bb/cdd512d40f8ea67692deee6b0da4f7235c6a0f9e126fdded32b62c5d91fe/rapidfuzz-3.9.6-cp311-cp311-win_amd64.whl", hash = "sha256:59c4a61fab676d37329fc3a671618a461bfeef53a4d0b8b12e3bc24a14e166f8", size = 1654104 }, + { url = "https://files.pythonhosted.org/packages/53/92/5014563b1e8f901f983f96606c6982ff4ed286a8ae4335b67012a4a50cf9/rapidfuzz-3.9.6-cp311-cp311-win_arm64.whl", hash = "sha256:8b4afea244102332973377fddbe54ce844d0916e1c67a5123432291717f32ffa", size = 855134 }, + { url = "https://files.pythonhosted.org/packages/df/f4/e8175a4ad862ede4caa8dd287d187d12db2f4eb426b00b030b1cb7f4d2dd/rapidfuzz-3.9.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:70591b28b218fff351b88cdd7f2359a01a71f9f7f5a2e465ce3715ed4b3c422b", size = 2053429 }, + { url = "https://files.pythonhosted.org/packages/22/a5/8c14e41bcdea3be343764de6ad464ff87300352f8e2d01064bf0f1809e9d/rapidfuzz-3.9.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee2d8355c7343c631a03e57540ea06e8717c19ecf5ff64ea07e0498f7f161457", size = 1506224 }, + { url = "https://files.pythonhosted.org/packages/75/92/51d74bdf539475d8c71df76da73d4609231254ac2499beb24efa78667b14/rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:708fb675de0f47b9635d1cc6fbbf80d52cb710d0a1abbfae5c84c46e3abbddc3", size = 1542825 }, + { url = "https://files.pythonhosted.org/packages/b9/7a/29bf00754308ba43eb6f95988445b86953b29bc780164f8961d0c3d67b89/rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d66c247c2d3bb7a9b60567c395a15a929d0ebcc5f4ceedb55bfa202c38c6e0c", size = 5858827 }, + { url = "https://files.pythonhosted.org/packages/0a/a3/1b5a2bb95e5b532fe571b6b0c8c4cf35893e748eac5cac2ae7d3c0f41d47/rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15146301b32e6e3d2b7e8146db1a26747919d8b13690c7f83a4cb5dc111b3a08", size = 1794607 }, + { url = "https://files.pythonhosted.org/packages/0e/42/7ee9c15087d6b7146e73e4650bfb8ddbbe2161a9edbe2b44be9ffb68a2f1/rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7a03da59b6c7c97e657dd5cd4bcaab5fe4a2affd8193958d6f4d938bee36679", size = 1818934 }, + { url = "https://files.pythonhosted.org/packages/15/30/0a4bc8b641e2374475c03d6c6ec6568303ac2070698c067c690daefd9b8f/rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d2c2fe19e392dbc22695b6c3b2510527e2b774647e79936bbde49db7742d6f1", size = 3381282 }, + { url = "https://files.pythonhosted.org/packages/e1/45/6c9bbba66a5ada5679c0705375068337c2573a940443868cbcba5c909c07/rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:91aaee4c94cb45930684f583ffc4e7c01a52b46610971cede33586cf8a04a12e", size = 2425764 }, + { url = "https://files.pythonhosted.org/packages/74/b3/b02d002e643ec5f97278b6f04c2293b9b678249220f253b7e649a4e0df3a/rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3f5702828c10768f9281180a7ff8597da1e5002803e1304e9519dd0f06d79a85", size = 7176966 }, + { url = "https://files.pythonhosted.org/packages/3f/0d/52cd49cafb91fc0cc4e75e3beab7b16fffe62a6c66d5fb5d336b2deacda5/rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ccd1763b608fb4629a0b08f00b3c099d6395e67c14e619f6341b2c8429c2f310", size = 2800253 }, + { url = "https://files.pythonhosted.org/packages/4f/ee/82004bf9274566711b134bb2628bf878046a9212c798bd10f0138ad6cca9/rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc7a0d4b2cb166bc46d02c8c9f7551cde8e2f3c9789df3827309433ee9771163", size = 3345106 }, + { url = "https://files.pythonhosted.org/packages/d8/78/7008dcd6701cc84eb74fad6c743f03c33c7f41516d15a313fcd759b2d614/rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7496f53d40560a58964207b52586783633f371683834a8f719d6d965d223a2eb", size = 4360019 }, + { url = "https://files.pythonhosted.org/packages/07/25/5de7013daac2eb7b18bc0123fa5d83ddbe5508673b14b9ca7e32f2be3cbe/rapidfuzz-3.9.6-cp312-cp312-win32.whl", hash = "sha256:5eb1a9272ca71bc72be5415c2fa8448a6302ea4578e181bb7da9db855b367df0", size = 1842659 }, + { url = "https://files.pythonhosted.org/packages/7b/81/bfd28ed4a5638b594985988921d19fd716f119dde93703d8545c1bcb8e7e/rapidfuzz-3.9.6-cp312-cp312-win_amd64.whl", hash = "sha256:0d21fc3c0ca507a1180152a6dbd129ebaef48facde3f943db5c1055b6e6be56a", size = 1648213 }, + { url = "https://files.pythonhosted.org/packages/8a/81/249ed13ce5cee9c9aa9c69656e2d78ed240534d478ebaada04930513820a/rapidfuzz-3.9.6-cp312-cp312-win_arm64.whl", hash = "sha256:43bb27a57c29dc5fa754496ba6a1a508480d21ae99ac0d19597646c16407e9f3", size = 849878 }, + { url = "https://files.pythonhosted.org/packages/d1/de/83b660bb054a3bd85f033a2521ba99ae65e49b95f3b18745cfcf68a94ae7/rapidfuzz-3.9.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:83a5ac6547a9d6eedaa212975cb8f2ce2aa07e6e30833b40e54a52b9f9999aa4", size = 2026087 }, + { url = "https://files.pythonhosted.org/packages/6f/f3/7b7f8ddb80562722c6cb86a3396ad6945c0003f36addbca610782fe7e113/rapidfuzz-3.9.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:10f06139142ecde67078ebc9a745965446132b998f9feebffd71acdf218acfcc", size = 1499413 }, + { url = "https://files.pythonhosted.org/packages/bd/e9/a37db9a3674b210d6ef21b15c66eb1585125d553ed5b73f6481dadf932c3/rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74720c3f24597f76c7c3e2c4abdff55f1664f4766ff5b28aeaa689f8ffba5fab", size = 1537241 }, + { url = "https://files.pythonhosted.org/packages/75/67/e111c7a11eafd70677d6688c36d93b54a43783119b16ee5591589a110ff9/rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2bce52b5c150878e558a0418c2b637fb3dbb6eb38e4eb27d24aa839920483e", size = 5877164 }, + { url = "https://files.pythonhosted.org/packages/80/58/ce20051fbbac74bc369d4ab3f450683ebf70e456474d6172ba9b6f6164f0/rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1611199f178793ca9a060c99b284e11f6d7d124998191f1cace9a0245334d219", size = 1766888 }, + { url = "https://files.pythonhosted.org/packages/8f/b4/afde433a48fb18f5d7ddf144ffb2b0b674f3f176a2aca89f2ea06fe54d4f/rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0308b2ad161daf502908a6e21a57c78ded0258eba9a8f5e2545e2dafca312507", size = 1819868 }, + { url = "https://files.pythonhosted.org/packages/53/47/089d2d8a27c4e90dd4dfb532d31bc873537fcc479874e9909a9018156855/rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eda91832201b86e3b70835f91522587725bec329ec68f2f7faf5124091e5ca7", size = 3361094 }, + { url = "https://files.pythonhosted.org/packages/95/a5/f5e1fc00485f45ed17803f91f7877fa07b0fb4006ff42cfebd7355ad1bdc/rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ece873c093aedd87fc07c2a7e333d52e458dc177016afa1edaf157e82b6914d8", size = 2421352 }, + { url = "https://files.pythonhosted.org/packages/57/fa/0d6573980251fb63147a35be8f4fae962d79ebbe4b675fdaf0cf16726aa0/rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d97d3c9d209d5c30172baea5966f2129e8a198fec4a1aeb2f92abb6e82a2edb1", size = 7190683 }, + { url = "https://files.pythonhosted.org/packages/71/50/2f866735f788d565a2ed6d113a54a410b4a412b46cb399e3ae466e72730f/rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6c4550d0db4931f5ebe9f0678916d1b06f06f5a99ba0b8a48b9457fd8959a7d4", size = 2791255 }, + { url = "https://files.pythonhosted.org/packages/a2/90/7c36906695b216bf489cd234d95e5e00f06f976054ce3c441085a5ae650f/rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b6b8dd4af6324fc325d9483bec75ecf9be33e590928c9202d408e4eafff6a0a6", size = 3341004 }, + { url = "https://files.pythonhosted.org/packages/16/2b/15f6df84ef774457fd77a80436154e8fc6c903bfc997490a275fca84adda/rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:16122ae448bc89e2bea9d81ce6cb0f751e4e07da39bd1e70b95cae2493857853", size = 4355422 }, + { url = "https://files.pythonhosted.org/packages/7f/3b/e593d8f0b7bb2c1cb00514552056a4b61000d2d8f4fd24e016fdd2e1afe1/rapidfuzz-3.9.6-cp313-cp313-win32.whl", hash = "sha256:71cc168c305a4445109cd0d4925406f6e66bcb48fde99a1835387c58af4ecfe9", size = 1840420 }, + { url = "https://files.pythonhosted.org/packages/fe/09/d25939dfe7eea5e4a474dfebd60073acd792621d42a9ffe7534627c8ad26/rapidfuzz-3.9.6-cp313-cp313-win_amd64.whl", hash = "sha256:59ee78f2ecd53fef8454909cda7400fe2cfcd820f62b8a5d4dfe930102268054", size = 1645331 }, + { url = "https://files.pythonhosted.org/packages/d8/26/6eda9e43dd5b0833feb4cf9ea0ad4e46b07c4811d8b8815a8517b379c640/rapidfuzz-3.9.6-cp313-cp313-win_arm64.whl", hash = "sha256:58b4ce83f223605c358ae37e7a2d19a41b96aa65b1fede99cc664c9053af89ac", size = 848759 }, +] + +[[package]] +name = "red-commons" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/a9/de9bad2793856dfdc7dca87b306bed42f04dbcf703e21093b30980325ca5/Red-Commons-1.0.0.tar.gz", hash = "sha256:b9bcc55c72801c33eb0c77aaf48041d018bfb5f1293053cff8a3e10e4d33e52d", size = 2898 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/7a/4afb80e4aa69fec9736159d2571db76e3546c6e3b4e8deefe0e55114526c/red_commons-1.0.0-py3-none-any.whl", hash = "sha256:7007b70abfe8e2c9a8e03f8b60810ab1201c4d8274974e0c3842d972cb25af44", size = 3531 }, +] + +[[package]] +name = "red-discordbot" +version = "3.5.13" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "aiohttp-json-rpc" }, + { name = "aiosignal" }, + { name = "apsw" }, + { name = "async-timeout", marker = "python_full_version >= '3.12'" }, + { name = "attrs" }, + { name = "babel" }, + { name = "brotli" }, + { name = "click" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "discord-py" }, + { name = "distro", marker = "sys_platform == 'linux'" }, + { name = "frozenlist" }, + { name = "idna" }, + { name = "importlib-metadata", marker = "python_full_version >= '3.12'" }, + { name = "markdown" }, + { name = "markdown-it-py" }, + { name = "mdurl" }, + { name = "multidict" }, + { name = "orjson" }, + { name = "packaging" }, + { name = "platformdirs" }, + { name = "psutil" }, + { name = "pygments" }, + { name = "python-dateutil" }, + { name = "pyyaml" }, + { name = "rapidfuzz" }, + { name = "red-commons" }, + { name = "red-lavalink" }, + { name = "rich" }, + { name = "schema" }, + { name = "six" }, + { name = "typing-extensions" }, + { name = "uvloop", marker = "platform_python_implementation == 'CPython' and sys_platform != 'win32'" }, + { name = "yarl" }, + { name = "zipp", marker = "python_full_version >= '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e2/d2/1055cd2db6cec6278046f71ed486d852ce7578fbff5579d3dd0c147cf7e0/red_discordbot-3.5.13.tar.gz", hash = "sha256:7708dcc8203f2487616e95eba2aa1a6e5d78fbb03975c0b96587b0548c0f5d5b", size = 3661865 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/67/2908f01ddb83dc5cbf6cd37f1ae6fc70cad00871de763f4ee10d2a7a219d/Red_DiscordBot-3.5.13-py3-none-any.whl", hash = "sha256:bd598a91c7504503b03b0d10f8ad1f230403fbab981a78f00461be61d458c285", size = 5754615 }, +] + +[[package]] +name = "red-lavalink" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "discord-py" }, + { name = "red-commons" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/66/b05f3661afbc22d7af10827eaf68e5da5076d73ad0c3f7028acb8bf40bfd/Red-Lavalink-0.11.0.tar.gz", hash = "sha256:6ee2671dfc43a96b7e6be4effaa4137024de51bc5681f64a67c125bc3b7d4f99", size = 33992 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/01/748c284bd03e788ac2c6cf2c58f19b4d1e3ad96dae36b21e289f1bc6c5e5/Red_Lavalink-0.11.0-py3-none-any.whl", hash = "sha256:f76329eee2ec5e4d77e0e97fe6ba76207efdcc8d963a9c39913cf91057d7920a", size = 36060 }, +] + +[[package]] +name = "regex" +version = "2024.9.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/38/148df33b4dbca3bd069b963acab5e0fa1a9dbd6820f8c322d0dd6faeff96/regex-2024.9.11.tar.gz", hash = "sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd", size = 399403 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/a1/d526b7b6095a0019aa360948c143aacfeb029919c898701ce7763bbe4c15/regex-2024.9.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df", size = 482483 }, + { url = "https://files.pythonhosted.org/packages/32/d9/bfdd153179867c275719e381e1e8e84a97bd186740456a0dcb3e7125c205/regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268", size = 287442 }, + { url = "https://files.pythonhosted.org/packages/33/c4/60f3370735135e3a8d673ddcdb2507a8560d0e759e1398d366e43d000253/regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad", size = 284561 }, + { url = "https://files.pythonhosted.org/packages/b1/51/91a5ebdff17f9ec4973cb0aa9d37635efec1c6868654bbc25d1543aca4ec/regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679", size = 791779 }, + { url = "https://files.pythonhosted.org/packages/07/4a/022c5e6f0891a90cd7eb3d664d6c58ce2aba48bff107b00013f3d6167069/regex-2024.9.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4", size = 832605 }, + { url = "https://files.pythonhosted.org/packages/ac/1c/3793990c8c83ca04e018151ddda83b83ecc41d89964f0f17749f027fc44d/regex-2024.9.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664", size = 818556 }, + { url = "https://files.pythonhosted.org/packages/e9/5c/8b385afbfacb853730682c57be56225f9fe275c5bf02ac1fc88edbff316d/regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50", size = 792808 }, + { url = "https://files.pythonhosted.org/packages/9b/8b/a4723a838b53c771e9240951adde6af58c829fb6a6a28f554e8131f53839/regex-2024.9.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199", size = 781115 }, + { url = "https://files.pythonhosted.org/packages/83/5f/031a04b6017033d65b261259c09043c06f4ef2d4eac841d0649d76d69541/regex-2024.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4", size = 778155 }, + { url = "https://files.pythonhosted.org/packages/fd/cd/4660756070b03ce4a66663a43f6c6e7ebc2266cc6b4c586c167917185eb4/regex-2024.9.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd", size = 784614 }, + { url = "https://files.pythonhosted.org/packages/93/8d/65b9bea7df120a7be8337c415b6d256ba786cbc9107cebba3bf8ff09da99/regex-2024.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f", size = 853744 }, + { url = "https://files.pythonhosted.org/packages/96/a7/fba1eae75eb53a704475baf11bd44b3e6ccb95b316955027eb7748f24ef8/regex-2024.9.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96", size = 855890 }, + { url = "https://files.pythonhosted.org/packages/45/14/d864b2db80a1a3358534392373e8a281d95b28c29c87d8548aed58813910/regex-2024.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1", size = 781887 }, + { url = "https://files.pythonhosted.org/packages/4d/a9/bfb29b3de3eb11dc9b412603437023b8e6c02fb4e11311863d9bf62c403a/regex-2024.9.11-cp311-cp311-win32.whl", hash = "sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9", size = 261644 }, + { url = "https://files.pythonhosted.org/packages/c7/ab/1ad2511cf6a208fde57fafe49829cab8ca018128ab0d0b48973d8218634a/regex-2024.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf", size = 274033 }, + { url = "https://files.pythonhosted.org/packages/6e/92/407531450762bed778eedbde04407f68cbd75d13cee96c6f8d6903d9c6c1/regex-2024.9.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7", size = 483590 }, + { url = "https://files.pythonhosted.org/packages/8e/a2/048acbc5ae1f615adc6cba36cc45734e679b5f1e4e58c3c77f0ed611d4e2/regex-2024.9.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231", size = 288175 }, + { url = "https://files.pythonhosted.org/packages/8a/ea/909d8620329ab710dfaf7b4adee41242ab7c9b95ea8d838e9bfe76244259/regex-2024.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d", size = 284749 }, + { url = "https://files.pythonhosted.org/packages/ca/fa/521eb683b916389b4975337873e66954e0f6d8f91bd5774164a57b503185/regex-2024.9.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64", size = 795181 }, + { url = "https://files.pythonhosted.org/packages/28/db/63047feddc3280cc242f9c74f7aeddc6ee662b1835f00046f57d5630c827/regex-2024.9.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42", size = 835842 }, + { url = "https://files.pythonhosted.org/packages/e3/94/86adc259ff8ec26edf35fcca7e334566c1805c7493b192cb09679f9c3dee/regex-2024.9.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766", size = 823533 }, + { url = "https://files.pythonhosted.org/packages/29/52/84662b6636061277cb857f658518aa7db6672bc6d1a3f503ccd5aefc581e/regex-2024.9.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a", size = 797037 }, + { url = "https://files.pythonhosted.org/packages/c3/2a/cd4675dd987e4a7505f0364a958bc41f3b84942de9efaad0ef9a2646681c/regex-2024.9.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9", size = 784106 }, + { url = "https://files.pythonhosted.org/packages/6f/75/3ea7ec29de0bbf42f21f812f48781d41e627d57a634f3f23947c9a46e303/regex-2024.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d", size = 782468 }, + { url = "https://files.pythonhosted.org/packages/d3/67/15519d69b52c252b270e679cb578e22e0c02b8dd4e361f2b04efcc7f2335/regex-2024.9.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822", size = 790324 }, + { url = "https://files.pythonhosted.org/packages/9c/71/eff77d3fe7ba08ab0672920059ec30d63fa7e41aa0fb61c562726e9bd721/regex-2024.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0", size = 860214 }, + { url = "https://files.pythonhosted.org/packages/81/11/e1bdf84a72372e56f1ea4b833dd583b822a23138a616ace7ab57a0e11556/regex-2024.9.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a", size = 859420 }, + { url = "https://files.pythonhosted.org/packages/ea/75/9753e9dcebfa7c3645563ef5c8a58f3a47e799c872165f37c55737dadd3e/regex-2024.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a", size = 787333 }, + { url = "https://files.pythonhosted.org/packages/bc/4e/ba1cbca93141f7416624b3ae63573e785d4bc1834c8be44a8f0747919eca/regex-2024.9.11-cp312-cp312-win32.whl", hash = "sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776", size = 262058 }, + { url = "https://files.pythonhosted.org/packages/6e/16/efc5f194778bf43e5888209e5cec4b258005d37c613b67ae137df3b89c53/regex-2024.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009", size = 273526 }, + { url = "https://files.pythonhosted.org/packages/93/0a/d1c6b9af1ff1e36832fe38d74d5c5bab913f2bdcbbd6bc0e7f3ce8b2f577/regex-2024.9.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784", size = 483376 }, + { url = "https://files.pythonhosted.org/packages/a4/42/5910a050c105d7f750a72dcb49c30220c3ae4e2654e54aaaa0e9bc0584cb/regex-2024.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36", size = 288112 }, + { url = "https://files.pythonhosted.org/packages/8d/56/0c262aff0e9224fa7ffce47b5458d373f4d3e3ff84e99b5ff0cb15e0b5b2/regex-2024.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92", size = 284608 }, + { url = "https://files.pythonhosted.org/packages/b9/54/9fe8f9aec5007bbbbce28ba3d2e3eaca425f95387b7d1e84f0d137d25237/regex-2024.9.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86", size = 795337 }, + { url = "https://files.pythonhosted.org/packages/b2/e7/6b2f642c3cded271c4f16cc4daa7231be544d30fe2b168e0223724b49a61/regex-2024.9.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85", size = 835848 }, + { url = "https://files.pythonhosted.org/packages/cd/9e/187363bdf5d8c0e4662117b92aa32bf52f8f09620ae93abc7537d96d3311/regex-2024.9.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963", size = 823503 }, + { url = "https://files.pythonhosted.org/packages/f8/10/601303b8ee93589f879664b0cfd3127949ff32b17f9b6c490fb201106c4d/regex-2024.9.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6", size = 797049 }, + { url = "https://files.pythonhosted.org/packages/ef/1c/ea200f61ce9f341763f2717ab4daebe4422d83e9fd4ac5e33435fd3a148d/regex-2024.9.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802", size = 784144 }, + { url = "https://files.pythonhosted.org/packages/d8/5c/d2429be49ef3292def7688401d3deb11702c13dcaecdc71d2b407421275b/regex-2024.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29", size = 782483 }, + { url = "https://files.pythonhosted.org/packages/12/d9/cbc30f2ff7164f3b26a7760f87c54bf8b2faed286f60efd80350a51c5b99/regex-2024.9.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8", size = 790320 }, + { url = "https://files.pythonhosted.org/packages/19/1d/43ed03a236313639da5a45e61bc553c8d41e925bcf29b0f8ecff0c2c3f25/regex-2024.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84", size = 860435 }, + { url = "https://files.pythonhosted.org/packages/34/4f/5d04da61c7c56e785058a46349f7285ae3ebc0726c6ea7c5c70600a52233/regex-2024.9.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554", size = 859571 }, + { url = "https://files.pythonhosted.org/packages/12/7f/8398c8155a3c70703a8e91c29532558186558e1aea44144b382faa2a6f7a/regex-2024.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8", size = 787398 }, + { url = "https://files.pythonhosted.org/packages/58/3a/f5903977647a9a7e46d5535e9e96c194304aeeca7501240509bde2f9e17f/regex-2024.9.11-cp313-cp313-win32.whl", hash = "sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8", size = 262035 }, + { url = "https://files.pythonhosted.org/packages/ff/80/51ba3a4b7482f6011095b3a036e07374f64de180b7d870b704ed22509002/regex-2024.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f", size = 273510 }, +] + +[[package]] +name = "requests" +version = "2.32.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, +] + +[[package]] +name = "rich" +version = "13.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cf/60/5959113cae0ce512cf246a6871c623117330105a0d5f59b4e26138f2c9cc/rich-13.8.0.tar.gz", hash = "sha256:a5ac1f1cd448ade0d59cc3356f7db7a7ccda2c8cbae9c7a90c28ff463d3e91f4", size = 222072 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/d9/c2a126eeae791e90ea099d05cb0515feea3688474b978343f3cdcfe04523/rich-13.8.0-py3-none-any.whl", hash = "sha256:2e85306a063b9492dffc86278197a60cbece75bcb766022f3436f567cae11bdc", size = 241597 }, +] + +[[package]] +name = "ruff" +version = "0.6.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/0d/6148a48dab5662ca1d5a93b7c0d13c03abd3cc7e2f35db08410e47cef15d/ruff-0.6.9.tar.gz", hash = "sha256:b076ef717a8e5bc819514ee1d602bbdca5b4420ae13a9cf61a0c0a4f53a2baa2", size = 3095355 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6e/8f/f7a0a0ef1818662efb32ed6df16078c95da7a0a3248d64c2410c1e27799f/ruff-0.6.9-py3-none-linux_armv6l.whl", hash = "sha256:064df58d84ccc0ac0fcd63bc3090b251d90e2a372558c0f057c3f75ed73e1ccd", size = 10440526 }, + { url = "https://files.pythonhosted.org/packages/8b/69/b179a5faf936a9e2ab45bb412a668e4661eded964ccfa19d533f29463ef6/ruff-0.6.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:140d4b5c9f5fc7a7b074908a78ab8d384dd7f6510402267bc76c37195c02a7ec", size = 10034612 }, + { url = "https://files.pythonhosted.org/packages/c7/ef/fd1b4be979c579d191eeac37b5cfc0ec906de72c8bcd8595e2c81bb700c1/ruff-0.6.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53fd8ca5e82bdee8da7f506d7b03a261f24cd43d090ea9db9a1dc59d9313914c", size = 9706197 }, + { url = "https://files.pythonhosted.org/packages/29/61/b376d775deb5851cb48d893c568b511a6d3625ef2c129ad5698b64fb523c/ruff-0.6.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645d7d8761f915e48a00d4ecc3686969761df69fb561dd914a773c1a8266e14e", size = 10751855 }, + { url = "https://files.pythonhosted.org/packages/13/d7/def9e5f446d75b9a9c19b24231a3a658c075d79163b08582e56fa5dcfa38/ruff-0.6.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eae02b700763e3847595b9d2891488989cac00214da7f845f4bcf2989007d577", size = 10200889 }, + { url = "https://files.pythonhosted.org/packages/6c/d6/7f34160818bcb6e84ce293a5966cba368d9112ff0289b273fbb689046047/ruff-0.6.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d5ccc9e58112441de8ad4b29dcb7a86dc25c5f770e3c06a9d57e0e5eba48829", size = 11038678 }, + { url = "https://files.pythonhosted.org/packages/13/34/a40ff8ae62fb1b26fb8e6fa7e64bc0e0a834b47317880de22edd6bfb54fb/ruff-0.6.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:417b81aa1c9b60b2f8edc463c58363075412866ae4e2b9ab0f690dc1e87ac1b5", size = 11808682 }, + { url = "https://files.pythonhosted.org/packages/2e/6d/25a4386ae4009fc798bd10ba48c942d1b0b3e459b5403028f1214b6dd161/ruff-0.6.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c866b631f5fbce896a74a6e4383407ba7507b815ccc52bcedabb6810fdb3ef7", size = 11330446 }, + { url = "https://files.pythonhosted.org/packages/f7/f6/bdf891a9200d692c94ebcd06ae5a2fa5894e522f2c66c2a12dd5d8cb2654/ruff-0.6.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b118afbb3202f5911486ad52da86d1d52305b59e7ef2031cea3425142b97d6f", size = 12483048 }, + { url = "https://files.pythonhosted.org/packages/a7/86/96f4252f41840e325b3fa6c48297e661abb9f564bd7dcc0572398c8daa42/ruff-0.6.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67267654edc23c97335586774790cde402fb6bbdb3c2314f1fc087dee320bfa", size = 10936855 }, + { url = "https://files.pythonhosted.org/packages/45/87/801a52d26c8dbf73424238e9908b9ceac430d903c8ef35eab1b44fcfa2bd/ruff-0.6.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3ef0cc774b00fec123f635ce5c547dac263f6ee9fb9cc83437c5904183b55ceb", size = 10713007 }, + { url = "https://files.pythonhosted.org/packages/be/27/6f7161d90320a389695e32b6ebdbfbedde28ccbf52451e4b723d7ce744ad/ruff-0.6.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:12edd2af0c60fa61ff31cefb90aef4288ac4d372b4962c2864aeea3a1a2460c0", size = 10274594 }, + { url = "https://files.pythonhosted.org/packages/00/52/dc311775e7b5f5b19831563cb1572ecce63e62681bccc609867711fae317/ruff-0.6.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:55bb01caeaf3a60b2b2bba07308a02fca6ab56233302406ed5245180a05c5625", size = 10608024 }, + { url = "https://files.pythonhosted.org/packages/98/b6/be0a1ddcbac65a30c985cf7224c4fce786ba2c51e7efeb5178fe410ed3cf/ruff-0.6.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:925d26471fa24b0ce5a6cdfab1bb526fb4159952385f386bdcc643813d472039", size = 10982085 }, + { url = "https://files.pythonhosted.org/packages/bb/a4/c84bc13d0b573cf7bb7d17b16d6d29f84267c92d79b2f478d4ce322e8e72/ruff-0.6.9-py3-none-win32.whl", hash = "sha256:eb61ec9bdb2506cffd492e05ac40e5bc6284873aceb605503d8494180d6fc84d", size = 8522088 }, + { url = "https://files.pythonhosted.org/packages/74/be/fc352bd8ca40daae8740b54c1c3e905a7efe470d420a268cd62150248c91/ruff-0.6.9-py3-none-win_amd64.whl", hash = "sha256:785d31851c1ae91f45b3d8fe23b8ae4b5170089021fbb42402d811135f0b7117", size = 9359275 }, + { url = "https://files.pythonhosted.org/packages/3e/14/fd026bc74ded05e2351681545a5f626e78ef831f8edce064d61acd2e6ec7/ruff-0.6.9-py3-none-win_arm64.whl", hash = "sha256:a9641e31476d601f83cd602608739a0840e348bda93fec9f1ee816f8b6798b93", size = 8679879 }, +] + +[[package]] +name = "schema" +version = "0.7.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/01/0ea2e66bad2f13271e93b729c653747614784d3ebde219679e41ccdceecd/schema-0.7.7.tar.gz", hash = "sha256:7da553abd2958a19dc2547c388cde53398b39196175a9be59ea1caf5ab0a1807", size = 44245 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/1b/81855a88c6db2b114d5b2e9f96339190d5ee4d1b981d217fa32127bb00e0/schema-0.7.7-py2.py3-none-any.whl", hash = "sha256:5d976a5b50f36e74e2157b47097b60002bd4d42e65425fcc9c9befadb4255dde", size = 18632 }, +] + +[[package]] +name = "seacogs" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "aiosqlite" }, + { name = "beautifulsoup4" }, + { name = "colorthief" }, + { name = "markdownify" }, + { name = "numpy" }, + { name = "phx-class-registry" }, + { name = "pillow" }, + { name = "py-dactyl" }, + { name = "pydantic" }, + { name = "red-discordbot" }, + { name = "websockets" }, +] + +[package.optional-dependencies] +documentation = [ + { name = "mkdocs" }, + { name = "mkdocs-git-authors-plugin" }, + { name = "mkdocs-git-revision-date-localized-plugin" }, + { name = "mkdocs-material", extra = ["imaging"] }, + { name = "mkdocs-redirects" }, + { name = "mkdocstrings", extra = ["python"] }, +] + +[package.dev-dependencies] +dev = [ + { name = "pylint" }, + { name = "ruff" }, + { name = "sqlite-web" }, +] + +[package.metadata] +requires-dist = [ + { name = "aiosqlite", specifier = ">=0.20.0" }, + { name = "beautifulsoup4", specifier = ">=4.12.3" }, + { name = "colorthief", specifier = ">=0.2.1" }, + { name = "markdownify", specifier = ">=0.13.1" }, + { name = "mkdocs", marker = "extra == 'documentation'", specifier = ">=1.6.1" }, + { name = "mkdocs-git-authors-plugin", marker = "extra == 'documentation'", specifier = ">=0.9.0" }, + { name = "mkdocs-git-revision-date-localized-plugin", marker = "extra == 'documentation'", specifier = ">=1.2.9" }, + { name = "mkdocs-material", extras = ["imaging"], marker = "extra == 'documentation'", specifier = ">=9.5.40" }, + { name = "mkdocs-redirects", marker = "extra == 'documentation'", specifier = ">=1.2.1" }, + { name = "mkdocstrings", extras = ["python"], marker = "extra == 'documentation'", specifier = ">=0.26.1" }, + { name = "numpy", specifier = ">=2.1.2" }, + { name = "phx-class-registry", specifier = ">=5.0.0" }, + { name = "pillow", specifier = ">=10.4.0" }, + { name = "py-dactyl", git = "https://github.com/cswimr/pydactyl" }, + { name = "pydantic", specifier = ">=2.9.2" }, + { name = "red-discordbot", specifier = ">=3.5.13" }, + { name = "websockets", specifier = ">=13.1" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pylint", specifier = ">=3.3.1" }, + { name = "ruff", specifier = ">=0.6.9" }, + { name = "sqlite-web", specifier = ">=0.6.4" }, +] + +[[package]] +name = "six" +version = "1.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 }, +] + +[[package]] +name = "smmap" +version = "5.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/04/b5bf6d21dc4041000ccba7eb17dd3055feb237e7ffc2c20d3fae3af62baa/smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62", size = 22291 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/a5/10f97f73544edcdef54409f1d839f6049a0d79df68adbc1ceb24d1aaca42/smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da", size = 24282 }, +] + +[[package]] +name = "soupsieve" +version = "2.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/ce/fbaeed4f9fb8b2daa961f90591662df6a86c1abf25c548329a86920aedfb/soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", size = 101569 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 }, +] + +[[package]] +name = "sqlite-web" +version = "0.6.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "flask" }, + { name = "peewee" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7e/ee/6748afd822a2cc26f40cf2917350be0fbaa6a57bbb0e85dc75a1e098d82c/sqlite-web-0.6.4.tar.gz", hash = "sha256:e4175dd42f4cdc78ef7c329d56f19243efc8d088a6bdfd4c6703e89d18aac2a5", size = 807634 } + +[[package]] +name = "tinycss2" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/44/6f/38d2335a2b70b9982d112bb177e3dbe169746423e33f718bf5e9c7b3ddd3/tinycss2-1.3.0.tar.gz", hash = "sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d", size = 67360 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/4d/0db5b8a613d2a59bbc29bc5bb44a2f8070eb9ceab11c50d477502a8a0092/tinycss2-1.3.0-py3-none-any.whl", hash = "sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7", size = 22532 }, +] + +[[package]] +name = "tomlkit" +version = "0.13.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/09/a439bec5888f00a54b8b9f05fa94d7f901d6735ef4e55dcec9bc37b5d8fa/tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79", size = 192885 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/b6/a447b5e4ec71e13871be01ba81f5dfc9d0af7e473da256ff46bc0e24026f/tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", size = 37955 }, +] + +[[package]] +name = "typing-extensions" +version = "4.12.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, +] + +[[package]] +name = "urllib3" +version = "2.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 }, +] + +[[package]] +name = "uvloop" +version = "0.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/f1/dc9577455e011ad43d9379e836ee73f40b4f99c02946849a44f7ae64835e/uvloop-0.20.0.tar.gz", hash = "sha256:4603ca714a754fc8d9b197e325db25b2ea045385e8a3ad05d3463de725fdf469", size = 2329938 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/bf/45828beccf685b7ed9638d9b77ef382b470c6ca3b5bff78067e02ffd5663/uvloop-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e50289c101495e0d1bb0bfcb4a60adde56e32f4449a67216a1ab2750aa84f037", size = 1320593 }, + { url = "https://files.pythonhosted.org/packages/27/c0/3c24e50bee7802a2add96ca9f0d5eb0ebab07e0a5615539d38aeb89499b9/uvloop-0.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e237f9c1e8a00e7d9ddaa288e535dc337a39bcbf679f290aee9d26df9e72bce9", size = 736676 }, + { url = "https://files.pythonhosted.org/packages/83/ce/ffa3c72954eae36825acfafd2b6a9221d79abd2670c0d25e04d6ef4a2007/uvloop-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:746242cd703dc2b37f9d8b9f173749c15e9a918ddb021575a0205ec29a38d31e", size = 3494573 }, + { url = "https://files.pythonhosted.org/packages/46/6d/4caab3a36199ba52b98d519feccfcf48921d7a6649daf14a93c7e77497e9/uvloop-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82edbfd3df39fb3d108fc079ebc461330f7c2e33dbd002d146bf7c445ba6e756", size = 3489932 }, + { url = "https://files.pythonhosted.org/packages/e4/4f/49c51595bd794945c88613df88922c38076eae2d7653f4624aa6f4980b07/uvloop-0.20.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:80dc1b139516be2077b3e57ce1cb65bfed09149e1d175e0478e7a987863b68f0", size = 4185596 }, + { url = "https://files.pythonhosted.org/packages/b8/94/7e256731260d313f5049717d1c4582d52a3b132424c95e16954a50ab95d3/uvloop-0.20.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f44af67bf39af25db4c1ac27e82e9665717f9c26af2369c404be865c8818dcf", size = 4185746 }, + { url = "https://files.pythonhosted.org/packages/2d/64/31cbd379d6e260ac8de3f672f904e924f09715c3f192b09f26cc8e9f574c/uvloop-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4b75f2950ddb6feed85336412b9a0c310a2edbcf4cf931aa5cfe29034829676d", size = 1324302 }, + { url = "https://files.pythonhosted.org/packages/1e/6b/9207e7177ff30f78299401f2e1163ea41130d4fd29bcdc6d12572c06b728/uvloop-0.20.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:77fbc69c287596880ecec2d4c7a62346bef08b6209749bf6ce8c22bbaca0239e", size = 738105 }, + { url = "https://files.pythonhosted.org/packages/c1/ba/b64b10f577519d875992dc07e2365899a1a4c0d28327059ce1e1bdfb6854/uvloop-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6462c95f48e2d8d4c993a2950cd3d31ab061864d1c226bbf0ee2f1a8f36674b9", size = 4090658 }, + { url = "https://files.pythonhosted.org/packages/0a/f8/5ceea6876154d926604f10c1dd896adf9bce6d55a55911364337b8a5ed8d/uvloop-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:649c33034979273fa71aa25d0fe120ad1777c551d8c4cd2c0c9851d88fcb13ab", size = 4173357 }, + { url = "https://files.pythonhosted.org/packages/18/b2/117ab6bfb18274753fbc319607bf06e216bd7eea8be81d5bac22c912d6a7/uvloop-0.20.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a609780e942d43a275a617c0839d85f95c334bad29c4c0918252085113285b5", size = 4029868 }, + { url = "https://files.pythonhosted.org/packages/6f/52/deb4be09060637ef4752adaa0b75bf770c20c823e8108705792f99cd4a6f/uvloop-0.20.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aea15c78e0d9ad6555ed201344ae36db5c63d428818b4b2a42842b3870127c00", size = 4115980 }, +] + +[[package]] +name = "watchdog" +version = "5.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/48/a86139aaeab2db0a2482676f64798d8ac4d2dbb457523f50ab37bf02ce2c/watchdog-5.0.3.tar.gz", hash = "sha256:108f42a7f0345042a854d4d0ad0834b741d421330d5f575b81cb27b883500176", size = 129556 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/34/946f08602f8b8e6af45bc725e4a8013975a34883ab5570bd0d827a4c9829/watchdog-5.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f01f4a3565a387080dc49bdd1fefe4ecc77f894991b88ef927edbfa45eb10818", size = 96650 }, + { url = "https://files.pythonhosted.org/packages/96/2b/b84e35d49e8b0bad77e5d086fc1e2c6c833bbfe74d53144cfe8b26117eff/watchdog-5.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:91b522adc25614cdeaf91f7897800b82c13b4b8ac68a42ca959f992f6990c490", size = 88653 }, + { url = "https://files.pythonhosted.org/packages/d5/3f/41b5d77c10f450b79921c17b7d0b416616048867bfe63acaa072a619a0cb/watchdog-5.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d52db5beb5e476e6853da2e2d24dbbbed6797b449c8bf7ea118a4ee0d2c9040e", size = 89286 }, + { url = "https://files.pythonhosted.org/packages/1c/9b/8b206a928c188fdeb7b12e1c795199534cd44bdef223b8470129016009dd/watchdog-5.0.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:94d11b07c64f63f49876e0ab8042ae034674c8653bfcdaa8c4b32e71cfff87e8", size = 96739 }, + { url = "https://files.pythonhosted.org/packages/e1/26/129ca9cd0f8016672f37000010c2fedc0b86816e894ebdc0af9bb04a6439/watchdog-5.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:349c9488e1d85d0a58e8cb14222d2c51cbc801ce11ac3936ab4c3af986536926", size = 88708 }, + { url = "https://files.pythonhosted.org/packages/8f/b3/5e10ec32f0c429cdb55b1369066d6e83faf9985b3a53a4e37bb5c5e29aa0/watchdog-5.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:53a3f10b62c2d569e260f96e8d966463dec1a50fa4f1b22aec69e3f91025060e", size = 89309 }, + { url = "https://files.pythonhosted.org/packages/54/c4/49af4ab00bcfb688e9962eace2edda07a2cf89b9699ea536da48e8585cff/watchdog-5.0.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:950f531ec6e03696a2414b6308f5c6ff9dab7821a768c9d5788b1314e9a46ca7", size = 96740 }, + { url = "https://files.pythonhosted.org/packages/96/a4/b24de77cc9ae424c1687c9d4fb15aa560d7d7b28ba559aca72f781d0202b/watchdog-5.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae6deb336cba5d71476caa029ceb6e88047fc1dc74b62b7c4012639c0b563906", size = 88711 }, + { url = "https://files.pythonhosted.org/packages/a4/71/3f2e9fe8403386b99d788868955b3a790f7a09721501a7e1eb58f514ffaa/watchdog-5.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1021223c08ba8d2d38d71ec1704496471ffd7be42cfb26b87cd5059323a389a1", size = 89319 }, + { url = "https://files.pythonhosted.org/packages/60/33/7cb71c9df9a77b6927ee5f48d25e1de5562ce0fa7e0c56dcf2b0472e64a2/watchdog-5.0.3-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dd021efa85970bd4824acacbb922066159d0f9e546389a4743d56919b6758b91", size = 79335 }, + { url = "https://files.pythonhosted.org/packages/f6/91/320bc1496cf951a3cf93a7ffd18a581f0792c304be963d943e0e608c2919/watchdog-5.0.3-py3-none-manylinux2014_armv7l.whl", hash = "sha256:78864cc8f23dbee55be34cc1494632a7ba30263951b5b2e8fc8286b95845f82c", size = 79334 }, + { url = "https://files.pythonhosted.org/packages/8b/2c/567c5e042ed667d3544c43d48a65cf853450a2d2a9089d9523a65f195e94/watchdog-5.0.3-py3-none-manylinux2014_i686.whl", hash = "sha256:1e9679245e3ea6498494b3028b90c7b25dbb2abe65c7d07423ecfc2d6218ff7c", size = 79333 }, + { url = "https://files.pythonhosted.org/packages/c3/f0/64059fe162ef3274662e67bbdea6c45b3cd53e846d5bd1365fcdc3dc1d15/watchdog-5.0.3-py3-none-manylinux2014_ppc64.whl", hash = "sha256:9413384f26b5d050b6978e6fcd0c1e7f0539be7a4f1a885061473c5deaa57221", size = 79334 }, + { url = "https://files.pythonhosted.org/packages/f6/d9/19b7d02965be2801e2d0f6f4bde23e4ae172620071b65430fa0c2f8441ac/watchdog-5.0.3-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:294b7a598974b8e2c6123d19ef15de9abcd282b0fbbdbc4d23dfa812959a9e05", size = 79333 }, + { url = "https://files.pythonhosted.org/packages/cb/a1/5393ac6d0b095d3a44946b09258e9b5f22cb2fb67bcfa419dd868478826c/watchdog-5.0.3-py3-none-manylinux2014_s390x.whl", hash = "sha256:26dd201857d702bdf9d78c273cafcab5871dd29343748524695cecffa44a8d97", size = 79332 }, + { url = "https://files.pythonhosted.org/packages/a0/58/edec25190b6403caf4426dd418234f2358a106634b7d6aa4aec6939b104f/watchdog-5.0.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:0f9332243355643d567697c3e3fa07330a1d1abf981611654a1f2bf2175612b7", size = 79334 }, + { url = "https://files.pythonhosted.org/packages/97/69/cfb2d17ba8aabc73be2e2d03c8c319b1f32053a02c4b571852983aa24ff2/watchdog-5.0.3-py3-none-win32.whl", hash = "sha256:c66f80ee5b602a9c7ab66e3c9f36026590a0902db3aea414d59a2f55188c1f49", size = 79320 }, + { url = "https://files.pythonhosted.org/packages/91/b4/2b5b59358dadfa2c8676322f955b6c22cde4937602f40490e2f7403e548e/watchdog-5.0.3-py3-none-win_amd64.whl", hash = "sha256:f00b4cf737f568be9665563347a910f8bdc76f88c2970121c86243c8cfdf90e9", size = 79325 }, + { url = "https://files.pythonhosted.org/packages/38/b8/0aa69337651b3005f161f7f494e59188a1d8d94171666900d26d29d10f69/watchdog-5.0.3-py3-none-win_ia64.whl", hash = "sha256:49f4d36cb315c25ea0d946e018c01bb028048023b9e103d3d3943f58e109dd45", size = 79324 }, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774 }, +] + +[[package]] +name = "websockets" +version = "13.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e2/73/9223dbc7be3dcaf2a7bbf756c351ec8da04b1fa573edaf545b95f6b0c7fd/websockets-13.1.tar.gz", hash = "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878", size = 158549 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/f0/cf0b8a30d86b49e267ac84addbebbc7a48a6e7bb7c19db80f62411452311/websockets-13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19", size = 157813 }, + { url = "https://files.pythonhosted.org/packages/bf/e7/22285852502e33071a8cf0ac814f8988480ec6db4754e067b8b9d0e92498/websockets-13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5", size = 155469 }, + { url = "https://files.pythonhosted.org/packages/68/d4/c8c7c1e5b40ee03c5cc235955b0fb1ec90e7e37685a5f69229ad4708dcde/websockets-13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd", size = 155717 }, + { url = "https://files.pythonhosted.org/packages/c9/e4/c50999b9b848b1332b07c7fd8886179ac395cb766fda62725d1539e7bc6c/websockets-13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02", size = 165379 }, + { url = "https://files.pythonhosted.org/packages/bc/49/4a4ad8c072f18fd79ab127650e47b160571aacfc30b110ee305ba25fffc9/websockets-13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7", size = 164376 }, + { url = "https://files.pythonhosted.org/packages/af/9b/8c06d425a1d5a74fd764dd793edd02be18cf6fc3b1ccd1f29244ba132dc0/websockets-13.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096", size = 164753 }, + { url = "https://files.pythonhosted.org/packages/d5/5b/0acb5815095ff800b579ffc38b13ab1b915b317915023748812d24e0c1ac/websockets-13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084", size = 165051 }, + { url = "https://files.pythonhosted.org/packages/30/93/c3891c20114eacb1af09dedfcc620c65c397f4fd80a7009cd12d9457f7f5/websockets-13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3", size = 164489 }, + { url = "https://files.pythonhosted.org/packages/28/09/af9e19885539759efa2e2cd29b8b3f9eecef7ecefea40d46612f12138b36/websockets-13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9", size = 164438 }, + { url = "https://files.pythonhosted.org/packages/b6/08/6f38b8e625b3d93de731f1d248cc1493327f16cb45b9645b3e791782cff0/websockets-13.1-cp311-cp311-win32.whl", hash = "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f", size = 158710 }, + { url = "https://files.pythonhosted.org/packages/fb/39/ec8832ecb9bb04a8d318149005ed8cee0ba4e0205835da99e0aa497a091f/websockets-13.1-cp311-cp311-win_amd64.whl", hash = "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557", size = 159137 }, + { url = "https://files.pythonhosted.org/packages/df/46/c426282f543b3c0296cf964aa5a7bb17e984f58dde23460c3d39b3148fcf/websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc", size = 157821 }, + { url = "https://files.pythonhosted.org/packages/aa/85/22529867010baac258da7c45848f9415e6cf37fef00a43856627806ffd04/websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49", size = 155480 }, + { url = "https://files.pythonhosted.org/packages/29/2c/bdb339bfbde0119a6e84af43ebf6275278698a2241c2719afc0d8b0bdbf2/websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd", size = 155715 }, + { url = "https://files.pythonhosted.org/packages/9f/d0/8612029ea04c5c22bf7af2fd3d63876c4eaeef9b97e86c11972a43aa0e6c/websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0", size = 165647 }, + { url = "https://files.pythonhosted.org/packages/56/04/1681ed516fa19ca9083f26d3f3a302257e0911ba75009533ed60fbb7b8d1/websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6", size = 164592 }, + { url = "https://files.pythonhosted.org/packages/38/6f/a96417a49c0ed132bb6087e8e39a37db851c70974f5c724a4b2a70066996/websockets-13.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9", size = 165012 }, + { url = "https://files.pythonhosted.org/packages/40/8b/fccf294919a1b37d190e86042e1a907b8f66cff2b61e9befdbce03783e25/websockets-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68", size = 165311 }, + { url = "https://files.pythonhosted.org/packages/c1/61/f8615cf7ce5fe538476ab6b4defff52beb7262ff8a73d5ef386322d9761d/websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14", size = 164692 }, + { url = "https://files.pythonhosted.org/packages/5c/f1/a29dd6046d3a722d26f182b783a7997d25298873a14028c4760347974ea3/websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf", size = 164686 }, + { url = "https://files.pythonhosted.org/packages/0f/99/ab1cdb282f7e595391226f03f9b498f52109d25a2ba03832e21614967dfa/websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c", size = 158712 }, + { url = "https://files.pythonhosted.org/packages/46/93/e19160db48b5581feac8468330aa11b7292880a94a37d7030478596cc14e/websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3", size = 159145 }, + { url = "https://files.pythonhosted.org/packages/51/20/2b99ca918e1cbd33c53db2cace5f0c0cd8296fc77558e1908799c712e1cd/websockets-13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6", size = 157828 }, + { url = "https://files.pythonhosted.org/packages/b8/47/0932a71d3d9c0e9483174f60713c84cee58d62839a143f21a2bcdbd2d205/websockets-13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708", size = 155487 }, + { url = "https://files.pythonhosted.org/packages/a9/60/f1711eb59ac7a6c5e98e5637fef5302f45b6f76a2c9d64fd83bbb341377a/websockets-13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418", size = 155721 }, + { url = "https://files.pythonhosted.org/packages/6a/e6/ba9a8db7f9d9b0e5f829cf626ff32677f39824968317223605a6b419d445/websockets-13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a", size = 165609 }, + { url = "https://files.pythonhosted.org/packages/c1/22/4ec80f1b9c27a0aebd84ccd857252eda8418ab9681eb571b37ca4c5e1305/websockets-13.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f", size = 164556 }, + { url = "https://files.pythonhosted.org/packages/27/ac/35f423cb6bb15600438db80755609d27eda36d4c0b3c9d745ea12766c45e/websockets-13.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5", size = 164993 }, + { url = "https://files.pythonhosted.org/packages/31/4e/98db4fd267f8be9e52e86b6ee4e9aa7c42b83452ea0ea0672f176224b977/websockets-13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135", size = 165360 }, + { url = "https://files.pythonhosted.org/packages/3f/15/3f0de7cda70ffc94b7e7024544072bc5b26e2c1eb36545291abb755d8cdb/websockets-13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2", size = 164745 }, + { url = "https://files.pythonhosted.org/packages/a1/6e/66b6b756aebbd680b934c8bdbb6dcb9ce45aad72cde5f8a7208dbb00dd36/websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6", size = 164732 }, + { url = "https://files.pythonhosted.org/packages/35/c6/12e3aab52c11aeb289e3dbbc05929e7a9d90d7a9173958477d3ef4f8ce2d/websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d", size = 158709 }, + { url = "https://files.pythonhosted.org/packages/41/d8/63d6194aae711d7263df4498200c690a9c39fb437ede10f3e157a6343e0d/websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2", size = 159144 }, + { url = "https://files.pythonhosted.org/packages/56/27/96a5cd2626d11c8280656c6c71d8ab50fe006490ef9971ccd154e0c42cd2/websockets-13.1-py3-none-any.whl", hash = "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f", size = 152134 }, +] + +[[package]] +name = "werkzeug" +version = "3.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0f/e2/6dbcaab07560909ff8f654d3a2e5a60552d937c909455211b1b36d7101dc/werkzeug-3.0.4.tar.gz", hash = "sha256:34f2371506b250df4d4f84bfe7b0921e4762525762bbd936614909fe25cd7306", size = 803966 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/84/997bbf7c2bf2dc3f09565c6d0b4959fefe5355c18c4096cfd26d83e0785b/werkzeug-3.0.4-py3-none-any.whl", hash = "sha256:02c9eb92b7d6c06f31a782811505d2157837cea66aaede3e217c7c27c039476c", size = 227554 }, +] + +[[package]] +name = "yarl" +version = "1.9.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e0/ad/bedcdccbcbf91363fd425a948994f3340924145c2bc8ccb296f4a1e52c28/yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf", size = 141869 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/65/4c7f3676209a569405c9f0f492df2bc3a387c253f5d906e36944fdd12277/yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099", size = 132836 }, + { url = "https://files.pythonhosted.org/packages/3b/c5/81e3dbf5271ab1510860d2ae7a704ef43f93f7cb9326bf7ebb1949a7260b/yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c", size = 83215 }, + { url = "https://files.pythonhosted.org/packages/20/3d/7dabf580dfc0b588e48830486b488858122b10a61f33325e0d7cf1d6180b/yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0", size = 81237 }, + { url = "https://files.pythonhosted.org/packages/38/45/7c669999f5d350f4f8f74369b94e0f6705918eee18e38610bfe44af93d4f/yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525", size = 324181 }, + { url = "https://files.pythonhosted.org/packages/50/49/aa04effe2876cced8867bf9d89b620acf02b733c62adfe22a8218c35d70b/yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8", size = 339412 }, + { url = "https://files.pythonhosted.org/packages/7d/95/4310771fb9c71599d8466f43347ac18fafd501621e65b93f4f4f16899b1d/yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9", size = 337973 }, + { url = "https://files.pythonhosted.org/packages/9f/ea/94ad7d8299df89844e666e4aa8a0e9b88e02416cd6a7dd97969e9eae5212/yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42", size = 328126 }, + { url = "https://files.pythonhosted.org/packages/6d/be/9d4885e2725f5860833547c9e4934b6e0f44a355b24ffc37957264761e3e/yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe", size = 316677 }, + { url = "https://files.pythonhosted.org/packages/4a/70/5c744d67cad3d093e233cb02f37f2830cb89abfcbb7ad5b5af00ff21d14d/yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce", size = 324243 }, + { url = "https://files.pythonhosted.org/packages/c2/80/8b38d8fed958ac37afb8b81a54bf4f767b107e2c2004dab165edb58fc51b/yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9", size = 318099 }, + { url = "https://files.pythonhosted.org/packages/59/50/715bbc7bda65291f9295e757f67854206f4d8be9746d39187724919ac14d/yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572", size = 334924 }, + { url = "https://files.pythonhosted.org/packages/a8/af/ca9962488027576d7162878a1864cbb1275d298af986ce96bdfd4807d7b2/yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958", size = 335060 }, + { url = "https://files.pythonhosted.org/packages/28/c7/249a3a903d500ca7369eb542e2847a14f12f249638dcc10371db50cd17ff/yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98", size = 326689 }, + { url = "https://files.pythonhosted.org/packages/ec/0c/f02dd0b875a7a460f95dc7cf18983ed43c693283d6ab92e0ad71b9e0de8f/yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31", size = 70407 }, + { url = "https://files.pythonhosted.org/packages/27/41/945ae9a80590e4fb0be166863c6e63d75e4b35789fa3a61ff1dbdcdc220f/yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1", size = 76719 }, + { url = "https://files.pythonhosted.org/packages/7b/cd/a921122610dedfed94e494af18e85aae23e93274c00ca464cfc591c8f4fb/yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81", size = 129561 }, + { url = "https://files.pythonhosted.org/packages/7c/a0/887c93020c788f249c24eaab288c46e5fed4d2846080eaf28ed3afc36e8d/yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142", size = 81595 }, + { url = "https://files.pythonhosted.org/packages/54/99/ed3c92c38f421ba6e36caf6aa91c34118771d252dce800118fa2f44d7962/yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074", size = 79400 }, + { url = "https://files.pythonhosted.org/packages/ea/45/65801be625ef939acc8b714cf86d4a198c0646e80dc8970359d080c47204/yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129", size = 317397 }, + { url = "https://files.pythonhosted.org/packages/06/91/9696601a8ba674c8f0c15035cc9e94ca31f541330364adcfd5a399f598bf/yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2", size = 327246 }, + { url = "https://files.pythonhosted.org/packages/da/3e/bf25177b3618889bf067aacf01ef54e910cd569d14e2f84f5e7bec23bb82/yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78", size = 327321 }, + { url = "https://files.pythonhosted.org/packages/28/1c/bdb3411467b805737dd2720b85fd082e49f59bf0cc12dc1dfcc80ab3d274/yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4", size = 322424 }, + { url = "https://files.pythonhosted.org/packages/41/e9/53bc89f039df2824a524a2aa03ee0bfb8f0585b08949e7521f5eab607085/yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0", size = 310868 }, + { url = "https://files.pythonhosted.org/packages/79/cd/a78c3b0304a4a970b5ae3993f4f5f649443bc8bfa5622f244aed44c810ed/yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51", size = 323452 }, + { url = "https://files.pythonhosted.org/packages/2e/5e/1c78eb05ae0efae08498fd7ab939435a29f12c7f161732e7fe327e5b8ca1/yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff", size = 313554 }, + { url = "https://files.pythonhosted.org/packages/04/e0/0029563a8434472697aebb269fdd2ffc8a19e3840add1d5fa169ec7c56e3/yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7", size = 331029 }, + { url = "https://files.pythonhosted.org/packages/de/1b/7e6b1ad42ccc0ed059066a7ae2b6fd4bce67795d109a99ccce52e9824e96/yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc", size = 333839 }, + { url = "https://files.pythonhosted.org/packages/85/8a/c364d6e2eeb4e128a5ee9a346fc3a09aa76739c0c4e2a7305989b54f174b/yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10", size = 328251 }, + { url = "https://files.pythonhosted.org/packages/ec/9d/0da94b33b9fb89041e10f95a14a55b0fef36c60b6a1d5ff85a0c2ecb1a97/yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7", size = 70195 }, + { url = "https://files.pythonhosted.org/packages/c5/f4/2fdc5a11503bc61818243653d836061c9ce0370e2dd9ac5917258a007675/yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984", size = 76397 }, + { url = "https://files.pythonhosted.org/packages/4d/05/4d79198ae568a92159de0f89e710a8d19e3fa267b719a236582eee921f4a/yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad", size = 31638 }, +] + +[[package]] +name = "zipp" +version = "3.20.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/8b/1239a3ef43a0d0ebdca623fb6413bc7702c321400c5fdd574f0b7aa0fbb4/zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b", size = 23848 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/9e/c96f7a4cd0bf5625bb409b7e61e99b1130dc63a98cb8b24aeabae62d43e8/zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064", size = 8988 }, +] -- 2.45.3 From 9fb796d7f2cf902049a3671c9051d13e44125b39 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 21 Oct 2024 16:53:28 -0400 Subject: [PATCH 355/376] remove poetry file and update workflow file to use correct meli secret --- .forgejo/workflows/workflow.yaml | 2 +- pyproject.toml | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index 600988e..5e44ea5 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -65,7 +65,7 @@ jobs: npx -p "@getmeli/cli" meli upload ./site \ --url "https://pages.coastalcommits.com" \ --site "${{ vars.MELI_SITE_ID }}" \ - --token "${{ secrets.MELI_SECRET }}" \ + --token "${{ secrets.MELI_TOKEN }}" \ --release "$CI_ACTION_REF_NAME_SLUG/${{ env.GITHUB_SHA }}" \ --branch "$CI_ACTION_REF_NAME_SLUG" diff --git a/pyproject.toml b/pyproject.toml index 0480d5d..9681d55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,12 +2,10 @@ name = "seacogs" version = "0.1.0" description = "My assorted cogs for Red-DiscordBot." -license = "MPL 2" +authors = [{name = "cswimr", email = "seaswimmerthefsh@gmail.com"}] +license = {file="LICENSE"} readme = "README.md" requires-python = ">=3.11" -authors = [ - { name = "cswimr", email = "seaswimmerthefsh@gmail.com" }, -] dependencies = [ "aiosqlite>=0.20.0", "beautifulsoup4>=4.12.3", -- 2.45.3 From 90e04cb70a29e354a2479940e19f1d1255178ce3 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 1 Nov 2024 11:21:38 -0400 Subject: [PATCH 356/376] chore(repo): update issue templates --- .forgejo/ISSUE_TEMPLATE/bug_report.yaml | 2 -- .forgejo/ISSUE_TEMPLATE/suggestion.yaml | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.forgejo/ISSUE_TEMPLATE/bug_report.yaml b/.forgejo/ISSUE_TEMPLATE/bug_report.yaml index 7fa4c8d..86bb98c 100644 --- a/.forgejo/ISSUE_TEMPLATE/bug_report.yaml +++ b/.forgejo/ISSUE_TEMPLATE/bug_report.yaml @@ -1,8 +1,6 @@ name: Bug Report about: File a bug report -title: "[Cog Name] " labels: [bug] -ref: master body: - type: markdown attributes: diff --git a/.forgejo/ISSUE_TEMPLATE/suggestion.yaml b/.forgejo/ISSUE_TEMPLATE/suggestion.yaml index 7c70ad3..f6c1fb8 100644 --- a/.forgejo/ISSUE_TEMPLATE/suggestion.yaml +++ b/.forgejo/ISSUE_TEMPLATE/suggestion.yaml @@ -1,8 +1,6 @@ name: Suggestion about: Trying to suggest something for SeaCogs? Use this. -title: "[Cog Name] " -labels: enhancement -ref: master +labels: [enhancement] body: - type: markdown attributes: @@ -13,7 +11,7 @@ body: attributes: label: What cog is your feature request for? description: Specify the cog within the repository. - placeholder: E.g., ModerationCog + placeholder: E.g., Pterodactyl validations: required: true - type: textarea -- 2.45.3 From 523a3a1e8924d4a30e3841f1cca9e5a2090c34d5 Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 20 Nov 2024 12:22:57 -0500 Subject: [PATCH 357/376] chore(repo): add nix flake dev-shell for development environment --- .envrc | 10 ++ .gitignore | 2 + flake.lock | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 50 ++++++++++ 4 files changed, 327 insertions(+) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..dc25ec7 --- /dev/null +++ b/.envrc @@ -0,0 +1,10 @@ +if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs=" +fi + +watch_file flake.nix +watch_file flake.lock +if ! use flake . --no-pure-eval +then + echo "devenv could not be built. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2 +fi diff --git a/.gitignore b/.gitignore index 3f0e8b8..2489db9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ site .venv __pycache__ +.direnv +.devenv diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..a0a5c22 --- /dev/null +++ b/flake.lock @@ -0,0 +1,265 @@ +{ + "nodes": { + "cachix": { + "inputs": { + "devenv": [ + "devenv" + ], + "flake-compat": [ + "devenv" + ], + "git-hooks": [ + "devenv" + ], + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1728672398, + "narHash": "sha256-KxuGSoVUFnQLB2ZcYODW7AVPAh9JqRlD5BrfsC/Q4qs=", + "owner": "cachix", + "repo": "cachix", + "rev": "aac51f698309fd0f381149214b7eee213c66ef0a", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "latest", + "repo": "cachix", + "type": "github" + } + }, + "devenv": { + "inputs": { + "cachix": "cachix", + "flake-compat": "flake-compat", + "git-hooks": "git-hooks", + "nix": "nix", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1732121232, + "narHash": "sha256-CmJt7aeSCJnJYGtYpyslRI+pC28RPVD43PD/7kkIVuM=", + "owner": "cachix", + "repo": "devenv", + "rev": "6ff1e5f92c0d74bbb12f7454a239ca2f02e05ea1", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "devenv" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-stable": [ + "devenv" + ] + }, + "locked": { + "lastModified": 1730302582, + "narHash": "sha256-W1MIJpADXQCgosJZT8qBYLRuZls2KSiKdpnTVdKBuvU=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "af8a16fe5c264f5e9e18bcee2859b40a656876cf", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "devenv", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "libgit2": { + "flake": false, + "locked": { + "lastModified": 1697646580, + "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", + "type": "github" + }, + "original": { + "owner": "libgit2", + "repo": "libgit2", + "type": "github" + } + }, + "nix": { + "inputs": { + "flake-compat": [ + "devenv" + ], + "flake-parts": "flake-parts", + "libgit2": "libgit2", + "nixpkgs": "nixpkgs_2", + "nixpkgs-23-11": [ + "devenv" + ], + "nixpkgs-regression": [ + "devenv" + ], + "pre-commit-hooks": [ + "devenv" + ] + }, + "locked": { + "lastModified": 1727438425, + "narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=", + "owner": "domenkozar", + "repo": "nix", + "rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.24", + "repo": "nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1730531603, + "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1717432640, + "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1731676054, + "narHash": "sha256-OZiZ3m8SCMfh3B6bfGC/Bm4x3qc1m2SVEAlkV6iY7Yg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5e4fbfb6b3de1aa2872b76d49fafc942626e2add", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs_3", + "systems": "systems" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..3ec26c4 --- /dev/null +++ b/flake.nix @@ -0,0 +1,50 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + systems.url = "github:nix-systems/default"; + devenv.url = "github:cachix/devenv"; + devenv.inputs.nixpkgs.follows = "nixpkgs"; + }; + + nixConfig = { + extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="; + extra-substituters = "https://devenv.cachix.org"; + }; + + outputs = { self, nixpkgs, devenv, systems, ... } @ inputs: + let + forEachSystem = nixpkgs.lib.genAttrs (import systems); + in + { + packages = forEachSystem (system: { + devenv-up = self.devShells.${system}.default.config.procfileScript; + devenv-test = self.devShells.${system}.default.config.test; + }); + + devShells = forEachSystem + (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + default = devenv.lib.mkShell { + inherit inputs pkgs; + modules = [ + { + languages.python = { + enable = true; + package = pkgs.python311; + uv = { + enable = true; + sync = { + enable = true; + allExtras = true; + }; + }; + }; + } + ]; + }; + }); + }; +} -- 2.45.3 From ec08130f998192eeb898ee65cb45ead46443abaa Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 20 Nov 2024 12:27:59 -0500 Subject: [PATCH 358/376] chore(repo): use `nixpkgs-python` to get python version instead of setting `languages.python.package` --- flake.lock | 38 ++++++++++++++++++++++++++++++++++++++ flake.nix | 4 +++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index a0a5c22..5de0f7a 100644 --- a/flake.lock +++ b/flake.lock @@ -68,6 +68,22 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": [ @@ -205,6 +221,27 @@ "type": "github" } }, + "nixpkgs-python": { + "inputs": { + "flake-compat": "flake-compat_2", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1730716553, + "narHash": "sha256-n4cibCp/ggDlSacCTnP8dVnywclQKYcHy6PRfe35Hk0=", + "owner": "cachix", + "repo": "nixpkgs-python", + "rev": "8fcdb8ec34a1c2bae3f5326873a41b310e948ccc", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "nixpkgs-python", + "type": "github" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1717432640, @@ -241,6 +278,7 @@ "inputs": { "devenv": "devenv", "nixpkgs": "nixpkgs_3", + "nixpkgs-python": "nixpkgs-python", "systems": "systems" } }, diff --git a/flake.nix b/flake.nix index 3ec26c4..f0ed09f 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,8 @@ { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + nixpkgs-python.url = "github:cachix/nixpkgs-python"; + nixpkgs-python.inputs = { nixpkgs.follows = "nixpkgs"; }; systems.url = "github:nix-systems/default"; devenv.url = "github:cachix/devenv"; devenv.inputs.nixpkgs.follows = "nixpkgs"; @@ -33,7 +35,7 @@ { languages.python = { enable = true; - package = pkgs.python311; + version = "3.11"; uv = { enable = true; sync = { -- 2.45.3 From 4d79320b39bf7f1e37b296217708e47c07adb96b Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 20 Nov 2024 12:33:59 -0500 Subject: [PATCH 359/376] chore(repo): flake formatting --- flake.nix | 52 +++++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/flake.nix b/flake.nix index f0ed09f..224293f 100644 --- a/flake.nix +++ b/flake.nix @@ -9,44 +9,38 @@ }; nixConfig = { - extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="; + extra-trusted-public-keys = + "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="; extra-substituters = "https://devenv.cachix.org"; }; - outputs = { self, nixpkgs, devenv, systems, ... } @ inputs: - let - forEachSystem = nixpkgs.lib.genAttrs (import systems); - in - { + outputs = { self, nixpkgs, devenv, systems, ... }@inputs: + let forEachSystem = nixpkgs.lib.genAttrs (import systems); + in { packages = forEachSystem (system: { devenv-up = self.devShells.${system}.default.config.procfileScript; devenv-test = self.devShells.${system}.default.config.test; }); - devShells = forEachSystem - (system: - let - pkgs = nixpkgs.legacyPackages.${system}; - in - { - default = devenv.lib.mkShell { - inherit inputs pkgs; - modules = [ - { - languages.python = { + devShells = forEachSystem (system: + let pkgs = nixpkgs.legacyPackages.${system}; + in { + default = devenv.lib.mkShell { + inherit inputs pkgs; + modules = [{ + languages.python = { + enable = true; + version = "3.11"; + uv = { + enable = true; + sync = { enable = true; - version = "3.11"; - uv = { - enable = true; - sync = { - enable = true; - allExtras = true; - }; - }; + allExtras = true; }; - } - ]; - }; - }); + }; + }; + }]; + }; + }); }; } -- 2.45.3 From 470b4d86d7b8237668ca8858408cef934cd0ec75 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 27 Dec 2024 10:51:43 -0500 Subject: [PATCH 360/376] Add renovate.json --- renovate.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..49d2467 --- /dev/null +++ b/renovate.json @@ -0,0 +1,17 @@ +{ + "extends": [ + "config:best-practices" + ], + "packageRules": [ + { + "matchUpdateTypes": [ + "minor", + "patch", + "pin", + "digest" + ], + "automerge": false + } + ], + "osvVulnerabilityAlerts": true +} \ No newline at end of file -- 2.45.3 From 1a78475bc68e5e68a6a214e68f62d64591d7e718 Mon Sep 17 00:00:00 2001 From: CoastalCommits-Renovate-Bot Date: Fri, 27 Dec 2024 19:48:58 +0000 Subject: [PATCH 361/376] chore(deps): update actions/checkout action to v4 --- .forgejo/workflows/workflow.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index 5e44ea5..288d1be 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -10,7 +10,7 @@ jobs: container: www.coastalcommits.com/cswimr/actions:uv steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Install python run: uv python install 3.11 @@ -32,7 +32,7 @@ jobs: container: www.coastalcommits.com/cswimr/actions:docs steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: fetch-depth: 0 -- 2.45.3 From 6e0b13bb20431c71c472eb38873878fc892fc271 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 27 Dec 2024 15:08:48 -0500 Subject: [PATCH 362/376] Update renovate.json --- renovate.json | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/renovate.json b/renovate.json index 49d2467..ccc5f45 100644 --- a/renovate.json +++ b/renovate.json @@ -1,17 +1,5 @@ { "extends": [ - "config:best-practices" - ], - "packageRules": [ - { - "matchUpdateTypes": [ - "minor", - "patch", - "pin", - "digest" - ], - "automerge": false - } - ], - "osvVulnerabilityAlerts": true + "local>CoastalCommits/renovate-config" + ] } \ No newline at end of file -- 2.45.3 From 719e040f2ed8e96dfa6bd41a5983fddaea3723fe Mon Sep 17 00:00:00 2001 From: Renovate Date: Fri, 27 Dec 2024 20:25:46 +0000 Subject: [PATCH 363/376] chore(deps): pin dependencies --- .forgejo/workflows/workflow.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index 288d1be..7bda2cb 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -7,7 +7,7 @@ jobs: lint: name: Lint Code (Ruff & Pylint) runs-on: docker - container: www.coastalcommits.com/cswimr/actions:uv + container: www.coastalcommits.com/cswimr/actions:uv@sha256:cd06ff5bd5b5883cdd5bb7c7f177957b402dafc25658bf06c3e464247d7bc8ef steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 @@ -29,7 +29,7 @@ jobs: name: Build Documentation (MkDocs) if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: docker - container: www.coastalcommits.com/cswimr/actions:docs + container: www.coastalcommits.com/cswimr/actions:docs@sha256:187a6986dba977a73a20ae30a89ceeba3d053e55b659dcc0ae7bab917571460d steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 -- 2.45.3 From ca78a197b954593d4d214ecaae3788de2704b710 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 27 Dec 2024 22:53:54 -0500 Subject: [PATCH 364/376] chore(repo): update renovate config --- renovate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index ccc5f45..5af45a8 100644 --- a/renovate.json +++ b/renovate.json @@ -1,5 +1,5 @@ { "extends": [ - "local>CoastalCommits/renovate-config" + "local>cc/renovate-config" ] } \ No newline at end of file -- 2.45.3 From 39d286b559c13c3efbc04bf13fa49777df33f508 Mon Sep 17 00:00:00 2001 From: Renovate Date: Wed, 22 Jan 2025 00:03:50 +0000 Subject: [PATCH 365/376] chore(deps): update www.coastalcommits.com/cswimr/actions:uv docker digest to 95493fb --- .forgejo/workflows/workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index 7bda2cb..bc7106d 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -7,7 +7,7 @@ jobs: lint: name: Lint Code (Ruff & Pylint) runs-on: docker - container: www.coastalcommits.com/cswimr/actions:uv@sha256:cd06ff5bd5b5883cdd5bb7c7f177957b402dafc25658bf06c3e464247d7bc8ef + container: www.coastalcommits.com/cswimr/actions:uv@sha256:95493fbfb15a62ce0db27a64901b763f95f87f0ce96e8318b790173079d7493c steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 -- 2.45.3 From 9637f5209fce7a6599acaba283ea6b138e8891d2 Mon Sep 17 00:00:00 2001 From: cswimr Date: Wed, 22 Jan 2025 08:57:20 -0600 Subject: [PATCH 366/376] style(repo): format nix flake --- flake.nix | 55 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/flake.nix b/flake.nix index 224293f..47dee2c 100644 --- a/flake.nix +++ b/flake.nix @@ -2,45 +2,62 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; nixpkgs-python.url = "github:cachix/nixpkgs-python"; - nixpkgs-python.inputs = { nixpkgs.follows = "nixpkgs"; }; + nixpkgs-python.inputs = { + nixpkgs.follows = "nixpkgs"; + }; systems.url = "github:nix-systems/default"; devenv.url = "github:cachix/devenv"; devenv.inputs.nixpkgs.follows = "nixpkgs"; }; nixConfig = { - extra-trusted-public-keys = - "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="; + extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="; extra-substituters = "https://devenv.cachix.org"; }; - outputs = { self, nixpkgs, devenv, systems, ... }@inputs: - let forEachSystem = nixpkgs.lib.genAttrs (import systems); - in { + outputs = + { + self, + nixpkgs, + devenv, + systems, + ... + }@inputs: + let + forEachSystem = nixpkgs.lib.genAttrs (import systems); + in + { packages = forEachSystem (system: { devenv-up = self.devShells.${system}.default.config.procfileScript; devenv-test = self.devShells.${system}.default.config.test; }); - devShells = forEachSystem (system: - let pkgs = nixpkgs.legacyPackages.${system}; - in { + devShells = forEachSystem ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { default = devenv.lib.mkShell { inherit inputs pkgs; - modules = [{ - languages.python = { - enable = true; - version = "3.11"; - uv = { + modules = [ + { + languages.python = { enable = true; - sync = { + version = "3.11"; + venv.enable = true; + uv = { enable = true; - allExtras = true; + sync = { + enable = true; + allExtras = true; + }; }; }; - }; - }]; + } + ]; }; - }); + } + ); }; } -- 2.45.3 From 65c35a422c11de5f8f6ee49106a85600228225f5 Mon Sep 17 00:00:00 2001 From: Renovate Date: Fri, 24 Jan 2025 00:11:43 +0000 Subject: [PATCH 367/376] chore(deps): update www.coastalcommits.com/cswimr/actions:uv docker digest to 211aaf7 --- .forgejo/workflows/workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index bc7106d..1f1df5b 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -7,7 +7,7 @@ jobs: lint: name: Lint Code (Ruff & Pylint) runs-on: docker - container: www.coastalcommits.com/cswimr/actions:uv@sha256:95493fbfb15a62ce0db27a64901b763f95f87f0ce96e8318b790173079d7493c + container: www.coastalcommits.com/cswimr/actions:uv@sha256:211aaf7d9ac98087579ebf9fab87a9122f51b2697e3a3649ac9f4bd3b03b8e5d steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 -- 2.45.3 From aa34b366088be20e8c6c38798b88696e48a08b81 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 24 Jan 2025 22:17:25 +0000 Subject: [PATCH 368/376] switch to devcontainers --- .devcontainer/Dockerfile | 34 ++++ .devcontainer/devcontainer.json | 35 ++++ .envrc | 10 -- .gitignore | 4 +- .vscode/settings.json | 12 ++ flake.lock | 303 -------------------------------- flake.nix | 63 ------- 7 files changed, 82 insertions(+), 379 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json delete mode 100644 .envrc create mode 100644 .vscode/settings.json delete mode 100644 flake.lock delete mode 100644 flake.nix diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..83ae86e --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,34 @@ +FROM ghcr.io/astral-sh/uv:0.5.24 AS uv +FROM python:3.11-slim AS python + +FROM mcr.microsoft.com/vscode/devcontainers/base:bookworm +LABEL repository="www.coastalcommits.com/cswimr/SeaCogs" +LABEL maintainer="cswimr " + +RUN apt-get update; \ + apt-get install -y --no-install-recommends \ + # Red-DiscordBot + build-essential \ + git \ + # PyNaCl + libsodium-dev \ + # CFFI + libffi-dev \ + # SSH repository support + openssh-client \ + # Cog dependencies + # Audio + openjdk-17-jre-headless \ + # PyLav + libaio1 \ + libaio-dev \ + # SeaUtils + dnsutils; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +COPY --from=uv --chown=vscode: /uv /uvx /bin/ +COPY --from=python --chown=vscode: /usr/local /usr/local + +RUN ln -s /usr/local/bin/python3.11 /usr/local/bin/python; \ + python --version diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..e480715 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,35 @@ +{ + "name": "Red-DiscordBot: SeaCogs", + "build": { + "context": "..", + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": [ + "charliermarsh.ruff", + "ms-azuretools.vscode-docker", + "ms-python.python", + "tekumara.typos-vscode", + "tamasfe.even-better-toml", + "redhat.vscode-yaml", + "DavidAnson.vscode-markdownlint", + "yy0931.vscode-sqlite3-editor", + "aaron-bond.better-comments", + "donjayamanne.githistory", + "eamodio.gitlens" + ] + } + }, + "containerEnv": { + "DISPLAY": "dummy", + "PYTHONUNBUFFERED": "True", + "UV_LINK_MODE": "copy", + "UV_PYTHON_PREFERENCE": "only-system", + "UV_PYTHON_DOWNLOADS": "never", + "PROJECT_DIR": "/workspaces/SeaCogs" + }, + "mounts": ["source=uv-persistent-data,target=/workspaces/SeaCogs/.data,type=volume"], + "postCreateCommand": "uv sync --frozen", + "remoteUser": "vscode" +} diff --git a/.envrc b/.envrc deleted file mode 100644 index dc25ec7..0000000 --- a/.envrc +++ /dev/null @@ -1,10 +0,0 @@ -if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs=" -fi - -watch_file flake.nix -watch_file flake.lock -if ! use flake . --no-pure-eval -then - echo "devenv could not be built. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2 -fi diff --git a/.gitignore b/.gitignore index 2489db9..d937fba 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,5 @@ .cache -.vscode site .venv +.data __pycache__ -.direnv -.devenv diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6808e51 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "[python]": { + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll": "explicit" + }, + "editor.defaultFormatter": "charliermarsh.ruff" + }, + "[json]": { + "editor.defaultFormatter": "vscode.json-language-features" + } +} diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 5de0f7a..0000000 --- a/flake.lock +++ /dev/null @@ -1,303 +0,0 @@ -{ - "nodes": { - "cachix": { - "inputs": { - "devenv": [ - "devenv" - ], - "flake-compat": [ - "devenv" - ], - "git-hooks": [ - "devenv" - ], - "nixpkgs": "nixpkgs" - }, - "locked": { - "lastModified": 1728672398, - "narHash": "sha256-KxuGSoVUFnQLB2ZcYODW7AVPAh9JqRlD5BrfsC/Q4qs=", - "owner": "cachix", - "repo": "cachix", - "rev": "aac51f698309fd0f381149214b7eee213c66ef0a", - "type": "github" - }, - "original": { - "owner": "cachix", - "ref": "latest", - "repo": "cachix", - "type": "github" - } - }, - "devenv": { - "inputs": { - "cachix": "cachix", - "flake-compat": "flake-compat", - "git-hooks": "git-hooks", - "nix": "nix", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1732121232, - "narHash": "sha256-CmJt7aeSCJnJYGtYpyslRI+pC28RPVD43PD/7kkIVuM=", - "owner": "cachix", - "repo": "devenv", - "rev": "6ff1e5f92c0d74bbb12f7454a239ca2f02e05ea1", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": [ - "devenv", - "nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1712014858, - "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "git-hooks": { - "inputs": { - "flake-compat": [ - "devenv" - ], - "gitignore": "gitignore", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-stable": [ - "devenv" - ] - }, - "locked": { - "lastModified": 1730302582, - "narHash": "sha256-W1MIJpADXQCgosJZT8qBYLRuZls2KSiKdpnTVdKBuvU=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "af8a16fe5c264f5e9e18bcee2859b40a656876cf", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "devenv", - "git-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "libgit2": { - "flake": false, - "locked": { - "lastModified": 1697646580, - "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", - "owner": "libgit2", - "repo": "libgit2", - "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", - "type": "github" - }, - "original": { - "owner": "libgit2", - "repo": "libgit2", - "type": "github" - } - }, - "nix": { - "inputs": { - "flake-compat": [ - "devenv" - ], - "flake-parts": "flake-parts", - "libgit2": "libgit2", - "nixpkgs": "nixpkgs_2", - "nixpkgs-23-11": [ - "devenv" - ], - "nixpkgs-regression": [ - "devenv" - ], - "pre-commit-hooks": [ - "devenv" - ] - }, - "locked": { - "lastModified": 1727438425, - "narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=", - "owner": "domenkozar", - "repo": "nix", - "rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546", - "type": "github" - }, - "original": { - "owner": "domenkozar", - "ref": "devenv-2.24", - "repo": "nix", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1730531603, - "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-python": { - "inputs": { - "flake-compat": "flake-compat_2", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1730716553, - "narHash": "sha256-n4cibCp/ggDlSacCTnP8dVnywclQKYcHy6PRfe35Hk0=", - "owner": "cachix", - "repo": "nixpkgs-python", - "rev": "8fcdb8ec34a1c2bae3f5326873a41b310e948ccc", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "nixpkgs-python", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1717432640, - "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "release-24.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { - "locked": { - "lastModified": 1731676054, - "narHash": "sha256-OZiZ3m8SCMfh3B6bfGC/Bm4x3qc1m2SVEAlkV6iY7Yg=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "5e4fbfb6b3de1aa2872b76d49fafc942626e2add", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "devenv": "devenv", - "nixpkgs": "nixpkgs_3", - "nixpkgs-python": "nixpkgs-python", - "systems": "systems" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 47dee2c..0000000 --- a/flake.nix +++ /dev/null @@ -1,63 +0,0 @@ -{ - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - nixpkgs-python.url = "github:cachix/nixpkgs-python"; - nixpkgs-python.inputs = { - nixpkgs.follows = "nixpkgs"; - }; - systems.url = "github:nix-systems/default"; - devenv.url = "github:cachix/devenv"; - devenv.inputs.nixpkgs.follows = "nixpkgs"; - }; - - nixConfig = { - extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="; - extra-substituters = "https://devenv.cachix.org"; - }; - - outputs = - { - self, - nixpkgs, - devenv, - systems, - ... - }@inputs: - let - forEachSystem = nixpkgs.lib.genAttrs (import systems); - in - { - packages = forEachSystem (system: { - devenv-up = self.devShells.${system}.default.config.procfileScript; - devenv-test = self.devShells.${system}.default.config.test; - }); - - devShells = forEachSystem ( - system: - let - pkgs = nixpkgs.legacyPackages.${system}; - in - { - default = devenv.lib.mkShell { - inherit inputs pkgs; - modules = [ - { - languages.python = { - enable = true; - version = "3.11"; - venv.enable = true; - uv = { - enable = true; - sync = { - enable = true; - allExtras = true; - }; - }; - }; - } - ]; - }; - } - ); - }; -} -- 2.45.3 From afc6735e90f2857afae429a59046f609ad28929c Mon Sep 17 00:00:00 2001 From: Renovate Date: Fri, 24 Jan 2025 22:53:48 +0000 Subject: [PATCH 369/376] chore(deps): pin dependencies --- .devcontainer/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 83ae86e..19d07ab 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,7 +1,7 @@ -FROM ghcr.io/astral-sh/uv:0.5.24 AS uv -FROM python:3.11-slim AS python +FROM ghcr.io/astral-sh/uv:0.5.24@sha256:2381d6aa60c326b71fd40023f921a0a3b8f91b14d5db6b90402e65a635053709 AS uv +FROM python:3.11-slim@sha256:6ed5bff4d7d377e2a27d9285553b8c21cfccc4f00881de1b24c9bc8d90016e82 AS python -FROM mcr.microsoft.com/vscode/devcontainers/base:bookworm +FROM mcr.microsoft.com/vscode/devcontainers/base:bookworm@sha256:6155a486f236fd5127b76af33086029d64f64cf49dd504accb6e5f949098eb7e LABEL repository="www.coastalcommits.com/cswimr/SeaCogs" LABEL maintainer="cswimr " -- 2.45.3 From 8aaa5bd33edc2f883a72c1021404abec3fa7f1e8 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 24 Jan 2025 23:05:15 +0000 Subject: [PATCH 370/376] chore(repo): update `red-discordbot` and add `pip` --- pyproject.toml | 3 +- uv.lock | 619 +++++++++++++++++++++++++++++++------------------ 2 files changed, 389 insertions(+), 233 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9681d55..2c40dee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,9 +14,10 @@ dependencies = [ "numpy>=2.1.2", "phx-class-registry>=5.0.0", "pillow>=10.4.0", + "pip>=24.3.1", "py-dactyl", "pydantic>=2.9.2", - "red-discordbot>=3.5.13", + "red-discordbot>=3.5.14", "websockets>=13.1", ] diff --git a/uv.lock b/uv.lock index 0570982..9056ced 100644 --- a/uv.lock +++ b/uv.lock @@ -154,11 +154,11 @@ wheels = [ [[package]] name = "attrs" -version = "24.2.0" +version = "24.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fc/0f/aafca9af9315aee06a89ffde799a10a582fe8de76c563ee80bbcdc08b3fb/attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346", size = 792678 } +sdist = { url = "https://files.pythonhosted.org/packages/48/c8/6260f8ccc11f0917360fc0da435c5c9c7504e3db174d5a12a1494887b045/attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff", size = 805984 } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2", size = 63001 }, + { url = "https://files.pythonhosted.org/packages/89/aa/ab0f7891a01eeb2d2e338ae8fecbe57fcebea1a24dbb64d45801bfab481d/attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308", size = 63397 }, ] [[package]] @@ -207,8 +207,14 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/80/d6/0bd38d758d1afa62a5524172f0b18626bb2392d717ff94806f741fcd5ee9/Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9", size = 2813051 }, { url = "https://files.pythonhosted.org/packages/14/56/48859dd5d129d7519e001f06dcfbb6e2cf6db92b2702c0c2ce7d97e086c1/Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265", size = 2938172 }, { url = "https://files.pythonhosted.org/packages/3d/77/a236d5f8cd9e9f4348da5acc75ab032ab1ab2c03cc8f430d24eea2672888/Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8", size = 2933023 }, + { url = "https://files.pythonhosted.org/packages/f1/87/3b283efc0f5cb35f7f84c0c240b1e1a1003a5e47141a4881bf87c86d0ce2/Brotli-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c247dd99d39e0338a604f8c2b3bc7061d5c2e9e2ac7ba9cc1be5a69cb6cd832f", size = 2935871 }, + { url = "https://files.pythonhosted.org/packages/f3/eb/2be4cc3e2141dc1a43ad4ca1875a72088229de38c68e842746b342667b2a/Brotli-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1b2c248cd517c222d89e74669a4adfa5577e06ab68771a529060cf5a156e9757", size = 2847784 }, + { url = "https://files.pythonhosted.org/packages/66/13/b58ddebfd35edde572ccefe6890cf7c493f0c319aad2a5badee134b4d8ec/Brotli-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2a24c50840d89ded6c9a8fdc7b6ed3692ed4e86f1c4a4a938e1e92def92933e0", size = 3034905 }, + { url = "https://files.pythonhosted.org/packages/84/9c/bc96b6c7db824998a49ed3b38e441a2cae9234da6fa11f6ed17e8cf4f147/Brotli-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f31859074d57b4639318523d6ffdca586ace54271a73ad23ad021acd807eb14b", size = 2929467 }, { url = "https://files.pythonhosted.org/packages/e7/71/8f161dee223c7ff7fea9d44893fba953ce97cf2c3c33f78ba260a91bcff5/Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50", size = 333169 }, { url = "https://files.pythonhosted.org/packages/02/8a/fece0ee1057643cb2a5bbf59682de13f1725f8482b2c057d4e799d7ade75/Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1", size = 357253 }, + { url = "https://files.pythonhosted.org/packages/5c/d0/5373ae13b93fe00095a58efcbce837fd470ca39f703a235d2a999baadfbc/Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28", size = 815693 }, + { url = "https://files.pythonhosted.org/packages/8e/48/f6e1cdf86751300c288c1459724bfa6917a80e30dbfc326f92cea5d3683a/Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f", size = 422489 }, { url = "https://files.pythonhosted.org/packages/06/88/564958cedce636d0f1bed313381dfc4b4e3d3f6015a63dae6146e1b8c65c/Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", size = 873081 }, { url = "https://files.pythonhosted.org/packages/58/79/b7026a8bb65da9a6bb7d14329fd2bd48d2b7f86d7329d5cc8ddc6a90526f/Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", size = 446244 }, { url = "https://files.pythonhosted.org/packages/e5/18/c18c32ecea41b6c0004e15606e274006366fe19436b6adccc1ae7b2e50c2/Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", size = 2906505 }, @@ -219,8 +225,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/58/5c391b41ecfc4527d2cc3350719b02e87cb424ef8ba2023fb662f9bf743c/Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", size = 2814452 }, { url = "https://files.pythonhosted.org/packages/c7/4e/91b8256dfe99c407f174924b65a01f5305e303f486cc7a2e8a5d43c8bec3/Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", size = 2938751 }, { url = "https://files.pythonhosted.org/packages/5a/a6/e2a39a5d3b412938362bbbeba5af904092bf3f95b867b4a3eb856104074e/Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", size = 2933757 }, + { url = "https://files.pythonhosted.org/packages/13/f0/358354786280a509482e0e77c1a5459e439766597d280f28cb097642fc26/Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9", size = 2936146 }, + { url = "https://files.pythonhosted.org/packages/80/f7/daf538c1060d3a88266b80ecc1d1c98b79553b3f117a485653f17070ea2a/Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb", size = 2848055 }, + { url = "https://files.pythonhosted.org/packages/ad/cf/0eaa0585c4077d3c2d1edf322d8e97aabf317941d3a72d7b3ad8bce004b0/Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111", size = 3035102 }, + { url = "https://files.pythonhosted.org/packages/d8/63/1c1585b2aa554fe6dbce30f0c18bdbc877fa9a1bf5ff17677d9cca0ac122/Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839", size = 2930029 }, { url = "https://files.pythonhosted.org/packages/5f/3b/4e3fd1893eb3bbfef8e5a80d4508bec17a57bb92d586c85c12d28666bb13/Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", size = 333276 }, { url = "https://files.pythonhosted.org/packages/3d/d5/942051b45a9e883b5b6e98c041698b1eb2012d25e5948c58d6bf85b1bb43/Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", size = 357255 }, + { url = "https://files.pythonhosted.org/packages/0a/9f/fb37bb8ffc52a8da37b1c03c459a8cd55df7a57bdccd8831d500e994a0ca/Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5", size = 815681 }, + { url = "https://files.pythonhosted.org/packages/06/b3/dbd332a988586fefb0aa49c779f59f47cae76855c2d00f450364bb574cac/Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8", size = 422475 }, + { url = "https://files.pythonhosted.org/packages/bb/80/6aaddc2f63dbcf2d93c2d204e49c11a9ec93a8c7c63261e2b4bd35198283/Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f", size = 2906173 }, + { url = "https://files.pythonhosted.org/packages/ea/1d/e6ca79c96ff5b641df6097d299347507d39a9604bde8915e76bf026d6c77/Brotli-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648", size = 2943803 }, + { url = "https://files.pythonhosted.org/packages/ac/a3/d98d2472e0130b7dd3acdbb7f390d478123dbf62b7d32bda5c830a96116d/Brotli-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0", size = 2918946 }, + { url = "https://files.pythonhosted.org/packages/c4/a5/c69e6d272aee3e1423ed005d8915a7eaa0384c7de503da987f2d224d0721/Brotli-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089", size = 2845707 }, + { url = "https://files.pythonhosted.org/packages/58/9f/4149d38b52725afa39067350696c09526de0125ebfbaab5acc5af28b42ea/Brotli-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368", size = 2936231 }, + { url = "https://files.pythonhosted.org/packages/5a/5a/145de884285611838a16bebfdb060c231c52b8f84dfbe52b852a15780386/Brotli-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c", size = 2848157 }, + { url = "https://files.pythonhosted.org/packages/50/ae/408b6bfb8525dadebd3b3dd5b19d631da4f7d46420321db44cd99dcf2f2c/Brotli-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284", size = 3035122 }, + { url = "https://files.pythonhosted.org/packages/af/85/a94e5cfaa0ca449d8f91c3d6f78313ebf919a0dbd55a100c711c6e9655bc/Brotli-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7", size = 2930206 }, + { url = "https://files.pythonhosted.org/packages/c2/f0/a61d9262cd01351df22e57ad7c34f66794709acab13f34be2675f45bf89d/Brotli-1.1.0-cp313-cp313-win32.whl", hash = "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0", size = 333804 }, + { url = "https://files.pythonhosted.org/packages/7e/c1/ec214e9c94000d1c1974ec67ced1c970c148aa6b8d8373066123fc3dbf06/Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b", size = 358517 }, ] [[package]] @@ -361,14 +383,14 @@ wheels = [ [[package]] name = "click" -version = "8.1.7" +version = "8.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 }, + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, ] [[package]] @@ -462,41 +484,56 @@ wheels = [ [[package]] name = "frozenlist" -version = "1.4.1" +version = "1.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cf/3d/2102257e7acad73efc4a0c306ad3953f68c504c16982bbdfee3ad75d8085/frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b", size = 37820 } +sdist = { url = "https://files.pythonhosted.org/packages/8f/ed/0f4cec13a93c02c47ec32d81d11c0c1efbadf4a471e3f3ce7cad366cbbd3/frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", size = 39930 } wheels = [ - { url = "https://files.pythonhosted.org/packages/01/bc/8d33f2d84b9368da83e69e42720cff01c5e199b5a868ba4486189a4d8fa9/frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0", size = 97060 }, - { url = "https://files.pythonhosted.org/packages/af/b2/904500d6a162b98a70e510e743e7ea992241b4f9add2c8063bf666ca21df/frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49", size = 55347 }, - { url = "https://files.pythonhosted.org/packages/5b/9c/f12b69997d3891ddc0d7895999a00b0c6a67f66f79498c0e30f27876435d/frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced", size = 53374 }, - { url = "https://files.pythonhosted.org/packages/ac/6e/e0322317b7c600ba21dec224498c0c5959b2bce3865277a7c0badae340a9/frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0", size = 273288 }, - { url = "https://files.pythonhosted.org/packages/a7/76/180ee1b021568dad5b35b7678616c24519af130ed3fa1e0f1ed4014e0f93/frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106", size = 284737 }, - { url = "https://files.pythonhosted.org/packages/05/08/40159d706a6ed983c8aca51922a93fc69f3c27909e82c537dd4054032674/frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068", size = 280267 }, - { url = "https://files.pythonhosted.org/packages/e0/18/9f09f84934c2b2aa37d539a322267939770362d5495f37783440ca9c1b74/frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2", size = 258778 }, - { url = "https://files.pythonhosted.org/packages/b3/c9/0bc5ee7e1f5cc7358ab67da0b7dfe60fbd05c254cea5c6108e7d1ae28c63/frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19", size = 272276 }, - { url = "https://files.pythonhosted.org/packages/12/5d/147556b73a53ad4df6da8bbb50715a66ac75c491fdedac3eca8b0b915345/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82", size = 272424 }, - { url = "https://files.pythonhosted.org/packages/83/61/2087bbf24070b66090c0af922685f1d0596c24bb3f3b5223625bdeaf03ca/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec", size = 260881 }, - { url = "https://files.pythonhosted.org/packages/a8/be/a235bc937dd803258a370fe21b5aa2dd3e7bfe0287a186a4bec30c6cccd6/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a", size = 282327 }, - { url = "https://files.pythonhosted.org/packages/5d/e7/b2469e71f082948066b9382c7b908c22552cc705b960363c390d2e23f587/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74", size = 281502 }, - { url = "https://files.pythonhosted.org/packages/db/1b/6a5b970e55dffc1a7d0bb54f57b184b2a2a2ad0b7bca16a97ca26d73c5b5/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2", size = 272292 }, - { url = "https://files.pythonhosted.org/packages/1a/05/ebad68130e6b6eb9b287dacad08ea357c33849c74550c015b355b75cc714/frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17", size = 44446 }, - { url = "https://files.pythonhosted.org/packages/b3/21/c5aaffac47fd305d69df46cfbf118768cdf049a92ee6b0b5cb029d449dcf/frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825", size = 50459 }, - { url = "https://files.pythonhosted.org/packages/b4/db/4cf37556a735bcdb2582f2c3fa286aefde2322f92d3141e087b8aeb27177/frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae", size = 93937 }, - { url = "https://files.pythonhosted.org/packages/46/03/69eb64642ca8c05f30aa5931d6c55e50b43d0cd13256fdd01510a1f85221/frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb", size = 53656 }, - { url = "https://files.pythonhosted.org/packages/3f/ab/c543c13824a615955f57e082c8a5ee122d2d5368e80084f2834e6f4feced/frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b", size = 51868 }, - { url = "https://files.pythonhosted.org/packages/a9/b8/438cfd92be2a124da8259b13409224d9b19ef8f5a5b2507174fc7e7ea18f/frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86", size = 280652 }, - { url = "https://files.pythonhosted.org/packages/54/72/716a955521b97a25d48315c6c3653f981041ce7a17ff79f701298195bca3/frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480", size = 286739 }, - { url = "https://files.pythonhosted.org/packages/65/d8/934c08103637567084568e4d5b4219c1016c60b4d29353b1a5b3587827d6/frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09", size = 289447 }, - { url = "https://files.pythonhosted.org/packages/70/bb/d3b98d83ec6ef88f9bd63d77104a305d68a146fd63a683569ea44c3085f6/frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a", size = 265466 }, - { url = "https://files.pythonhosted.org/packages/0b/f2/b8158a0f06faefec33f4dff6345a575c18095a44e52d4f10c678c137d0e0/frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd", size = 281530 }, - { url = "https://files.pythonhosted.org/packages/ea/a2/20882c251e61be653764038ece62029bfb34bd5b842724fff32a5b7a2894/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6", size = 281295 }, - { url = "https://files.pythonhosted.org/packages/4c/f9/8894c05dc927af2a09663bdf31914d4fb5501653f240a5bbaf1e88cab1d3/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1", size = 268054 }, - { url = "https://files.pythonhosted.org/packages/37/ff/a613e58452b60166507d731812f3be253eb1229808e59980f0405d1eafbf/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b", size = 286904 }, - { url = "https://files.pythonhosted.org/packages/cc/6e/0091d785187f4c2020d5245796d04213f2261ad097e0c1cf35c44317d517/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e", size = 290754 }, - { url = "https://files.pythonhosted.org/packages/a5/c2/e42ad54bae8bcffee22d1e12a8ee6c7717f7d5b5019261a8c861854f4776/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8", size = 282602 }, - { url = "https://files.pythonhosted.org/packages/b6/61/56bad8cb94f0357c4bc134acc30822e90e203b5cb8ff82179947de90c17f/frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89", size = 44063 }, - { url = "https://files.pythonhosted.org/packages/3e/dc/96647994a013bc72f3d453abab18340b7f5e222b7b7291e3697ca1fcfbd5/frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5", size = 50452 }, - { url = "https://files.pythonhosted.org/packages/83/10/466fe96dae1bff622021ee687f68e5524d6392b0a2f80d05001cd3a451ba/frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7", size = 11552 }, + { url = "https://files.pythonhosted.org/packages/79/43/0bed28bf5eb1c9e4301003b74453b8e7aa85fb293b31dde352aac528dafc/frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30", size = 94987 }, + { url = "https://files.pythonhosted.org/packages/bb/bf/b74e38f09a246e8abbe1e90eb65787ed745ccab6eaa58b9c9308e052323d/frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5", size = 54584 }, + { url = "https://files.pythonhosted.org/packages/2c/31/ab01375682f14f7613a1ade30149f684c84f9b8823a4391ed950c8285656/frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778", size = 52499 }, + { url = "https://files.pythonhosted.org/packages/98/a8/d0ac0b9276e1404f58fec3ab6e90a4f76b778a49373ccaf6a563f100dfbc/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a", size = 276357 }, + { url = "https://files.pythonhosted.org/packages/ad/c9/c7761084fa822f07dac38ac29f841d4587570dd211e2262544aa0b791d21/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869", size = 287516 }, + { url = "https://files.pythonhosted.org/packages/a1/ff/cd7479e703c39df7bdab431798cef89dc75010d8aa0ca2514c5b9321db27/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d", size = 283131 }, + { url = "https://files.pythonhosted.org/packages/59/a0/370941beb47d237eca4fbf27e4e91389fd68699e6f4b0ebcc95da463835b/frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45", size = 261320 }, + { url = "https://files.pythonhosted.org/packages/b8/5f/c10123e8d64867bc9b4f2f510a32042a306ff5fcd7e2e09e5ae5100ee333/frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d", size = 274877 }, + { url = "https://files.pythonhosted.org/packages/fa/79/38c505601ae29d4348f21706c5d89755ceded02a745016ba2f58bd5f1ea6/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3", size = 269592 }, + { url = "https://files.pythonhosted.org/packages/19/e2/39f3a53191b8204ba9f0bb574b926b73dd2efba2a2b9d2d730517e8f7622/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a", size = 265934 }, + { url = "https://files.pythonhosted.org/packages/d5/c9/3075eb7f7f3a91f1a6b00284af4de0a65a9ae47084930916f5528144c9dd/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9", size = 283859 }, + { url = "https://files.pythonhosted.org/packages/05/f5/549f44d314c29408b962fa2b0e69a1a67c59379fb143b92a0a065ffd1f0f/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2", size = 287560 }, + { url = "https://files.pythonhosted.org/packages/9d/f8/cb09b3c24a3eac02c4c07a9558e11e9e244fb02bf62c85ac2106d1eb0c0b/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf", size = 277150 }, + { url = "https://files.pythonhosted.org/packages/37/48/38c2db3f54d1501e692d6fe058f45b6ad1b358d82cd19436efab80cfc965/frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942", size = 45244 }, + { url = "https://files.pythonhosted.org/packages/ca/8c/2ddffeb8b60a4bce3b196c32fcc30d8830d4615e7b492ec2071da801b8ad/frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d", size = 51634 }, + { url = "https://files.pythonhosted.org/packages/79/73/fa6d1a96ab7fd6e6d1c3500700963eab46813847f01ef0ccbaa726181dd5/frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", size = 94026 }, + { url = "https://files.pythonhosted.org/packages/ab/04/ea8bf62c8868b8eada363f20ff1b647cf2e93377a7b284d36062d21d81d1/frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", size = 54150 }, + { url = "https://files.pythonhosted.org/packages/d0/9a/8e479b482a6f2070b26bda572c5e6889bb3ba48977e81beea35b5ae13ece/frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", size = 51927 }, + { url = "https://files.pythonhosted.org/packages/e3/12/2aad87deb08a4e7ccfb33600871bbe8f0e08cb6d8224371387f3303654d7/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a", size = 282647 }, + { url = "https://files.pythonhosted.org/packages/77/f2/07f06b05d8a427ea0060a9cef6e63405ea9e0d761846b95ef3fb3be57111/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", size = 289052 }, + { url = "https://files.pythonhosted.org/packages/bd/9f/8bf45a2f1cd4aa401acd271b077989c9267ae8463e7c8b1eb0d3f561b65e/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", size = 291719 }, + { url = "https://files.pythonhosted.org/packages/41/d1/1f20fd05a6c42d3868709b7604c9f15538a29e4f734c694c6bcfc3d3b935/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", size = 267433 }, + { url = "https://files.pythonhosted.org/packages/af/f2/64b73a9bb86f5a89fb55450e97cd5c1f84a862d4ff90d9fd1a73ab0f64a5/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", size = 283591 }, + { url = "https://files.pythonhosted.org/packages/29/e2/ffbb1fae55a791fd6c2938dd9ea779509c977435ba3940b9f2e8dc9d5316/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", size = 273249 }, + { url = "https://files.pythonhosted.org/packages/2e/6e/008136a30798bb63618a114b9321b5971172a5abddff44a100c7edc5ad4f/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", size = 271075 }, + { url = "https://files.pythonhosted.org/packages/ae/f0/4e71e54a026b06724cec9b6c54f0b13a4e9e298cc8db0f82ec70e151f5ce/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", size = 285398 }, + { url = "https://files.pythonhosted.org/packages/4d/36/70ec246851478b1c0b59f11ef8ade9c482ff447c1363c2bd5fad45098b12/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", size = 294445 }, + { url = "https://files.pythonhosted.org/packages/37/e0/47f87544055b3349b633a03c4d94b405956cf2437f4ab46d0928b74b7526/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", size = 280569 }, + { url = "https://files.pythonhosted.org/packages/f9/7c/490133c160fb6b84ed374c266f42800e33b50c3bbab1652764e6e1fc498a/frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", size = 44721 }, + { url = "https://files.pythonhosted.org/packages/b1/56/4e45136ffc6bdbfa68c29ca56ef53783ef4c2fd395f7cbf99a2624aa9aaa/frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", size = 51329 }, + { url = "https://files.pythonhosted.org/packages/da/3b/915f0bca8a7ea04483622e84a9bd90033bab54bdf485479556c74fd5eaf5/frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953", size = 91538 }, + { url = "https://files.pythonhosted.org/packages/c7/d1/a7c98aad7e44afe5306a2b068434a5830f1470675f0e715abb86eb15f15b/frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0", size = 52849 }, + { url = "https://files.pythonhosted.org/packages/3a/c8/76f23bf9ab15d5f760eb48701909645f686f9c64fbb8982674c241fbef14/frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2", size = 50583 }, + { url = "https://files.pythonhosted.org/packages/1f/22/462a3dd093d11df623179d7754a3b3269de3b42de2808cddef50ee0f4f48/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f", size = 265636 }, + { url = "https://files.pythonhosted.org/packages/80/cf/e075e407fc2ae7328155a1cd7e22f932773c8073c1fc78016607d19cc3e5/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608", size = 270214 }, + { url = "https://files.pythonhosted.org/packages/a1/58/0642d061d5de779f39c50cbb00df49682832923f3d2ebfb0fedf02d05f7f/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b", size = 273905 }, + { url = "https://files.pythonhosted.org/packages/ab/66/3fe0f5f8f2add5b4ab7aa4e199f767fd3b55da26e3ca4ce2cc36698e50c4/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840", size = 250542 }, + { url = "https://files.pythonhosted.org/packages/f6/b8/260791bde9198c87a465224e0e2bb62c4e716f5d198fc3a1dacc4895dbd1/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439", size = 267026 }, + { url = "https://files.pythonhosted.org/packages/2e/a4/3d24f88c527f08f8d44ade24eaee83b2627793fa62fa07cbb7ff7a2f7d42/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de", size = 257690 }, + { url = "https://files.pythonhosted.org/packages/de/9a/d311d660420b2beeff3459b6626f2ab4fb236d07afbdac034a4371fe696e/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641", size = 253893 }, + { url = "https://files.pythonhosted.org/packages/c6/23/e491aadc25b56eabd0f18c53bb19f3cdc6de30b2129ee0bc39cd387cd560/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e", size = 267006 }, + { url = "https://files.pythonhosted.org/packages/08/c4/ab918ce636a35fb974d13d666dcbe03969592aeca6c3ab3835acff01f79c/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9", size = 276157 }, + { url = "https://files.pythonhosted.org/packages/c0/29/3b7a0bbbbe5a34833ba26f686aabfe982924adbdcafdc294a7a129c31688/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03", size = 264642 }, + { url = "https://files.pythonhosted.org/packages/ab/42/0595b3dbffc2e82d7fe658c12d5a5bafcd7516c6bf2d1d1feb5387caa9c1/frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c", size = 44914 }, + { url = "https://files.pythonhosted.org/packages/17/c4/b7db1206a3fea44bf3b838ca61deb6f74424a8a5db1dd53ecb21da669be6/frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28", size = 51167 }, + { url = "https://files.pythonhosted.org/packages/c6/c8/a5be5b7550c10858fcf9b0ea054baccab474da77d37f1e828ce043a3a5d4/frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", size = 11901 }, ] [[package]] @@ -549,23 +586,23 @@ wheels = [ [[package]] name = "idna" -version = "3.8" +version = "3.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/ac/e349c5e6d4543326c6883ee9491e3921e0d07b55fdf3cce184b40d63e72a/idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603", size = 189467 } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } wheels = [ - { url = "https://files.pythonhosted.org/packages/22/7e/d71db821f177828df9dea8c42ac46473366f191be53080e552e628aad991/idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac", size = 66894 }, + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] [[package]] name = "importlib-metadata" -version = "8.4.0" +version = "8.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp" }, + { name = "zipp", marker = "python_full_version >= '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c0/bd/fa8ce65b0a7d4b6d143ec23b0f5fd3f7ab80121078c465bc02baeaab22dc/importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5", size = 54320 } +sdist = { url = "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7", size = 55304 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/14/362d31bf1076b21e1bcdcb0dc61944822ff263937b804a79231df2774d28/importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1", size = 26269 }, + { url = "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", size = 26514 }, ] [[package]] @@ -713,7 +750,7 @@ version = "1.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "ghp-import" }, { name = "jinja2" }, { name = "markdown" }, @@ -875,41 +912,56 @@ wheels = [ [[package]] name = "multidict" -version = "6.0.5" +version = "6.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/79/722ca999a3a09a63b35aac12ec27dfa8e5bb3a38b0f857f7a1a209a88836/multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da", size = 59867 } +sdist = { url = "https://files.pythonhosted.org/packages/d6/be/504b89a5e9ca731cd47487e91c469064f8ae5af93b7259758dcfc2b9c848/multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", size = 64002 } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/da/b10ea65b850b54f44a6479177c6987f456bc2d38f8dc73009b78afcf0ede/multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba", size = 50815 }, - { url = "https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e", size = 30269 }, - { url = "https://files.pythonhosted.org/packages/02/c1/b15ecceb6ffa5081ed2ed450aea58d65b0e0358001f2b426705f9f41f4c2/multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd", size = 30500 }, - { url = "https://files.pythonhosted.org/packages/3f/e1/7fdd0f39565df3af87d6c2903fb66a7d529fbd0a8a066045d7a5b6ad1145/multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3", size = 130751 }, - { url = "https://files.pythonhosted.org/packages/76/bc/9f593f9e38c6c09bbf0344b56ad67dd53c69167937c2edadee9719a5e17d/multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf", size = 138185 }, - { url = "https://files.pythonhosted.org/packages/28/32/d7799a208701d537b92705f46c777ded812a6dc139c18d8ed599908f6b1c/multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29", size = 133585 }, - { url = "https://files.pythonhosted.org/packages/52/ec/be54a3ad110f386d5bd7a9a42a4ff36b3cd723ebe597f41073a73ffa16b8/multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed", size = 128684 }, - { url = "https://files.pythonhosted.org/packages/36/e1/a680eabeb71e25d4733276d917658dfa1cd3a99b1223625dbc247d266c98/multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733", size = 120994 }, - { url = "https://files.pythonhosted.org/packages/ef/08/08f4f44a8a43ea4cee13aa9cdbbf4a639af8db49310a0637ca389c4cf817/multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f", size = 159689 }, - { url = "https://files.pythonhosted.org/packages/aa/a9/46cdb4cb40bbd4b732169413f56b04a6553460b22bd914f9729c9ba63761/multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4", size = 150611 }, - { url = "https://files.pythonhosted.org/packages/e9/32/35668bb3e6ab2f12f4e4f7f4000f72f714882a94f904d4c3633fbd036753/multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1", size = 164444 }, - { url = "https://files.pythonhosted.org/packages/fa/10/f1388a91552af732d8ec48dab928abc209e732767e9e8f92d24c3544353c/multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc", size = 160158 }, - { url = "https://files.pythonhosted.org/packages/14/c3/f602601f1819983e018156e728e57b3f19726cb424b543667faab82f6939/multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e", size = 156072 }, - { url = "https://files.pythonhosted.org/packages/82/a6/0290af8487326108c0d03d14f8a0b8b1001d71e4494df5f96ab0c88c0b88/multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c", size = 25731 }, - { url = "https://files.pythonhosted.org/packages/88/aa/ea217cb18325aa05cb3e3111c19715f1e97c50a4a900cbc20e54648de5f5/multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea", size = 28176 }, - { url = "https://files.pythonhosted.org/packages/90/9c/7fda9c0defa09538c97b1f195394be82a1f53238536f70b32eb5399dfd4e/multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e", size = 49575 }, - { url = "https://files.pythonhosted.org/packages/be/21/d6ca80dd1b9b2c5605ff7475699a8ff5dc6ea958cd71fb2ff234afc13d79/multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b", size = 29638 }, - { url = "https://files.pythonhosted.org/packages/9c/18/9565f32c19d186168731e859692dfbc0e98f66a1dcf9e14d69c02a78b75a/multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5", size = 29874 }, - { url = "https://files.pythonhosted.org/packages/4e/4e/3815190e73e6ef101b5681c174c541bf972a1b064e926e56eea78d06e858/multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450", size = 129914 }, - { url = "https://files.pythonhosted.org/packages/0c/08/bb47f886457e2259aefc10044e45c8a1b62f0c27228557e17775869d0341/multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496", size = 134589 }, - { url = "https://files.pythonhosted.org/packages/d5/2f/952f79b5f0795cf4e34852fc5cf4dfda6166f63c06c798361215b69c131d/multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a", size = 133259 }, - { url = "https://files.pythonhosted.org/packages/24/1f/af976383b0b772dd351210af5b60ff9927e3abb2f4a103e93da19a957da0/multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226", size = 130779 }, - { url = "https://files.pythonhosted.org/packages/fc/b1/b0a7744be00b0f5045c7ed4e4a6b8ee6bde4672b2c620474712299df5979/multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271", size = 120125 }, - { url = "https://files.pythonhosted.org/packages/d0/bf/2a1d667acf11231cdf0b97a6cd9f30e7a5cf847037b5cf6da44884284bd0/multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb", size = 167095 }, - { url = "https://files.pythonhosted.org/packages/5e/e8/ad6ee74b1a2050d3bc78f566dabcc14c8bf89cbe87eecec866c011479815/multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef", size = 155823 }, - { url = "https://files.pythonhosted.org/packages/45/7c/06926bb91752c52abca3edbfefac1ea90d9d1bc00c84d0658c137589b920/multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24", size = 170233 }, - { url = "https://files.pythonhosted.org/packages/3c/29/3dd36cf6b9c5abba8b97bba84eb499a168ba59c3faec8829327b3887d123/multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6", size = 169035 }, - { url = "https://files.pythonhosted.org/packages/60/47/9a0f43470c70bbf6e148311f78ef5a3d4996b0226b6d295bdd50fdcfe387/multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda", size = 166229 }, - { url = "https://files.pythonhosted.org/packages/1d/23/c1b7ae7a0b8a3e08225284ef3ecbcf014b292a3ee821bc4ed2185fd4ce7d/multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5", size = 25840 }, - { url = "https://files.pythonhosted.org/packages/4a/68/66fceb758ad7a88993940dbdf3ac59911ba9dc46d7798bf6c8652f89f853/multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556", size = 27905 }, - { url = "https://files.pythonhosted.org/packages/fa/a2/17e1e23c6be0a916219c5292f509360c345b5fa6beeb50d743203c27532c/multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7", size = 9729 }, + { url = "https://files.pythonhosted.org/packages/93/13/df3505a46d0cd08428e4c8169a196131d1b0c4b515c3649829258843dde6/multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6", size = 48570 }, + { url = "https://files.pythonhosted.org/packages/f0/e1/a215908bfae1343cdb72f805366592bdd60487b4232d039c437fe8f5013d/multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156", size = 29316 }, + { url = "https://files.pythonhosted.org/packages/70/0f/6dc70ddf5d442702ed74f298d69977f904960b82368532c88e854b79f72b/multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb", size = 29640 }, + { url = "https://files.pythonhosted.org/packages/d8/6d/9c87b73a13d1cdea30b321ef4b3824449866bd7f7127eceed066ccb9b9ff/multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b", size = 131067 }, + { url = "https://files.pythonhosted.org/packages/cc/1e/1b34154fef373371fd6c65125b3d42ff5f56c7ccc6bfff91b9b3c60ae9e0/multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72", size = 138507 }, + { url = "https://files.pythonhosted.org/packages/fb/e0/0bc6b2bac6e461822b5f575eae85da6aae76d0e2a79b6665d6206b8e2e48/multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304", size = 133905 }, + { url = "https://files.pythonhosted.org/packages/ba/af/73d13b918071ff9b2205fcf773d316e0f8fefb4ec65354bbcf0b10908cc6/multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351", size = 129004 }, + { url = "https://files.pythonhosted.org/packages/74/21/23960627b00ed39643302d81bcda44c9444ebcdc04ee5bedd0757513f259/multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb", size = 121308 }, + { url = "https://files.pythonhosted.org/packages/8b/5c/cf282263ffce4a596ed0bb2aa1a1dddfe1996d6a62d08842a8d4b33dca13/multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3", size = 132608 }, + { url = "https://files.pythonhosted.org/packages/d7/3e/97e778c041c72063f42b290888daff008d3ab1427f5b09b714f5a8eff294/multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399", size = 127029 }, + { url = "https://files.pythonhosted.org/packages/47/ac/3efb7bfe2f3aefcf8d103e9a7162572f01936155ab2f7ebcc7c255a23212/multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423", size = 137594 }, + { url = "https://files.pythonhosted.org/packages/42/9b/6c6e9e8dc4f915fc90a9b7798c44a30773dea2995fdcb619870e705afe2b/multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3", size = 134556 }, + { url = "https://files.pythonhosted.org/packages/1d/10/8e881743b26aaf718379a14ac58572a240e8293a1c9d68e1418fb11c0f90/multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753", size = 130993 }, + { url = "https://files.pythonhosted.org/packages/45/84/3eb91b4b557442802d058a7579e864b329968c8d0ea57d907e7023c677f2/multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80", size = 26405 }, + { url = "https://files.pythonhosted.org/packages/9f/0b/ad879847ecbf6d27e90a6eabb7eff6b62c129eefe617ea45eae7c1f0aead/multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926", size = 28795 }, + { url = "https://files.pythonhosted.org/packages/fd/16/92057c74ba3b96d5e211b553895cd6dc7cc4d1e43d9ab8fafc727681ef71/multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", size = 48713 }, + { url = "https://files.pythonhosted.org/packages/94/3d/37d1b8893ae79716179540b89fc6a0ee56b4a65fcc0d63535c6f5d96f217/multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", size = 29516 }, + { url = "https://files.pythonhosted.org/packages/a2/12/adb6b3200c363062f805275b4c1e656be2b3681aada66c80129932ff0bae/multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", size = 29557 }, + { url = "https://files.pythonhosted.org/packages/47/e9/604bb05e6e5bce1e6a5cf80a474e0f072e80d8ac105f1b994a53e0b28c42/multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", size = 130170 }, + { url = "https://files.pythonhosted.org/packages/7e/13/9efa50801785eccbf7086b3c83b71a4fb501a4d43549c2f2f80b8787d69f/multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", size = 134836 }, + { url = "https://files.pythonhosted.org/packages/bf/0f/93808b765192780d117814a6dfcc2e75de6dcc610009ad408b8814dca3ba/multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", size = 133475 }, + { url = "https://files.pythonhosted.org/packages/d3/c8/529101d7176fe7dfe1d99604e48d69c5dfdcadb4f06561f465c8ef12b4df/multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", size = 131049 }, + { url = "https://files.pythonhosted.org/packages/ca/0c/fc85b439014d5a58063e19c3a158a889deec399d47b5269a0f3b6a2e28bc/multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", size = 120370 }, + { url = "https://files.pythonhosted.org/packages/db/46/d4416eb20176492d2258fbd47b4abe729ff3b6e9c829ea4236f93c865089/multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", size = 125178 }, + { url = "https://files.pythonhosted.org/packages/5b/46/73697ad7ec521df7de5531a32780bbfd908ded0643cbe457f981a701457c/multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", size = 119567 }, + { url = "https://files.pythonhosted.org/packages/cd/ed/51f060e2cb0e7635329fa6ff930aa5cffa17f4c7f5c6c3ddc3500708e2f2/multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", size = 129822 }, + { url = "https://files.pythonhosted.org/packages/df/9e/ee7d1954b1331da3eddea0c4e08d9142da5f14b1321c7301f5014f49d492/multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", size = 128656 }, + { url = "https://files.pythonhosted.org/packages/77/00/8538f11e3356b5d95fa4b024aa566cde7a38aa7a5f08f4912b32a037c5dc/multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", size = 125360 }, + { url = "https://files.pythonhosted.org/packages/be/05/5d334c1f2462d43fec2363cd00b1c44c93a78c3925d952e9a71caf662e96/multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", size = 26382 }, + { url = "https://files.pythonhosted.org/packages/a3/bf/f332a13486b1ed0496d624bcc7e8357bb8053823e8cd4b9a18edc1d97e73/multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", size = 28529 }, + { url = "https://files.pythonhosted.org/packages/22/67/1c7c0f39fe069aa4e5d794f323be24bf4d33d62d2a348acdb7991f8f30db/multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", size = 48771 }, + { url = "https://files.pythonhosted.org/packages/3c/25/c186ee7b212bdf0df2519eacfb1981a017bda34392c67542c274651daf23/multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", size = 29533 }, + { url = "https://files.pythonhosted.org/packages/67/5e/04575fd837e0958e324ca035b339cea174554f6f641d3fb2b4f2e7ff44a2/multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", size = 29595 }, + { url = "https://files.pythonhosted.org/packages/d3/b2/e56388f86663810c07cfe4a3c3d87227f3811eeb2d08450b9e5d19d78876/multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", size = 130094 }, + { url = "https://files.pythonhosted.org/packages/6c/ee/30ae9b4186a644d284543d55d491fbd4239b015d36b23fea43b4c94f7052/multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", size = 134876 }, + { url = "https://files.pythonhosted.org/packages/84/c7/70461c13ba8ce3c779503c70ec9d0345ae84de04521c1f45a04d5f48943d/multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", size = 133500 }, + { url = "https://files.pythonhosted.org/packages/4a/9f/002af221253f10f99959561123fae676148dd730e2daa2cd053846a58507/multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", size = 131099 }, + { url = "https://files.pythonhosted.org/packages/82/42/d1c7a7301d52af79d88548a97e297f9d99c961ad76bbe6f67442bb77f097/multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", size = 120403 }, + { url = "https://files.pythonhosted.org/packages/68/f3/471985c2c7ac707547553e8f37cff5158030d36bdec4414cb825fbaa5327/multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", size = 125348 }, + { url = "https://files.pythonhosted.org/packages/67/2c/e6df05c77e0e433c214ec1d21ddd203d9a4770a1f2866a8ca40a545869a0/multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", size = 119673 }, + { url = "https://files.pythonhosted.org/packages/c5/cd/bc8608fff06239c9fb333f9db7743a1b2eafe98c2666c9a196e867a3a0a4/multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", size = 129927 }, + { url = "https://files.pythonhosted.org/packages/44/8e/281b69b7bc84fc963a44dc6e0bbcc7150e517b91df368a27834299a526ac/multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", size = 128711 }, + { url = "https://files.pythonhosted.org/packages/12/a4/63e7cd38ed29dd9f1881d5119f272c898ca92536cdb53ffe0843197f6c85/multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", size = 125519 }, + { url = "https://files.pythonhosted.org/packages/38/e0/4f5855037a72cd8a7a2f60a3952d9aa45feedb37ae7831642102604e8a37/multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", size = 26426 }, + { url = "https://files.pythonhosted.org/packages/7e/a5/17ee3a4db1e310b7405f5d25834460073a8ccd86198ce044dfaf69eac073/multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", size = 28531 }, + { url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051 }, ] [[package]] @@ -960,45 +1012,54 @@ wheels = [ [[package]] name = "orjson" -version = "3.10.7" +version = "3.10.12" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9e/03/821c8197d0515e46ea19439f5c5d5fd9a9889f76800613cfac947b5d7845/orjson-3.10.7.tar.gz", hash = "sha256:75ef0640403f945f3a1f9f6400686560dbfb0fb5b16589ad62cd477043c4eee3", size = 5056450 } +sdist = { url = "https://files.pythonhosted.org/packages/e0/04/bb9f72987e7f62fb591d6c880c0caaa16238e4e530cbc3bdc84a7372d75f/orjson-3.10.12.tar.gz", hash = "sha256:0a78bbda3aea0f9f079057ee1ee8a1ecf790d4f1af88dd67493c6b8ee52506ff", size = 5438647 } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/c9/dd286c97c2f478d43839bd859ca4d9820e2177d4e07a64c516dc3e018062/orjson-3.10.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7db8539039698ddfb9a524b4dd19508256107568cdad24f3682d5773e60504a2", size = 251312 }, - { url = "https://files.pythonhosted.org/packages/b9/72/d90bd11e83a0e9623b3803b079478a93de8ec4316c98fa66110d594de5fa/orjson-3.10.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:480f455222cb7a1dea35c57a67578848537d2602b46c464472c995297117fa09", size = 148125 }, - { url = "https://files.pythonhosted.org/packages/9d/b6/ed61e87f327a4cbb2075ed0716e32ba68cb029aa654a68c3eb27803050d8/orjson-3.10.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a9c9b168b3a19e37fe2778c0003359f07822c90fdff8f98d9d2a91b3144d8e0", size = 147278 }, - { url = "https://files.pythonhosted.org/packages/66/9f/e6a11b5d1ad11e9dc869d938707ef93ff5ed20b53d6cda8b5e2ac532a9d2/orjson-3.10.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8de062de550f63185e4c1c54151bdddfc5625e37daf0aa1e75d2a1293e3b7d9a", size = 152954 }, - { url = "https://files.pythonhosted.org/packages/92/ee/702d5e8ccd42dc2b9d1043f22daa1ba75165616aa021dc19fb0c5a726ce8/orjson-3.10.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6b0dd04483499d1de9c8f6203f8975caf17a6000b9c0c54630cef02e44ee624e", size = 163953 }, - { url = "https://files.pythonhosted.org/packages/d3/cb/55205f3f1ee6ba80c0a9a18ca07423003ca8de99192b18be30f1f31b4cdd/orjson-3.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b58d3795dafa334fc8fd46f7c5dc013e6ad06fd5b9a4cc98cb1456e7d3558bd6", size = 141895 }, - { url = "https://files.pythonhosted.org/packages/bb/ab/1185e472f15c00d37d09c395e478803ed0eae7a3a3d055a5f3885e1ea136/orjson-3.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33cfb96c24034a878d83d1a9415799a73dc77480e6c40417e5dda0710d559ee6", size = 170169 }, - { url = "https://files.pythonhosted.org/packages/53/b9/10abe9089bdb08cd4218cc45eb7abfd787c82cf301cecbfe7f141542d7f4/orjson-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e724cebe1fadc2b23c6f7415bad5ee6239e00a69f30ee423f319c6af70e2a5c0", size = 167808 }, - { url = "https://files.pythonhosted.org/packages/8a/ad/26b40ccef119dcb0f4a39745ffd7d2d319152c1a52859b1ebbd114eca19c/orjson-3.10.7-cp311-none-win32.whl", hash = "sha256:82763b46053727a7168d29c772ed5c870fdae2f61aa8a25994c7984a19b1021f", size = 143010 }, - { url = "https://files.pythonhosted.org/packages/e7/63/5f4101e4895b78ada568f4cf8f870dd594139ca2e75e654e373da78b03b0/orjson-3.10.7-cp311-none-win_amd64.whl", hash = "sha256:eb8d384a24778abf29afb8e41d68fdd9a156cf6e5390c04cc07bbc24b89e98b5", size = 137307 }, - { url = "https://files.pythonhosted.org/packages/14/7c/b4ecc2069210489696a36e42862ccccef7e49e1454a3422030ef52881b01/orjson-3.10.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44a96f2d4c3af51bfac6bc4ef7b182aa33f2f054fd7f34cc0ee9a320d051d41f", size = 251409 }, - { url = "https://files.pythonhosted.org/packages/60/84/e495edb919ef0c98d054a9b6d05f2700fdeba3886edd58f1c4dfb25d514a/orjson-3.10.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ac14cd57df0572453543f8f2575e2d01ae9e790c21f57627803f5e79b0d3c3", size = 147913 }, - { url = "https://files.pythonhosted.org/packages/c5/27/e40bc7d79c4afb7e9264f22320c285d06d2c9574c9c682ba0f1be3012833/orjson-3.10.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bdbb61dcc365dd9be94e8f7df91975edc9364d6a78c8f7adb69c1cdff318ec93", size = 147390 }, - { url = "https://files.pythonhosted.org/packages/30/be/fd646fb1a461de4958a6eacf4ecf064b8d5479c023e0e71cc89b28fa91ac/orjson-3.10.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b48b3db6bb6e0a08fa8c83b47bc169623f801e5cc4f24442ab2b6617da3b5313", size = 152973 }, - { url = "https://files.pythonhosted.org/packages/b1/00/414f8d4bc5ec3447e27b5c26b4e996e4ef08594d599e79b3648f64da060c/orjson-3.10.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23820a1563a1d386414fef15c249040042b8e5d07b40ab3fe3efbfbbcbcb8864", size = 164039 }, - { url = "https://files.pythonhosted.org/packages/a0/6b/34e6904ac99df811a06e42d8461d47b6e0c9b86e2fe7ee84934df6e35f0d/orjson-3.10.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0c6a008e91d10a2564edbb6ee5069a9e66df3fbe11c9a005cb411f441fd2c09", size = 142035 }, - { url = "https://files.pythonhosted.org/packages/17/7e/254189d9b6df89660f65aec878d5eeaa5b1ae371bd2c458f85940445d36f/orjson-3.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d352ee8ac1926d6193f602cbe36b1643bbd1bbcb25e3c1a657a4390f3000c9a5", size = 169941 }, - { url = "https://files.pythonhosted.org/packages/02/1a/d11805670c29d3a1b29fc4bd048dc90b094784779690592efe8c9f71249a/orjson-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d2d9f990623f15c0ae7ac608103c33dfe1486d2ed974ac3f40b693bad1a22a7b", size = 167994 }, - { url = "https://files.pythonhosted.org/packages/20/5f/03d89b007f9d6733dc11bc35d64812101c85d6c4e9c53af9fa7e7689cb11/orjson-3.10.7-cp312-none-win32.whl", hash = "sha256:7c4c17f8157bd520cdb7195f75ddbd31671997cbe10aee559c2d613592e7d7eb", size = 143130 }, - { url = "https://files.pythonhosted.org/packages/c6/9d/9b9fb6c60b8a0e04031ba85414915e19ecea484ebb625402d968ea45b8d5/orjson-3.10.7-cp312-none-win_amd64.whl", hash = "sha256:1d9c0e733e02ada3ed6098a10a8ee0052dd55774de3d9110d29868d24b17faa1", size = 137326 }, - { url = "https://files.pythonhosted.org/packages/15/05/121af8a87513c56745d01ad7cf215c30d08356da9ad882ebe2ba890824cd/orjson-3.10.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:77d325ed866876c0fa6492598ec01fe30e803272a6e8b10e992288b009cbe149", size = 251331 }, - { url = "https://files.pythonhosted.org/packages/73/7f/8d6ccd64a6f8bdbfe6c9be7c58aeb8094aa52a01fbbb2cda42ff7e312bd7/orjson-3.10.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ea2c232deedcb605e853ae1db2cc94f7390ac776743b699b50b071b02bea6fe", size = 142012 }, - { url = "https://files.pythonhosted.org/packages/04/65/f2a03fd1d4f0308f01d372e004c049f7eb9bc5676763a15f20f383fa9c01/orjson-3.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3dcfbede6737fdbef3ce9c37af3fb6142e8e1ebc10336daa05872bfb1d87839c", size = 169920 }, - { url = "https://files.pythonhosted.org/packages/e2/1c/3ef8d83d7c6a619ad3d69a4d5318591b4ce5862e6eda7c26bbe8208652ca/orjson-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11748c135f281203f4ee695b7f80bb1358a82a63905f9f0b794769483ea854ad", size = 167916 }, - { url = "https://files.pythonhosted.org/packages/f2/0d/820a640e5a7dfbe525e789c70871ebb82aff73b0c7bf80082653f86b9431/orjson-3.10.7-cp313-none-win32.whl", hash = "sha256:a7e19150d215c7a13f39eb787d84db274298d3f83d85463e61d277bbd7f401d2", size = 143089 }, - { url = "https://files.pythonhosted.org/packages/1a/72/a424db9116c7cad2950a8f9e4aeb655a7b57de988eb015acd0fcd1b4609b/orjson-3.10.7-cp313-none-win_amd64.whl", hash = "sha256:eef44224729e9525d5261cc8d28d6b11cafc90e6bd0be2157bde69a52ec83024", size = 137081 }, + { url = "https://files.pythonhosted.org/packages/d3/48/7c3cd094488f5a3bc58488555244609a8c4d105bc02f2b77e509debf0450/orjson-3.10.12-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a734c62efa42e7df94926d70fe7d37621c783dea9f707a98cdea796964d4cf74", size = 248687 }, + { url = "https://files.pythonhosted.org/packages/ff/90/e55f0e25c7fdd1f82551fe787f85df6f378170caca863c04c810cd8f2730/orjson-3.10.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:750f8b27259d3409eda8350c2919a58b0cfcd2054ddc1bd317a643afc646ef23", size = 136953 }, + { url = "https://files.pythonhosted.org/packages/2a/b3/109c020cf7fee747d400de53b43b183ca9d3ebda3906ad0b858eb5479718/orjson-3.10.12-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb52c22bfffe2857e7aa13b4622afd0dd9d16ea7cc65fd2bf318d3223b1b6252", size = 149090 }, + { url = "https://files.pythonhosted.org/packages/96/d4/35c0275dc1350707d182a1b5da16d1184b9439848060af541285407f18f9/orjson-3.10.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:440d9a337ac8c199ff8251e100c62e9488924c92852362cd27af0e67308c16ef", size = 140480 }, + { url = "https://files.pythonhosted.org/packages/3b/79/f863ff460c291ad2d882cc3b580cc444bd4ec60c9df55f6901e6c9a3f519/orjson-3.10.12-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9e15c06491c69997dfa067369baab3bf094ecb74be9912bdc4339972323f252", size = 156564 }, + { url = "https://files.pythonhosted.org/packages/98/7e/8d5835449ddd873424ee7b1c4ba73a0369c1055750990d824081652874d6/orjson-3.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:362d204ad4b0b8724cf370d0cd917bb2dc913c394030da748a3bb632445ce7c4", size = 131279 }, + { url = "https://files.pythonhosted.org/packages/46/f5/d34595b6d7f4f984c6fef289269a7f98abcdc2445ebdf90e9273487dda6b/orjson-3.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b57cbb4031153db37b41622eac67329c7810e5f480fda4cfd30542186f006ae", size = 139764 }, + { url = "https://files.pythonhosted.org/packages/b3/5b/ee6e9ddeab54a7b7806768151c2090a2d36025bc346a944f51cf172ef7f7/orjson-3.10.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:165c89b53ef03ce0d7c59ca5c82fa65fe13ddf52eeb22e859e58c237d4e33b9b", size = 131915 }, + { url = "https://files.pythonhosted.org/packages/c4/45/febee5951aef6db5cd8cdb260548101d7ece0ca9d4ddadadf1766306b7a4/orjson-3.10.12-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5dee91b8dfd54557c1a1596eb90bcd47dbcd26b0baaed919e6861f076583e9da", size = 415783 }, + { url = "https://files.pythonhosted.org/packages/27/a5/5a8569e49f3a6c093bee954a3de95062a231196f59e59df13a48e2420081/orjson-3.10.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:77a4e1cfb72de6f905bdff061172adfb3caf7a4578ebf481d8f0530879476c07", size = 142387 }, + { url = "https://files.pythonhosted.org/packages/6e/05/02550fb38c5bf758f3994f55401233a2ef304e175f473f2ac6dbf464cc8b/orjson-3.10.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:038d42c7bc0606443459b8fe2d1f121db474c49067d8d14c6a075bbea8bf14dd", size = 130664 }, + { url = "https://files.pythonhosted.org/packages/8c/f4/ba31019d0646ce51f7ac75af6dabf98fd89dbf8ad87a9086da34710738e7/orjson-3.10.12-cp311-none-win32.whl", hash = "sha256:03b553c02ab39bed249bedd4abe37b2118324d1674e639b33fab3d1dafdf4d79", size = 143623 }, + { url = "https://files.pythonhosted.org/packages/83/fe/babf08842b989acf4c46103fefbd7301f026423fab47e6f3ba07b54d7837/orjson-3.10.12-cp311-none-win_amd64.whl", hash = "sha256:8b8713b9e46a45b2af6b96f559bfb13b1e02006f4242c156cbadef27800a55a8", size = 135074 }, + { url = "https://files.pythonhosted.org/packages/a1/2f/989adcafad49afb535da56b95d8f87d82e748548b2a86003ac129314079c/orjson-3.10.12-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:53206d72eb656ca5ac7d3a7141e83c5bbd3ac30d5eccfe019409177a57634b0d", size = 248678 }, + { url = "https://files.pythonhosted.org/packages/69/b9/8c075e21a50c387649db262b618ebb7e4d40f4197b949c146fc225dd23da/orjson-3.10.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac8010afc2150d417ebda810e8df08dd3f544e0dd2acab5370cfa6bcc0662f8f", size = 136763 }, + { url = "https://files.pythonhosted.org/packages/87/d3/78edf10b4ab14c19f6d918cf46a145818f4aca2b5a1773c894c5490d3a4c/orjson-3.10.12-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed459b46012ae950dd2e17150e838ab08215421487371fa79d0eced8d1461d70", size = 149137 }, + { url = "https://files.pythonhosted.org/packages/16/81/5db8852bdf990a0ddc997fa8f16b80895b8cc77c0fe3701569ed2b4b9e78/orjson-3.10.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dcb9673f108a93c1b52bfc51b0af422c2d08d4fc710ce9c839faad25020bb69", size = 140567 }, + { url = "https://files.pythonhosted.org/packages/fa/a6/9ce1e3e3db918512efadad489630c25841eb148513d21dab96f6b4157fa1/orjson-3.10.12-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:22a51ae77680c5c4652ebc63a83d5255ac7d65582891d9424b566fb3b5375ee9", size = 156620 }, + { url = "https://files.pythonhosted.org/packages/47/d4/05133d6bea24e292d2f7628b1e19986554f7d97b6412b3e51d812e38db2d/orjson-3.10.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910fdf2ac0637b9a77d1aad65f803bac414f0b06f720073438a7bd8906298192", size = 131555 }, + { url = "https://files.pythonhosted.org/packages/b9/7a/b3fbffda8743135c7811e95dc2ab7cdbc5f04999b83c2957d046f1b3fac9/orjson-3.10.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:24ce85f7100160936bc2116c09d1a8492639418633119a2224114f67f63a4559", size = 139743 }, + { url = "https://files.pythonhosted.org/packages/b5/13/95bbcc9a6584aa083da5ce5004ce3d59ea362a542a0b0938d884fd8790b6/orjson-3.10.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a76ba5fc8dd9c913640292df27bff80a685bed3a3c990d59aa6ce24c352f8fc", size = 131733 }, + { url = "https://files.pythonhosted.org/packages/e8/29/dddbb2ea6e7af426fcc3da65a370618a88141de75c6603313d70768d1df1/orjson-3.10.12-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ff70ef093895fd53f4055ca75f93f047e088d1430888ca1229393a7c0521100f", size = 415788 }, + { url = "https://files.pythonhosted.org/packages/53/df/4aea59324ac539975919b4705ee086aced38e351a6eb3eea0f5071dd5661/orjson-3.10.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f4244b7018b5753ecd10a6d324ec1f347da130c953a9c88432c7fbc8875d13be", size = 142347 }, + { url = "https://files.pythonhosted.org/packages/55/55/a52d83d7c49f8ff44e0daab10554490447d6c658771569e1c662aa7057fe/orjson-3.10.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:16135ccca03445f37921fa4b585cff9a58aa8d81ebcb27622e69bfadd220b32c", size = 130829 }, + { url = "https://files.pythonhosted.org/packages/a1/8b/b1beb1624dd4adf7d72e2d9b73c4b529e7851c0c754f17858ea13e368b33/orjson-3.10.12-cp312-none-win32.whl", hash = "sha256:2d879c81172d583e34153d524fcba5d4adafbab8349a7b9f16ae511c2cee8708", size = 143659 }, + { url = "https://files.pythonhosted.org/packages/13/91/634c9cd0bfc6a857fc8fab9bf1a1bd9f7f3345e0d6ca5c3d4569ceb6dcfa/orjson-3.10.12-cp312-none-win_amd64.whl", hash = "sha256:fc23f691fa0f5c140576b8c365bc942d577d861a9ee1142e4db468e4e17094fb", size = 135221 }, + { url = "https://files.pythonhosted.org/packages/1b/bb/3f560735f46fa6f875a9d7c4c2171a58cfb19f56a633d5ad5037a924f35f/orjson-3.10.12-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:47962841b2a8aa9a258b377f5188db31ba49af47d4003a32f55d6f8b19006543", size = 248662 }, + { url = "https://files.pythonhosted.org/packages/a3/df/54817902350636cc9270db20486442ab0e4db33b38555300a1159b439d16/orjson-3.10.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6334730e2532e77b6054e87ca84f3072bee308a45a452ea0bffbbbc40a67e296", size = 126055 }, + { url = "https://files.pythonhosted.org/packages/2e/77/55835914894e00332601a74540840f7665e81f20b3e2b9a97614af8565ed/orjson-3.10.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:accfe93f42713c899fdac2747e8d0d5c659592df2792888c6c5f829472e4f85e", size = 131507 }, + { url = "https://files.pythonhosted.org/packages/33/9e/b91288361898e3158062a876b5013c519a5d13e692ac7686e3486c4133ab/orjson-3.10.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7974c490c014c48810d1dede6c754c3cc46598da758c25ca3b4001ac45b703f", size = 131686 }, + { url = "https://files.pythonhosted.org/packages/b2/15/08ce117d60a4d2d3fd24e6b21db463139a658e9f52d22c9c30af279b4187/orjson-3.10.12-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3f250ce7727b0b2682f834a3facff88e310f52f07a5dcfd852d99637d386e79e", size = 415710 }, + { url = "https://files.pythonhosted.org/packages/71/af/c09da5ed58f9c002cf83adff7a4cdf3e6cee742aa9723395f8dcdb397233/orjson-3.10.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f31422ff9486ae484f10ffc51b5ab2a60359e92d0716fcce1b3593d7bb8a9af6", size = 142305 }, + { url = "https://files.pythonhosted.org/packages/17/d1/8612038d44f33fae231e9ba480d273bac2b0383ce9e77cb06bede1224ae3/orjson-3.10.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5f29c5d282bb2d577c2a6bbde88d8fdcc4919c593f806aac50133f01b733846e", size = 130815 }, + { url = "https://files.pythonhosted.org/packages/67/2c/d5f87834be3591555cfaf9aecdf28f480a6f0b4afeaac53bad534bf9518f/orjson-3.10.12-cp313-none-win32.whl", hash = "sha256:f45653775f38f63dc0e6cd4f14323984c3149c05d6007b58cb154dd080ddc0dc", size = 143664 }, + { url = "https://files.pythonhosted.org/packages/6a/05/7d768fa3ca23c9b3e1e09117abeded1501119f1d8de0ab722938c91ab25d/orjson-3.10.12-cp313-none-win_amd64.whl", hash = "sha256:229994d0c376d5bdc91d92b3c9e6be2f1fbabd4cc1b59daae1443a46ee5e9825", size = 134944 }, ] [[package]] name = "packaging" -version = "24.1" +version = "24.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/65/50db4dda066951078f0a96cf12f4b9ada6e4b811516bf0262c0f4f7064d4/packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", size = 148788 } +sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } wheels = [ - { url = "https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124", size = 53985 }, + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, ] [[package]] @@ -1076,27 +1137,93 @@ wheels = [ ] [[package]] -name = "platformdirs" -version = "4.2.2" +name = "pip" +version = "24.3.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f5/52/0763d1d976d5c262df53ddda8d8d4719eedf9594d046f117c25a27261a19/platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3", size = 20916 } +sdist = { url = "https://files.pythonhosted.org/packages/f4/b1/b422acd212ad7eedddaf7981eee6e5de085154ff726459cf2da7c5a184c1/pip-24.3.1.tar.gz", hash = "sha256:ebcb60557f2aefabc2e0f918751cd24ea0d56d8ec5445fe1807f1d2109660b99", size = 1931073 } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/13/2aa1f0e1364feb2c9ef45302f387ac0bd81484e9c9a4c5688a322fbdfd08/platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee", size = 18146 }, + { url = "https://files.pythonhosted.org/packages/ef/7d/500c9ad20238fcfcb4cb9243eede163594d7020ce87bd9610c9e02771876/pip-24.3.1-py3-none-any.whl", hash = "sha256:3790624780082365f47549d032f3770eeb2b1e8bd1f7b2e02dace1afa361b4ed", size = 1822182 }, +] + +[[package]] +name = "platformdirs" +version = "4.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 }, +] + +[[package]] +name = "propcache" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/4d/5e5a60b78dbc1d464f8a7bbaeb30957257afdc8512cbb9dfd5659304f5cd/propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70", size = 40951 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/1c/71eec730e12aec6511e702ad0cd73c2872eccb7cad39de8ba3ba9de693ef/propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354", size = 80811 }, + { url = "https://files.pythonhosted.org/packages/89/c3/7e94009f9a4934c48a371632197406a8860b9f08e3f7f7d922ab69e57a41/propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de", size = 46365 }, + { url = "https://files.pythonhosted.org/packages/c0/1d/c700d16d1d6903aeab28372fe9999762f074b80b96a0ccc953175b858743/propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87", size = 45602 }, + { url = "https://files.pythonhosted.org/packages/2e/5e/4a3e96380805bf742712e39a4534689f4cddf5fa2d3a93f22e9fd8001b23/propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016", size = 236161 }, + { url = "https://files.pythonhosted.org/packages/a5/85/90132481183d1436dff6e29f4fa81b891afb6cb89a7306f32ac500a25932/propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb", size = 244938 }, + { url = "https://files.pythonhosted.org/packages/4a/89/c893533cb45c79c970834274e2d0f6d64383ec740be631b6a0a1d2b4ddc0/propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2", size = 243576 }, + { url = "https://files.pythonhosted.org/packages/8c/56/98c2054c8526331a05f205bf45cbb2cda4e58e56df70e76d6a509e5d6ec6/propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4", size = 236011 }, + { url = "https://files.pythonhosted.org/packages/2d/0c/8b8b9f8a6e1abd869c0fa79b907228e7abb966919047d294ef5df0d136cf/propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504", size = 224834 }, + { url = "https://files.pythonhosted.org/packages/18/bb/397d05a7298b7711b90e13108db697732325cafdcd8484c894885c1bf109/propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178", size = 224946 }, + { url = "https://files.pythonhosted.org/packages/25/19/4fc08dac19297ac58135c03770b42377be211622fd0147f015f78d47cd31/propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d", size = 217280 }, + { url = "https://files.pythonhosted.org/packages/7e/76/c79276a43df2096ce2aba07ce47576832b1174c0c480fe6b04bd70120e59/propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2", size = 220088 }, + { url = "https://files.pythonhosted.org/packages/c3/9a/8a8cf428a91b1336b883f09c8b884e1734c87f724d74b917129a24fe2093/propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db", size = 233008 }, + { url = "https://files.pythonhosted.org/packages/25/7b/768a8969abd447d5f0f3333df85c6a5d94982a1bc9a89c53c154bf7a8b11/propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b", size = 237719 }, + { url = "https://files.pythonhosted.org/packages/ed/0d/e5d68ccc7976ef8b57d80613ac07bbaf0614d43f4750cf953f0168ef114f/propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b", size = 227729 }, + { url = "https://files.pythonhosted.org/packages/05/64/17eb2796e2d1c3d0c431dc5f40078d7282f4645af0bb4da9097fbb628c6c/propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1", size = 40473 }, + { url = "https://files.pythonhosted.org/packages/83/c5/e89fc428ccdc897ade08cd7605f174c69390147526627a7650fb883e0cd0/propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71", size = 44921 }, + { url = "https://files.pythonhosted.org/packages/7c/46/a41ca1097769fc548fc9216ec4c1471b772cc39720eb47ed7e38ef0006a9/propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2", size = 80800 }, + { url = "https://files.pythonhosted.org/packages/75/4f/93df46aab9cc473498ff56be39b5f6ee1e33529223d7a4d8c0a6101a9ba2/propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7", size = 46443 }, + { url = "https://files.pythonhosted.org/packages/0b/17/308acc6aee65d0f9a8375e36c4807ac6605d1f38074b1581bd4042b9fb37/propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8", size = 45676 }, + { url = "https://files.pythonhosted.org/packages/65/44/626599d2854d6c1d4530b9a05e7ff2ee22b790358334b475ed7c89f7d625/propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793", size = 246191 }, + { url = "https://files.pythonhosted.org/packages/f2/df/5d996d7cb18df076debae7d76ac3da085c0575a9f2be6b1f707fe227b54c/propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09", size = 251791 }, + { url = "https://files.pythonhosted.org/packages/2e/6d/9f91e5dde8b1f662f6dd4dff36098ed22a1ef4e08e1316f05f4758f1576c/propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89", size = 253434 }, + { url = "https://files.pythonhosted.org/packages/3c/e9/1b54b7e26f50b3e0497cd13d3483d781d284452c2c50dd2a615a92a087a3/propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e", size = 248150 }, + { url = "https://files.pythonhosted.org/packages/a7/ef/a35bf191c8038fe3ce9a414b907371c81d102384eda5dbafe6f4dce0cf9b/propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9", size = 233568 }, + { url = "https://files.pythonhosted.org/packages/97/d9/d00bb9277a9165a5e6d60f2142cd1a38a750045c9c12e47ae087f686d781/propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4", size = 229874 }, + { url = "https://files.pythonhosted.org/packages/8e/78/c123cf22469bdc4b18efb78893e69c70a8b16de88e6160b69ca6bdd88b5d/propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c", size = 225857 }, + { url = "https://files.pythonhosted.org/packages/31/1b/fd6b2f1f36d028820d35475be78859d8c89c8f091ad30e377ac49fd66359/propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887", size = 227604 }, + { url = "https://files.pythonhosted.org/packages/99/36/b07be976edf77a07233ba712e53262937625af02154353171716894a86a6/propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57", size = 238430 }, + { url = "https://files.pythonhosted.org/packages/0d/64/5822f496c9010e3966e934a011ac08cac8734561842bc7c1f65586e0683c/propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23", size = 244814 }, + { url = "https://files.pythonhosted.org/packages/fd/bd/8657918a35d50b18a9e4d78a5df7b6c82a637a311ab20851eef4326305c1/propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348", size = 235922 }, + { url = "https://files.pythonhosted.org/packages/a8/6f/ec0095e1647b4727db945213a9f395b1103c442ef65e54c62e92a72a3f75/propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5", size = 40177 }, + { url = "https://files.pythonhosted.org/packages/20/a2/bd0896fdc4f4c1db46d9bc361c8c79a9bf08ccc08ba054a98e38e7ba1557/propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3", size = 44446 }, + { url = "https://files.pythonhosted.org/packages/a8/a7/5f37b69197d4f558bfef5b4bceaff7c43cc9b51adf5bd75e9081d7ea80e4/propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7", size = 78120 }, + { url = "https://files.pythonhosted.org/packages/c8/cd/48ab2b30a6b353ecb95a244915f85756d74f815862eb2ecc7a518d565b48/propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763", size = 45127 }, + { url = "https://files.pythonhosted.org/packages/a5/ba/0a1ef94a3412aab057bd996ed5f0ac7458be5bf469e85c70fa9ceb43290b/propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d", size = 44419 }, + { url = "https://files.pythonhosted.org/packages/b4/6c/ca70bee4f22fa99eacd04f4d2f1699be9d13538ccf22b3169a61c60a27fa/propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a", size = 229611 }, + { url = "https://files.pythonhosted.org/packages/19/70/47b872a263e8511ca33718d96a10c17d3c853aefadeb86dc26e8421184b9/propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b", size = 234005 }, + { url = "https://files.pythonhosted.org/packages/4f/be/3b0ab8c84a22e4a3224719099c1229ddfdd8a6a1558cf75cb55ee1e35c25/propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb", size = 237270 }, + { url = "https://files.pythonhosted.org/packages/04/d8/f071bb000d4b8f851d312c3c75701e586b3f643fe14a2e3409b1b9ab3936/propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf", size = 231877 }, + { url = "https://files.pythonhosted.org/packages/93/e7/57a035a1359e542bbb0a7df95aad6b9871ebee6dce2840cb157a415bd1f3/propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2", size = 217848 }, + { url = "https://files.pythonhosted.org/packages/f0/93/d1dea40f112ec183398fb6c42fde340edd7bab202411c4aa1a8289f461b6/propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f", size = 216987 }, + { url = "https://files.pythonhosted.org/packages/62/4c/877340871251145d3522c2b5d25c16a1690ad655fbab7bb9ece6b117e39f/propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136", size = 212451 }, + { url = "https://files.pythonhosted.org/packages/7c/bb/a91b72efeeb42906ef58ccf0cdb87947b54d7475fee3c93425d732f16a61/propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325", size = 212879 }, + { url = "https://files.pythonhosted.org/packages/9b/7f/ee7fea8faac57b3ec5d91ff47470c6c5d40d7f15d0b1fccac806348fa59e/propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44", size = 222288 }, + { url = "https://files.pythonhosted.org/packages/ff/d7/acd67901c43d2e6b20a7a973d9d5fd543c6e277af29b1eb0e1f7bd7ca7d2/propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83", size = 228257 }, + { url = "https://files.pythonhosted.org/packages/8d/6f/6272ecc7a8daad1d0754cfc6c8846076a8cb13f810005c79b15ce0ef0cf2/propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544", size = 221075 }, + { url = "https://files.pythonhosted.org/packages/7c/bd/c7a6a719a6b3dd8b3aeadb3675b5783983529e4a3185946aa444d3e078f6/propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032", size = 39654 }, + { url = "https://files.pythonhosted.org/packages/88/e7/0eef39eff84fa3e001b44de0bd41c7c0e3432e7648ffd3d64955910f002d/propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e", size = 43705 }, + { url = "https://files.pythonhosted.org/packages/3d/b6/e6d98278f2d49b22b4d033c9f792eda783b9ab2094b041f013fc69bcde87/propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036", size = 11603 }, ] [[package]] name = "psutil" -version = "6.0.0" +version = "6.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/c7/8c6872f7372eb6a6b2e4708b88419fb46b857f7a2e1892966b851cc79fc9/psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2", size = 508067 } +sdist = { url = "https://files.pythonhosted.org/packages/1f/5a/07871137bb752428aa4b659f910b399ba6f291156bdea939be3e96cae7cb/psutil-6.1.1.tar.gz", hash = "sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5", size = 508502 } wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0", size = 250961 }, - { url = "https://files.pythonhosted.org/packages/35/56/72f86175e81c656a01c4401cd3b1c923f891b31fbcebe98985894176d7c9/psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0", size = 287478 }, - { url = "https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd", size = 290455 }, - { url = "https://files.pythonhosted.org/packages/cd/5f/60038e277ff0a9cc8f0c9ea3d0c5eb6ee1d2470ea3f9389d776432888e47/psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132", size = 292046 }, - { url = "https://files.pythonhosted.org/packages/8b/20/2ff69ad9c35c3df1858ac4e094f20bd2374d33c8643cf41da8fd7cdcb78b/psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d", size = 253560 }, - { url = "https://files.pythonhosted.org/packages/73/44/561092313ae925f3acfaace6f9ddc4f6a9c748704317bad9c8c8f8a36a79/psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3", size = 257399 }, - { url = "https://files.pythonhosted.org/packages/7c/06/63872a64c312a24fb9b4af123ee7007a306617da63ff13bcc1432386ead7/psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0", size = 251988 }, + { url = "https://files.pythonhosted.org/packages/61/99/ca79d302be46f7bdd8321089762dd4476ee725fce16fc2b2e1dbba8cac17/psutil-6.1.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8", size = 247511 }, + { url = "https://files.pythonhosted.org/packages/0b/6b/73dbde0dd38f3782905d4587049b9be64d76671042fdcaf60e2430c6796d/psutil-6.1.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377", size = 248985 }, + { url = "https://files.pythonhosted.org/packages/17/38/c319d31a1d3f88c5b79c68b3116c129e5133f1822157dd6da34043e32ed6/psutil-6.1.1-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003", size = 284488 }, + { url = "https://files.pythonhosted.org/packages/9c/39/0f88a830a1c8a3aba27fededc642da37613c57cbff143412e3536f89784f/psutil-6.1.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160", size = 287477 }, + { url = "https://files.pythonhosted.org/packages/47/da/99f4345d4ddf2845cb5b5bd0d93d554e84542d116934fde07a0c50bd4e9f/psutil-6.1.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3", size = 289017 }, + { url = "https://files.pythonhosted.org/packages/38/53/bd755c2896f4461fd4f36fa6a6dcb66a88a9e4b9fd4e5b66a77cf9d4a584/psutil-6.1.1-cp37-abi3-win32.whl", hash = "sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53", size = 250602 }, + { url = "https://files.pythonhosted.org/packages/7b/d7/7831438e6c3ebbfa6e01a927127a6cb42ad3ab844247f3c5b96bea25d73d/psutil-6.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649", size = 254444 }, ] [[package]] @@ -1287,55 +1414,55 @@ wheels = [ [[package]] name = "rapidfuzz" -version = "3.9.6" +version = "3.9.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/b0/e0756b5efe826c1bdf6442777cc924b41258685dcf372ee77399cc10408e/rapidfuzz-3.9.6.tar.gz", hash = "sha256:5cf2a7d621e4515fee84722e93563bf77ff2cbe832a77a48b81f88f9e23b9e8d", size = 1596107 } +sdist = { url = "https://files.pythonhosted.org/packages/17/ac/1f1bf726645d7740df2d1371380e35098bb8a460f482343cba1dd1668ab6/rapidfuzz-3.9.7.tar.gz", hash = "sha256:f1c7296534c1afb6f495aa95871f14ccdc197c6db42965854e483100df313030", size = 1596228 } wheels = [ - { url = "https://files.pythonhosted.org/packages/5e/55/5ba0016fe8fba98d8ff55832dd7d79f2d6b93fe27be7863ccf3f79366d76/rapidfuzz-3.9.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:52e4675f642fbc85632f691b67115a243cd4d2a47bdcc4a3d9a79e784518ff97", size = 2055435 }, - { url = "https://files.pythonhosted.org/packages/55/23/1d0c51c01fbff028ff5746a388edd610a591e76153fca72f6f7e68b5fc14/rapidfuzz-3.9.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1f93a2f13038700bd245b927c46a2017db3dcd4d4ff94687d74b5123689b873b", size = 1510617 }, - { url = "https://files.pythonhosted.org/packages/28/d6/8dd267f4377d8bf1698d891a28c24d417499724355f6a3541c0b5ab1c35d/rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b70500bca460264b8141d8040caee22e9cf0418c5388104ff0c73fb69ee28f", size = 1559930 }, - { url = "https://files.pythonhosted.org/packages/6a/3e/254fd9e2ce895480bc43a5a11a35d4825b11918d694c959cc0e214d842a9/rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1e037fb89f714a220f68f902fc6300ab7a33349f3ce8ffae668c3b3a40b0b06", size = 5964374 }, - { url = "https://files.pythonhosted.org/packages/d2/cd/3e555024d9168dbd732e919fb0f7d05c3f6809d6ed86042383efeb6f98a0/rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6792f66d59b86ccfad5e247f2912e255c85c575789acdbad8e7f561412ffed8a", size = 1825493 }, - { url = "https://files.pythonhosted.org/packages/32/5f/c47c511e2b174e80ea1091722359b4db7900e4987a4bcacffae6f27237c0/rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68d9cffe710b67f1969cf996983608cee4490521d96ea91d16bd7ea5dc80ea98", size = 1830053 }, - { url = "https://files.pythonhosted.org/packages/e9/85/88f1fd986714887ad4448c7b321c85b9aa5842df9deb606bcdfdfc35fae6/rapidfuzz-3.9.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63daaeeea76da17fa0bbe7fb05cba8ed8064bb1a0edf8360636557f8b6511961", size = 3384091 }, - { url = "https://files.pythonhosted.org/packages/cc/3f/9a941793dbc419a9e9aad742d8057c8440f191ab3758d1ce2c12e9f27ccd/rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d214e063bffa13e3b771520b74f674b22d309b5720d4df9918ff3e0c0f037720", size = 2458230 }, - { url = "https://files.pythonhosted.org/packages/9d/40/40b75226e0b45ba0212b8ce19996b8970fd3de4748341f6bdd0302b54856/rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ed443a2062460f44c0346cb9d269b586496b808c2419bbd6057f54061c9b9c75", size = 7239493 }, - { url = "https://files.pythonhosted.org/packages/df/62/47401ac22299f70a8231f7e7421b3f804cd716f6a24521ef172dec7afe01/rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:5b0c9b227ee0076fb2d58301c505bb837a290ae99ee628beacdb719f0626d749", size = 2837398 }, - { url = "https://files.pythonhosted.org/packages/59/f2/a3db1b31dc80d906528e03d213a9f9bd8c44547cb1cbf9a3c59649058c2e/rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:82c9722b7dfaa71e8b61f8c89fed0482567fb69178e139fe4151fc71ed7df782", size = 3386617 }, - { url = "https://files.pythonhosted.org/packages/5f/41/2d285edb31f718c81e3433a56142d5e606ba20d0997fcf57774042f79850/rapidfuzz-3.9.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c18897c95c0a288347e29537b63608a8f63a5c3cb6da258ac46fcf89155e723e", size = 4392081 }, - { url = "https://files.pythonhosted.org/packages/37/7b/d355309d5aa606dd91d91501a64c87db32e3d75b775950a19df8ec0288f0/rapidfuzz-3.9.6-cp311-cp311-win32.whl", hash = "sha256:3e910cf08944da381159587709daaad9e59d8ff7bca1f788d15928f3c3d49c2a", size = 1854906 }, - { url = "https://files.pythonhosted.org/packages/aa/bb/cdd512d40f8ea67692deee6b0da4f7235c6a0f9e126fdded32b62c5d91fe/rapidfuzz-3.9.6-cp311-cp311-win_amd64.whl", hash = "sha256:59c4a61fab676d37329fc3a671618a461bfeef53a4d0b8b12e3bc24a14e166f8", size = 1654104 }, - { url = "https://files.pythonhosted.org/packages/53/92/5014563b1e8f901f983f96606c6982ff4ed286a8ae4335b67012a4a50cf9/rapidfuzz-3.9.6-cp311-cp311-win_arm64.whl", hash = "sha256:8b4afea244102332973377fddbe54ce844d0916e1c67a5123432291717f32ffa", size = 855134 }, - { url = "https://files.pythonhosted.org/packages/df/f4/e8175a4ad862ede4caa8dd287d187d12db2f4eb426b00b030b1cb7f4d2dd/rapidfuzz-3.9.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:70591b28b218fff351b88cdd7f2359a01a71f9f7f5a2e465ce3715ed4b3c422b", size = 2053429 }, - { url = "https://files.pythonhosted.org/packages/22/a5/8c14e41bcdea3be343764de6ad464ff87300352f8e2d01064bf0f1809e9d/rapidfuzz-3.9.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee2d8355c7343c631a03e57540ea06e8717c19ecf5ff64ea07e0498f7f161457", size = 1506224 }, - { url = "https://files.pythonhosted.org/packages/75/92/51d74bdf539475d8c71df76da73d4609231254ac2499beb24efa78667b14/rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:708fb675de0f47b9635d1cc6fbbf80d52cb710d0a1abbfae5c84c46e3abbddc3", size = 1542825 }, - { url = "https://files.pythonhosted.org/packages/b9/7a/29bf00754308ba43eb6f95988445b86953b29bc780164f8961d0c3d67b89/rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d66c247c2d3bb7a9b60567c395a15a929d0ebcc5f4ceedb55bfa202c38c6e0c", size = 5858827 }, - { url = "https://files.pythonhosted.org/packages/0a/a3/1b5a2bb95e5b532fe571b6b0c8c4cf35893e748eac5cac2ae7d3c0f41d47/rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15146301b32e6e3d2b7e8146db1a26747919d8b13690c7f83a4cb5dc111b3a08", size = 1794607 }, - { url = "https://files.pythonhosted.org/packages/0e/42/7ee9c15087d6b7146e73e4650bfb8ddbbe2161a9edbe2b44be9ffb68a2f1/rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7a03da59b6c7c97e657dd5cd4bcaab5fe4a2affd8193958d6f4d938bee36679", size = 1818934 }, - { url = "https://files.pythonhosted.org/packages/15/30/0a4bc8b641e2374475c03d6c6ec6568303ac2070698c067c690daefd9b8f/rapidfuzz-3.9.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d2c2fe19e392dbc22695b6c3b2510527e2b774647e79936bbde49db7742d6f1", size = 3381282 }, - { url = "https://files.pythonhosted.org/packages/e1/45/6c9bbba66a5ada5679c0705375068337c2573a940443868cbcba5c909c07/rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:91aaee4c94cb45930684f583ffc4e7c01a52b46610971cede33586cf8a04a12e", size = 2425764 }, - { url = "https://files.pythonhosted.org/packages/74/b3/b02d002e643ec5f97278b6f04c2293b9b678249220f253b7e649a4e0df3a/rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3f5702828c10768f9281180a7ff8597da1e5002803e1304e9519dd0f06d79a85", size = 7176966 }, - { url = "https://files.pythonhosted.org/packages/3f/0d/52cd49cafb91fc0cc4e75e3beab7b16fffe62a6c66d5fb5d336b2deacda5/rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ccd1763b608fb4629a0b08f00b3c099d6395e67c14e619f6341b2c8429c2f310", size = 2800253 }, - { url = "https://files.pythonhosted.org/packages/4f/ee/82004bf9274566711b134bb2628bf878046a9212c798bd10f0138ad6cca9/rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc7a0d4b2cb166bc46d02c8c9f7551cde8e2f3c9789df3827309433ee9771163", size = 3345106 }, - { url = "https://files.pythonhosted.org/packages/d8/78/7008dcd6701cc84eb74fad6c743f03c33c7f41516d15a313fcd759b2d614/rapidfuzz-3.9.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7496f53d40560a58964207b52586783633f371683834a8f719d6d965d223a2eb", size = 4360019 }, - { url = "https://files.pythonhosted.org/packages/07/25/5de7013daac2eb7b18bc0123fa5d83ddbe5508673b14b9ca7e32f2be3cbe/rapidfuzz-3.9.6-cp312-cp312-win32.whl", hash = "sha256:5eb1a9272ca71bc72be5415c2fa8448a6302ea4578e181bb7da9db855b367df0", size = 1842659 }, - { url = "https://files.pythonhosted.org/packages/7b/81/bfd28ed4a5638b594985988921d19fd716f119dde93703d8545c1bcb8e7e/rapidfuzz-3.9.6-cp312-cp312-win_amd64.whl", hash = "sha256:0d21fc3c0ca507a1180152a6dbd129ebaef48facde3f943db5c1055b6e6be56a", size = 1648213 }, - { url = "https://files.pythonhosted.org/packages/8a/81/249ed13ce5cee9c9aa9c69656e2d78ed240534d478ebaada04930513820a/rapidfuzz-3.9.6-cp312-cp312-win_arm64.whl", hash = "sha256:43bb27a57c29dc5fa754496ba6a1a508480d21ae99ac0d19597646c16407e9f3", size = 849878 }, - { url = "https://files.pythonhosted.org/packages/d1/de/83b660bb054a3bd85f033a2521ba99ae65e49b95f3b18745cfcf68a94ae7/rapidfuzz-3.9.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:83a5ac6547a9d6eedaa212975cb8f2ce2aa07e6e30833b40e54a52b9f9999aa4", size = 2026087 }, - { url = "https://files.pythonhosted.org/packages/6f/f3/7b7f8ddb80562722c6cb86a3396ad6945c0003f36addbca610782fe7e113/rapidfuzz-3.9.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:10f06139142ecde67078ebc9a745965446132b998f9feebffd71acdf218acfcc", size = 1499413 }, - { url = "https://files.pythonhosted.org/packages/bd/e9/a37db9a3674b210d6ef21b15c66eb1585125d553ed5b73f6481dadf932c3/rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74720c3f24597f76c7c3e2c4abdff55f1664f4766ff5b28aeaa689f8ffba5fab", size = 1537241 }, - { url = "https://files.pythonhosted.org/packages/75/67/e111c7a11eafd70677d6688c36d93b54a43783119b16ee5591589a110ff9/rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2bce52b5c150878e558a0418c2b637fb3dbb6eb38e4eb27d24aa839920483e", size = 5877164 }, - { url = "https://files.pythonhosted.org/packages/80/58/ce20051fbbac74bc369d4ab3f450683ebf70e456474d6172ba9b6f6164f0/rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1611199f178793ca9a060c99b284e11f6d7d124998191f1cace9a0245334d219", size = 1766888 }, - { url = "https://files.pythonhosted.org/packages/8f/b4/afde433a48fb18f5d7ddf144ffb2b0b674f3f176a2aca89f2ea06fe54d4f/rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0308b2ad161daf502908a6e21a57c78ded0258eba9a8f5e2545e2dafca312507", size = 1819868 }, - { url = "https://files.pythonhosted.org/packages/53/47/089d2d8a27c4e90dd4dfb532d31bc873537fcc479874e9909a9018156855/rapidfuzz-3.9.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eda91832201b86e3b70835f91522587725bec329ec68f2f7faf5124091e5ca7", size = 3361094 }, - { url = "https://files.pythonhosted.org/packages/95/a5/f5e1fc00485f45ed17803f91f7877fa07b0fb4006ff42cfebd7355ad1bdc/rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ece873c093aedd87fc07c2a7e333d52e458dc177016afa1edaf157e82b6914d8", size = 2421352 }, - { url = "https://files.pythonhosted.org/packages/57/fa/0d6573980251fb63147a35be8f4fae962d79ebbe4b675fdaf0cf16726aa0/rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d97d3c9d209d5c30172baea5966f2129e8a198fec4a1aeb2f92abb6e82a2edb1", size = 7190683 }, - { url = "https://files.pythonhosted.org/packages/71/50/2f866735f788d565a2ed6d113a54a410b4a412b46cb399e3ae466e72730f/rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6c4550d0db4931f5ebe9f0678916d1b06f06f5a99ba0b8a48b9457fd8959a7d4", size = 2791255 }, - { url = "https://files.pythonhosted.org/packages/a2/90/7c36906695b216bf489cd234d95e5e00f06f976054ce3c441085a5ae650f/rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b6b8dd4af6324fc325d9483bec75ecf9be33e590928c9202d408e4eafff6a0a6", size = 3341004 }, - { url = "https://files.pythonhosted.org/packages/16/2b/15f6df84ef774457fd77a80436154e8fc6c903bfc997490a275fca84adda/rapidfuzz-3.9.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:16122ae448bc89e2bea9d81ce6cb0f751e4e07da39bd1e70b95cae2493857853", size = 4355422 }, - { url = "https://files.pythonhosted.org/packages/7f/3b/e593d8f0b7bb2c1cb00514552056a4b61000d2d8f4fd24e016fdd2e1afe1/rapidfuzz-3.9.6-cp313-cp313-win32.whl", hash = "sha256:71cc168c305a4445109cd0d4925406f6e66bcb48fde99a1835387c58af4ecfe9", size = 1840420 }, - { url = "https://files.pythonhosted.org/packages/fe/09/d25939dfe7eea5e4a474dfebd60073acd792621d42a9ffe7534627c8ad26/rapidfuzz-3.9.6-cp313-cp313-win_amd64.whl", hash = "sha256:59ee78f2ecd53fef8454909cda7400fe2cfcd820f62b8a5d4dfe930102268054", size = 1645331 }, - { url = "https://files.pythonhosted.org/packages/d8/26/6eda9e43dd5b0833feb4cf9ea0ad4e46b07c4811d8b8815a8517b379c640/rapidfuzz-3.9.6-cp313-cp313-win_arm64.whl", hash = "sha256:58b4ce83f223605c358ae37e7a2d19a41b96aa65b1fede99cc664c9053af89ac", size = 848759 }, + { url = "https://files.pythonhosted.org/packages/18/dd/530be3f5fb7ad43cc8ccce2cb391146602e11b5df1f1e948adfa7bae0802/rapidfuzz-3.9.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d098ce6162eb5e48fceb0745455bc950af059df6113eec83e916c129fca11408", size = 2055425 }, + { url = "https://files.pythonhosted.org/packages/60/e5/c919e2257c8c3ee43155f580bb86682d3b1f16256dc3622ca2e416068d67/rapidfuzz-3.9.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:048d55d36c02c6685a2b2741688503c3d15149694506655b6169dcfd3b6c2585", size = 1510614 }, + { url = "https://files.pythonhosted.org/packages/06/09/efe65f1b01e1778e57b8f29e9f8d39c8203c6022698a246f6c57e8471000/rapidfuzz-3.9.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c33211cfff9aec425bb1bfedaf94afcf337063aa273754f22779d6dadebef4c2", size = 1559939 }, + { url = "https://files.pythonhosted.org/packages/c1/f0/344a41ac82970e0a7b88821f9cfd3b46779db88089c146c9937e4bbfcc6c/rapidfuzz-3.9.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6d9db2fa4e9be171e9bb31cf2d2575574774966b43f5b951062bb2e67885852", size = 5964378 }, + { url = "https://files.pythonhosted.org/packages/83/31/3194dc0262dfa3c3bd585e6aac95af21c78e26981a9b19da08a4fd97adda/rapidfuzz-3.9.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4e049d5ad61448c9a020d1061eba20944c4887d720c4069724beb6ea1692507", size = 1825499 }, + { url = "https://files.pythonhosted.org/packages/e6/3e/ea01677779779819c083580e501aba1773f4fbcd7082fc52f110e73c09f5/rapidfuzz-3.9.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cfa74aac64c85898b93d9c80bb935a96bf64985e28d4ee0f1a3d1f3bf11a5106", size = 1830054 }, + { url = "https://files.pythonhosted.org/packages/8a/c4/a06602d0bf830414dd6b458785d868252d6f2cbe1a0a1f57a62cfab1a9ec/rapidfuzz-3.9.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:965693c2e9efd425b0f059f5be50ef830129f82892fa1858e220e424d9d0160f", size = 3384099 }, + { url = "https://files.pythonhosted.org/packages/87/f3/787a2950df7cc23eac5a89b9ee47cf833a9b5759f59b90a50d351467c257/rapidfuzz-3.9.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8501000a5eb8037c4b56857724797fe5a8b01853c363de91c8d0d0ad56bef319", size = 2458238 }, + { url = "https://files.pythonhosted.org/packages/41/85/e3531a970ae92dfe8c1c8060920d83ba083f4d56cd0953f444aaa15af9a9/rapidfuzz-3.9.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d92c552c6b7577402afdd547dcf5d31ea6c8ae31ad03f78226e055cfa37f3c6", size = 7239492 }, + { url = "https://files.pythonhosted.org/packages/b3/5f/08d5637681c80c2d5ae20d2f1e5be9e37351e8313359c2a00770efa14be7/rapidfuzz-3.9.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1ee2086f490cb501d86b7e386c1eb4e3a0ccbb0c99067089efaa8c79012c8952", size = 2837408 }, + { url = "https://files.pythonhosted.org/packages/0a/54/6f44905e09fc0136621ffa914737326aa3b6b9b6c24f3565af1c63cf3f3f/rapidfuzz-3.9.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1de91e7fd7f525e10ea79a6e62c559d1b0278ec097ad83d9da378b6fab65a265", size = 3386607 }, + { url = "https://files.pythonhosted.org/packages/77/a3/ac9b99d96a91b5d2ffa920481cbd94fcc73a042aee0b17ba627a146e7199/rapidfuzz-3.9.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a4da514d13f4433e16960a17f05b67e0af30ac771719c9a9fb877e5004f74477", size = 4392097 }, + { url = "https://files.pythonhosted.org/packages/f0/cc/67f959d95e556f1925b4c9211fb7f63c0df60610c28c2c618b48df9ff1d6/rapidfuzz-3.9.7-cp311-cp311-win32.whl", hash = "sha256:a40184c67db8252593ec518e17fb8a6e86d7259dc9f2d6c0bf4ff4db8cf1ad4b", size = 1857658 }, + { url = "https://files.pythonhosted.org/packages/64/d9/c86f7b247b1603cae62d5d39cbc12f5baaeb34e80fd00c7211fe43157a66/rapidfuzz-3.9.7-cp311-cp311-win_amd64.whl", hash = "sha256:c4f28f1930b09a2c300357d8465b388cecb7e8b2f454a5d5425561710b7fd07f", size = 1662871 }, + { url = "https://files.pythonhosted.org/packages/67/43/ca9cda58a08808b891866afecf567f5dd317c72816fe3df50cb87649d625/rapidfuzz-3.9.7-cp311-cp311-win_arm64.whl", hash = "sha256:675b75412a943bb83f1f53e2e54fd18c80ef15ed642dc6eb0382d1949419d904", size = 856548 }, + { url = "https://files.pythonhosted.org/packages/c5/69/3382886cf73774d6b4085e177e665326ee065d806ed775aa61e5d9e5cd8a/rapidfuzz-3.9.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1ef6a1a8f0b12f8722f595f15c62950c9a02d5abc64742561299ffd49f6c6944", size = 2053430 }, + { url = "https://files.pythonhosted.org/packages/33/58/d67551479432be743b9e36eaf46e8ca6a76a8edfeb060137856576836129/rapidfuzz-3.9.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:32532af1d70c6ec02ea5ac7ee2766dfff7c8ae8c761abfe8da9e527314e634e8", size = 1506225 }, + { url = "https://files.pythonhosted.org/packages/f0/d5/294e26070cc5f3ad079c001606f6fcccbd6e0d7e8b58dd1c9d4048971706/rapidfuzz-3.9.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae1a38bade755aa9dd95a81cda949e1bf9cd92b79341ccc5e2189c9e7bdfc5ec", size = 1542826 }, + { url = "https://files.pythonhosted.org/packages/24/4d/3e7f2afdb4571031e2b122d5d7a029dbc3e98a54d11ef5b20be142dbc688/rapidfuzz-3.9.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d73ee2df41224c87336448d279b5b6a3a75f36e41dd3dcf538c0c9cce36360d8", size = 5858829 }, + { url = "https://files.pythonhosted.org/packages/c3/37/71c46506ec0e71a3508fc1ea23a44c34f948b8e21057dd5cc23ebd252267/rapidfuzz-3.9.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be3a1fc3e2ab3bdf93dc0c83c00acca8afd2a80602297d96cf4a0ba028333cdf", size = 1794619 }, + { url = "https://files.pythonhosted.org/packages/5b/66/c62120f3d559136eb5d9504d0a1665f3d3ba63f0fe936360a605de8b3a4a/rapidfuzz-3.9.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:603f48f621272a448ff58bb556feb4371252a02156593303391f5c3281dfaeac", size = 1818937 }, + { url = "https://files.pythonhosted.org/packages/1e/bf/4717fb73e06c717d25472433420dec570cf8ee283a23529a643eb6317284/rapidfuzz-3.9.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:268f8e1ca50fc61c0736f3fe9d47891424adf62d96ed30196f30f4bd8216b41f", size = 3381291 }, + { url = "https://files.pythonhosted.org/packages/e7/33/d3dce4519a2d2d0c52174780aba6908ecb7c01182d8c3411a30d85849635/rapidfuzz-3.9.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f8bf3f0d02935751d8660abda6044821a861f6229f7d359f98bcdcc7e66c39b", size = 2425772 }, + { url = "https://files.pythonhosted.org/packages/30/72/0fb88a4e5d500cfc15bcc1d3c854fe53cf6242ba917a0626a615a1f5c579/rapidfuzz-3.9.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b997ff3b39d4cee9fb025d6c46b0a24bd67595ce5a5b652a97fb3a9d60beb651", size = 7176976 }, + { url = "https://files.pythonhosted.org/packages/61/21/82acba73a147dd009aef4603da95ff8cbacb644e79f409244ee65fd5a299/rapidfuzz-3.9.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca66676c8ef6557f9b81c5b2b519097817a7c776a6599b8d6fcc3e16edd216fe", size = 2800261 }, + { url = "https://files.pythonhosted.org/packages/73/3a/edccc360599fe6153472d4f2452cff65dd45422453141504d5002e1ce450/rapidfuzz-3.9.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:35d3044cb635ca6b1b2b7b67b3597bd19f34f1753b129eb6d2ae04cf98cd3945", size = 3345108 }, + { url = "https://files.pythonhosted.org/packages/38/00/e7b2656faa7a4ec6760299ab973d37fa9cae6ae91f6e3ca3987577665b99/rapidfuzz-3.9.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5a93c9e60904cb76e7aefef67afffb8b37c4894f81415ed513db090f29d01101", size = 4360023 }, + { url = "https://files.pythonhosted.org/packages/0d/c5/a9ab2e06a6661aa6f3955b478e3c6c6c2ebd9016570d6a34e88f41b4e59f/rapidfuzz-3.9.7-cp312-cp312-win32.whl", hash = "sha256:579d107102c0725f7c79b4e79f16d3cf4d7c9208f29c66b064fa1fd4641d5155", size = 1842729 }, + { url = "https://files.pythonhosted.org/packages/70/e6/4aa3e901452f54c201435da7f61a896daa16dce7899d4aebb856666ddb6b/rapidfuzz-3.9.7-cp312-cp312-win_amd64.whl", hash = "sha256:953b3780765c8846866faf891ee4290f6a41a6dacf4fbcd3926f78c9de412ca6", size = 1655171 }, + { url = "https://files.pythonhosted.org/packages/0d/16/8fadcef053e7658e731e2155ca795279c5159a28035891324f482e4ff6fc/rapidfuzz-3.9.7-cp312-cp312-win_arm64.whl", hash = "sha256:7c20c1474b068c4bd45bf2fd0ad548df284f74e9a14a68b06746c56e3aa8eb70", size = 851234 }, + { url = "https://files.pythonhosted.org/packages/78/5c/7a2f42b4610a1edf23aca94f609bf3390671e3b0e1bb42dab32274699b23/rapidfuzz-3.9.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fde81b1da9a947f931711febe2e2bee694e891f6d3e6aa6bc02c1884702aea19", size = 2026090 }, + { url = "https://files.pythonhosted.org/packages/93/60/9cfaac357675e8459f3360cd300cbb34dfa58061f8ad3acab0b5bf474c6f/rapidfuzz-3.9.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:47e92c155a14f44511ea8ebcc6bc1535a1fe8d0a7d67ad3cc47ba61606df7bcf", size = 1499416 }, + { url = "https://files.pythonhosted.org/packages/f2/53/1c2a0a525f709bb0cb0891c51d914a08e8f1e2f66078d43c17586f43610a/rapidfuzz-3.9.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8772b745668260c5c4d069c678bbaa68812e6c69830f3771eaad521af7bc17f8", size = 1537254 }, + { url = "https://files.pythonhosted.org/packages/cc/0e/4c7e85cc9f10ea005c3695af3f6ba47e5796fbe28a7700170cb09b266156/rapidfuzz-3.9.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:578302828dd97ee2ba507d2f71d62164e28d2fc7bc73aad0d2d1d2afc021a5d5", size = 5877170 }, + { url = "https://files.pythonhosted.org/packages/07/71/548af38b262bc4494266a7e26250e22ebd686203b5c9269e2878383b34fc/rapidfuzz-3.9.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc3e6081069eea61593f1d6839029da53d00c8c9b205c5534853eaa3f031085c", size = 1766905 }, + { url = "https://files.pythonhosted.org/packages/9c/ef/96159e7e0236efe9ffb78d7b02cee1b6a02dede9c23ede56ae4454031348/rapidfuzz-3.9.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0b1c2d504eddf97bc0f2eba422c8915576dbf025062ceaca2d68aecd66324ad9", size = 1819869 }, + { url = "https://files.pythonhosted.org/packages/75/8d/73d521da17f32ad389e8593f9d3d5df06b889ed2d261ca5a5bed657a13e8/rapidfuzz-3.9.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb76e5a21034f0307c51c5a2fc08856f698c53a4c593b17d291f7d6e9d09ca3", size = 3361102 }, + { url = "https://files.pythonhosted.org/packages/3a/bc/394837f81c377aad90cc6d5e0fa138da91101a63cac31b31f2ca85a65c7c/rapidfuzz-3.9.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d4ba2318ef670ce505f42881a5d2af70f948124646947341a3c6ccb33cd70369", size = 2421346 }, + { url = "https://files.pythonhosted.org/packages/96/fa/daf98b62dc5e6b6e094d6d17f0b23340463f1b4c9e556249103acba4ee7c/rapidfuzz-3.9.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:057bb03f39e285047d7e9412e01ecf31bb2d42b9466a5409d715d587460dd59b", size = 7190698 }, + { url = "https://files.pythonhosted.org/packages/dc/da/d548faf4d8cf14c0c58bd2ea91d27d3f0137dd2a7973eece7a561e0b9a2c/rapidfuzz-3.9.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a8feac9006d5c9758438906f093befffc4290de75663dbb2098461df7c7d28dd", size = 2791263 }, + { url = "https://files.pythonhosted.org/packages/35/17/5cb93655581eccf105c006c3d1918e9e7f359df6b2dbe0fbb012e4a4a4cd/rapidfuzz-3.9.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:95b8292383e717e10455f2c917df45032b611141e43d1adf70f71b1566136b11", size = 3341012 }, + { url = "https://files.pythonhosted.org/packages/a5/77/3486e011a9977ca5f070469f1ff38c7e38877e5ca4299368c85af48e1189/rapidfuzz-3.9.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e9fbf659537d246086d0297628b3795dc3e4a384101ecc01e5791c827b8d7345", size = 4355424 }, + { url = "https://files.pythonhosted.org/packages/6d/c7/a4add18324590be9cf311763baf0b3afe24a3065f54604052e6141161a45/rapidfuzz-3.9.7-cp313-cp313-win32.whl", hash = "sha256:1dc516ac6d32027be2b0196bedf6d977ac26debd09ca182376322ad620460feb", size = 1840822 }, + { url = "https://files.pythonhosted.org/packages/6e/3c/cc468b42740bb77dc94dd92cd29cf18ea4301a6f0cea3663d3291d97800a/rapidfuzz-3.9.7-cp313-cp313-win_amd64.whl", hash = "sha256:b4f86e09d3064dca0b014cd48688964036a904a2d28048f00c8f4640796d06a8", size = 1652011 }, + { url = "https://files.pythonhosted.org/packages/96/c7/b1fbae97a9e53ae833d477653bf5ab095b14338da0e79db4ae4bbf985ebb/rapidfuzz-3.9.7-cp313-cp313-win_arm64.whl", hash = "sha256:19c64d8ddb2940b42a4567b23f1681af77f50a5ff6c9b8e85daba079c210716e", size = 850094 }, ] [[package]] @@ -1349,7 +1476,7 @@ wheels = [ [[package]] name = "red-discordbot" -version = "3.5.13" +version = "3.5.14" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -1374,6 +1501,7 @@ dependencies = [ { name = "orjson" }, { name = "packaging" }, { name = "platformdirs" }, + { name = "propcache" }, { name = "psutil" }, { name = "pygments" }, { name = "python-dateutil" }, @@ -1389,9 +1517,9 @@ dependencies = [ { name = "yarl" }, { name = "zipp", marker = "python_full_version >= '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e2/d2/1055cd2db6cec6278046f71ed486d852ce7578fbff5579d3dd0c147cf7e0/red_discordbot-3.5.13.tar.gz", hash = "sha256:7708dcc8203f2487616e95eba2aa1a6e5d78fbb03975c0b96587b0548c0f5d5b", size = 3661865 } +sdist = { url = "https://files.pythonhosted.org/packages/ea/b6/b680024b91c8dbf89c66aa1f43a7599b155e6e69101641a9da66d5907011/red_discordbot-3.5.14.tar.gz", hash = "sha256:b603b59a75429fa37bf6bc303f08a95e725c339599ad044278bed8337429c110", size = 3681606 } wheels = [ - { url = "https://files.pythonhosted.org/packages/98/67/2908f01ddb83dc5cbf6cd37f1ae6fc70cad00871de763f4ee10d2a7a219d/Red_DiscordBot-3.5.13-py3-none-any.whl", hash = "sha256:bd598a91c7504503b03b0d10f8ad1f230403fbab981a78f00461be61d458c285", size = 5754615 }, + { url = "https://files.pythonhosted.org/packages/9d/0a/5cb23863863ed70bc60937fe16f4626b9cb22fe0afd74ac67a0f543ed33a/Red_DiscordBot-3.5.14-py3-none-any.whl", hash = "sha256:9be0806c21cf83c0e972b331583b088786b5f3c2d8221eefab5adbf1ac9b761f", size = 5772233 }, ] [[package]] @@ -1478,15 +1606,15 @@ wheels = [ [[package]] name = "rich" -version = "13.8.0" +version = "13.9.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cf/60/5959113cae0ce512cf246a6871c623117330105a0d5f59b4e26138f2c9cc/rich-13.8.0.tar.gz", hash = "sha256:a5ac1f1cd448ade0d59cc3356f7db7a7ccda2c8cbae9c7a90c28ff463d3e91f4", size = 222072 } +sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/d9/c2a126eeae791e90ea099d05cb0515feea3688474b978343f3cdcfe04523/rich-13.8.0-py3-none-any.whl", hash = "sha256:2e85306a063b9492dffc86278197a60cbece75bcb766022f3436f567cae11bdc", size = 241597 }, + { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, ] [[package]] @@ -1535,6 +1663,7 @@ dependencies = [ { name = "numpy" }, { name = "phx-class-registry" }, { name = "pillow" }, + { name = "pip" }, { name = "py-dactyl" }, { name = "pydantic" }, { name = "red-discordbot" }, @@ -1573,9 +1702,10 @@ requires-dist = [ { name = "numpy", specifier = ">=2.1.2" }, { name = "phx-class-registry", specifier = ">=5.0.0" }, { name = "pillow", specifier = ">=10.4.0" }, + { name = "pip", specifier = ">=24.3.1" }, { name = "py-dactyl", git = "https://github.com/cswimr/pydactyl" }, { name = "pydantic", specifier = ">=2.9.2" }, - { name = "red-discordbot", specifier = ">=3.5.13" }, + { name = "red-discordbot", specifier = ">=3.5.14" }, { name = "websockets", specifier = ">=13.1" }, ] @@ -1588,11 +1718,11 @@ dev = [ [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } wheels = [ - { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 }, + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, ] [[package]] @@ -1665,22 +1795,28 @@ wheels = [ [[package]] name = "uvloop" -version = "0.20.0" +version = "0.21.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bc/f1/dc9577455e011ad43d9379e836ee73f40b4f99c02946849a44f7ae64835e/uvloop-0.20.0.tar.gz", hash = "sha256:4603ca714a754fc8d9b197e325db25b2ea045385e8a3ad05d3463de725fdf469", size = 2329938 } +sdist = { url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", size = 2492741 } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/bf/45828beccf685b7ed9638d9b77ef382b470c6ca3b5bff78067e02ffd5663/uvloop-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e50289c101495e0d1bb0bfcb4a60adde56e32f4449a67216a1ab2750aa84f037", size = 1320593 }, - { url = "https://files.pythonhosted.org/packages/27/c0/3c24e50bee7802a2add96ca9f0d5eb0ebab07e0a5615539d38aeb89499b9/uvloop-0.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e237f9c1e8a00e7d9ddaa288e535dc337a39bcbf679f290aee9d26df9e72bce9", size = 736676 }, - { url = "https://files.pythonhosted.org/packages/83/ce/ffa3c72954eae36825acfafd2b6a9221d79abd2670c0d25e04d6ef4a2007/uvloop-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:746242cd703dc2b37f9d8b9f173749c15e9a918ddb021575a0205ec29a38d31e", size = 3494573 }, - { url = "https://files.pythonhosted.org/packages/46/6d/4caab3a36199ba52b98d519feccfcf48921d7a6649daf14a93c7e77497e9/uvloop-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82edbfd3df39fb3d108fc079ebc461330f7c2e33dbd002d146bf7c445ba6e756", size = 3489932 }, - { url = "https://files.pythonhosted.org/packages/e4/4f/49c51595bd794945c88613df88922c38076eae2d7653f4624aa6f4980b07/uvloop-0.20.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:80dc1b139516be2077b3e57ce1cb65bfed09149e1d175e0478e7a987863b68f0", size = 4185596 }, - { url = "https://files.pythonhosted.org/packages/b8/94/7e256731260d313f5049717d1c4582d52a3b132424c95e16954a50ab95d3/uvloop-0.20.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f44af67bf39af25db4c1ac27e82e9665717f9c26af2369c404be865c8818dcf", size = 4185746 }, - { url = "https://files.pythonhosted.org/packages/2d/64/31cbd379d6e260ac8de3f672f904e924f09715c3f192b09f26cc8e9f574c/uvloop-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4b75f2950ddb6feed85336412b9a0c310a2edbcf4cf931aa5cfe29034829676d", size = 1324302 }, - { url = "https://files.pythonhosted.org/packages/1e/6b/9207e7177ff30f78299401f2e1163ea41130d4fd29bcdc6d12572c06b728/uvloop-0.20.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:77fbc69c287596880ecec2d4c7a62346bef08b6209749bf6ce8c22bbaca0239e", size = 738105 }, - { url = "https://files.pythonhosted.org/packages/c1/ba/b64b10f577519d875992dc07e2365899a1a4c0d28327059ce1e1bdfb6854/uvloop-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6462c95f48e2d8d4c993a2950cd3d31ab061864d1c226bbf0ee2f1a8f36674b9", size = 4090658 }, - { url = "https://files.pythonhosted.org/packages/0a/f8/5ceea6876154d926604f10c1dd896adf9bce6d55a55911364337b8a5ed8d/uvloop-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:649c33034979273fa71aa25d0fe120ad1777c551d8c4cd2c0c9851d88fcb13ab", size = 4173357 }, - { url = "https://files.pythonhosted.org/packages/18/b2/117ab6bfb18274753fbc319607bf06e216bd7eea8be81d5bac22c912d6a7/uvloop-0.20.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a609780e942d43a275a617c0839d85f95c334bad29c4c0918252085113285b5", size = 4029868 }, - { url = "https://files.pythonhosted.org/packages/6f/52/deb4be09060637ef4752adaa0b75bf770c20c823e8108705792f99cd4a6f/uvloop-0.20.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aea15c78e0d9ad6555ed201344ae36db5c63d428818b4b2a42842b3870127c00", size = 4115980 }, + { url = "https://files.pythonhosted.org/packages/57/a7/4cf0334105c1160dd6819f3297f8700fda7fc30ab4f61fbf3e725acbc7cc/uvloop-0.21.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8", size = 1447410 }, + { url = "https://files.pythonhosted.org/packages/8c/7c/1517b0bbc2dbe784b563d6ab54f2ef88c890fdad77232c98ed490aa07132/uvloop-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0", size = 805476 }, + { url = "https://files.pythonhosted.org/packages/ee/ea/0bfae1aceb82a503f358d8d2fa126ca9dbdb2ba9c7866974faec1cb5875c/uvloop-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e", size = 3960855 }, + { url = "https://files.pythonhosted.org/packages/8a/ca/0864176a649838b838f36d44bf31c451597ab363b60dc9e09c9630619d41/uvloop-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb", size = 3973185 }, + { url = "https://files.pythonhosted.org/packages/30/bf/08ad29979a936d63787ba47a540de2132169f140d54aa25bc8c3df3e67f4/uvloop-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6", size = 3820256 }, + { url = "https://files.pythonhosted.org/packages/da/e2/5cf6ef37e3daf2f06e651aae5ea108ad30df3cb269102678b61ebf1fdf42/uvloop-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d", size = 3937323 }, + { url = "https://files.pythonhosted.org/packages/8c/4c/03f93178830dc7ce8b4cdee1d36770d2f5ebb6f3d37d354e061eefc73545/uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", size = 1471284 }, + { url = "https://files.pythonhosted.org/packages/43/3e/92c03f4d05e50f09251bd8b2b2b584a2a7f8fe600008bcc4523337abe676/uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2", size = 821349 }, + { url = "https://files.pythonhosted.org/packages/a6/ef/a02ec5da49909dbbfb1fd205a9a1ac4e88ea92dcae885e7c961847cd51e2/uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", size = 4580089 }, + { url = "https://files.pythonhosted.org/packages/06/a7/b4e6a19925c900be9f98bec0a75e6e8f79bb53bdeb891916609ab3958967/uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", size = 4693770 }, + { url = "https://files.pythonhosted.org/packages/ce/0c/f07435a18a4b94ce6bd0677d8319cd3de61f3a9eeb1e5f8ab4e8b5edfcb3/uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", size = 4451321 }, + { url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", size = 4659022 }, + { url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", size = 1468123 }, + { url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", size = 819325 }, + { url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", size = 4582806 }, + { url = "https://files.pythonhosted.org/packages/d2/19/f5b78616566ea68edd42aacaf645adbf71fbd83fc52281fba555dc27e3f1/uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", size = 4701068 }, + { url = "https://files.pythonhosted.org/packages/47/57/66f061ee118f413cd22a656de622925097170b9380b30091b78ea0c6ea75/uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", size = 4454428 }, + { url = "https://files.pythonhosted.org/packages/63/9a/0962b05b308494e3202d3f794a6e85abe471fe3cafdbcf95c2e8c713aabd/uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", size = 4660018 }, ] [[package]] @@ -1775,52 +1911,71 @@ wheels = [ [[package]] name = "yarl" -version = "1.9.4" +version = "1.15.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, { name = "multidict" }, + { name = "propcache" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e0/ad/bedcdccbcbf91363fd425a948994f3340924145c2bc8ccb296f4a1e52c28/yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf", size = 141869 } +sdist = { url = "https://files.pythonhosted.org/packages/06/e1/d5427a061819c9f885f58bb0467d02a523f1aec19f9e5f9c82ce950d90d3/yarl-1.15.2.tar.gz", hash = "sha256:a39c36f4218a5bb668b4f06874d676d35a035ee668e6e7e3538835c703634b84", size = 169318 } wheels = [ - { url = "https://files.pythonhosted.org/packages/12/65/4c7f3676209a569405c9f0f492df2bc3a387c253f5d906e36944fdd12277/yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099", size = 132836 }, - { url = "https://files.pythonhosted.org/packages/3b/c5/81e3dbf5271ab1510860d2ae7a704ef43f93f7cb9326bf7ebb1949a7260b/yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c", size = 83215 }, - { url = "https://files.pythonhosted.org/packages/20/3d/7dabf580dfc0b588e48830486b488858122b10a61f33325e0d7cf1d6180b/yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0", size = 81237 }, - { url = "https://files.pythonhosted.org/packages/38/45/7c669999f5d350f4f8f74369b94e0f6705918eee18e38610bfe44af93d4f/yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525", size = 324181 }, - { url = "https://files.pythonhosted.org/packages/50/49/aa04effe2876cced8867bf9d89b620acf02b733c62adfe22a8218c35d70b/yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8", size = 339412 }, - { url = "https://files.pythonhosted.org/packages/7d/95/4310771fb9c71599d8466f43347ac18fafd501621e65b93f4f4f16899b1d/yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9", size = 337973 }, - { url = "https://files.pythonhosted.org/packages/9f/ea/94ad7d8299df89844e666e4aa8a0e9b88e02416cd6a7dd97969e9eae5212/yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42", size = 328126 }, - { url = "https://files.pythonhosted.org/packages/6d/be/9d4885e2725f5860833547c9e4934b6e0f44a355b24ffc37957264761e3e/yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe", size = 316677 }, - { url = "https://files.pythonhosted.org/packages/4a/70/5c744d67cad3d093e233cb02f37f2830cb89abfcbb7ad5b5af00ff21d14d/yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce", size = 324243 }, - { url = "https://files.pythonhosted.org/packages/c2/80/8b38d8fed958ac37afb8b81a54bf4f767b107e2c2004dab165edb58fc51b/yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9", size = 318099 }, - { url = "https://files.pythonhosted.org/packages/59/50/715bbc7bda65291f9295e757f67854206f4d8be9746d39187724919ac14d/yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572", size = 334924 }, - { url = "https://files.pythonhosted.org/packages/a8/af/ca9962488027576d7162878a1864cbb1275d298af986ce96bdfd4807d7b2/yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958", size = 335060 }, - { url = "https://files.pythonhosted.org/packages/28/c7/249a3a903d500ca7369eb542e2847a14f12f249638dcc10371db50cd17ff/yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98", size = 326689 }, - { url = "https://files.pythonhosted.org/packages/ec/0c/f02dd0b875a7a460f95dc7cf18983ed43c693283d6ab92e0ad71b9e0de8f/yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31", size = 70407 }, - { url = "https://files.pythonhosted.org/packages/27/41/945ae9a80590e4fb0be166863c6e63d75e4b35789fa3a61ff1dbdcdc220f/yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1", size = 76719 }, - { url = "https://files.pythonhosted.org/packages/7b/cd/a921122610dedfed94e494af18e85aae23e93274c00ca464cfc591c8f4fb/yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81", size = 129561 }, - { url = "https://files.pythonhosted.org/packages/7c/a0/887c93020c788f249c24eaab288c46e5fed4d2846080eaf28ed3afc36e8d/yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142", size = 81595 }, - { url = "https://files.pythonhosted.org/packages/54/99/ed3c92c38f421ba6e36caf6aa91c34118771d252dce800118fa2f44d7962/yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074", size = 79400 }, - { url = "https://files.pythonhosted.org/packages/ea/45/65801be625ef939acc8b714cf86d4a198c0646e80dc8970359d080c47204/yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129", size = 317397 }, - { url = "https://files.pythonhosted.org/packages/06/91/9696601a8ba674c8f0c15035cc9e94ca31f541330364adcfd5a399f598bf/yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2", size = 327246 }, - { url = "https://files.pythonhosted.org/packages/da/3e/bf25177b3618889bf067aacf01ef54e910cd569d14e2f84f5e7bec23bb82/yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78", size = 327321 }, - { url = "https://files.pythonhosted.org/packages/28/1c/bdb3411467b805737dd2720b85fd082e49f59bf0cc12dc1dfcc80ab3d274/yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4", size = 322424 }, - { url = "https://files.pythonhosted.org/packages/41/e9/53bc89f039df2824a524a2aa03ee0bfb8f0585b08949e7521f5eab607085/yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0", size = 310868 }, - { url = "https://files.pythonhosted.org/packages/79/cd/a78c3b0304a4a970b5ae3993f4f5f649443bc8bfa5622f244aed44c810ed/yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51", size = 323452 }, - { url = "https://files.pythonhosted.org/packages/2e/5e/1c78eb05ae0efae08498fd7ab939435a29f12c7f161732e7fe327e5b8ca1/yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff", size = 313554 }, - { url = "https://files.pythonhosted.org/packages/04/e0/0029563a8434472697aebb269fdd2ffc8a19e3840add1d5fa169ec7c56e3/yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7", size = 331029 }, - { url = "https://files.pythonhosted.org/packages/de/1b/7e6b1ad42ccc0ed059066a7ae2b6fd4bce67795d109a99ccce52e9824e96/yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc", size = 333839 }, - { url = "https://files.pythonhosted.org/packages/85/8a/c364d6e2eeb4e128a5ee9a346fc3a09aa76739c0c4e2a7305989b54f174b/yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10", size = 328251 }, - { url = "https://files.pythonhosted.org/packages/ec/9d/0da94b33b9fb89041e10f95a14a55b0fef36c60b6a1d5ff85a0c2ecb1a97/yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7", size = 70195 }, - { url = "https://files.pythonhosted.org/packages/c5/f4/2fdc5a11503bc61818243653d836061c9ce0370e2dd9ac5917258a007675/yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984", size = 76397 }, - { url = "https://files.pythonhosted.org/packages/4d/05/4d79198ae568a92159de0f89e710a8d19e3fa267b719a236582eee921f4a/yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad", size = 31638 }, + { url = "https://files.pythonhosted.org/packages/4a/59/3ae125c97a2a8571ea16fdf59fcbd288bc169e0005d1af9946a90ea831d9/yarl-1.15.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9fcda20b2de7042cc35cf911702fa3d8311bd40055a14446c1e62403684afdc5", size = 136492 }, + { url = "https://files.pythonhosted.org/packages/f9/2b/efa58f36b582db45b94c15e87803b775eb8a4ca0db558121a272e67f3564/yarl-1.15.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0545de8c688fbbf3088f9e8b801157923be4bf8e7b03e97c2ecd4dfa39e48e0e", size = 88614 }, + { url = "https://files.pythonhosted.org/packages/82/69/eb73c0453a2ff53194df485dc7427d54e6cb8d1180fcef53251a8e24d069/yarl-1.15.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fbda058a9a68bec347962595f50546a8a4a34fd7b0654a7b9697917dc2bf810d", size = 86607 }, + { url = "https://files.pythonhosted.org/packages/48/4e/89beaee3a4da0d1c6af1176d738cff415ff2ad3737785ee25382409fe3e3/yarl-1.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1ac2bc069f4a458634c26b101c2341b18da85cb96afe0015990507efec2e417", size = 334077 }, + { url = "https://files.pythonhosted.org/packages/da/e8/8fcaa7552093f94c3f327783e2171da0eaa71db0c267510898a575066b0f/yarl-1.15.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd126498171f752dd85737ab1544329a4520c53eed3997f9b08aefbafb1cc53b", size = 347365 }, + { url = "https://files.pythonhosted.org/packages/be/fa/dc2002f82a89feab13a783d3e6b915a3a2e0e83314d9e3f6d845ee31bfcc/yarl-1.15.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3db817b4e95eb05c362e3b45dafe7144b18603e1211f4a5b36eb9522ecc62bcf", size = 344823 }, + { url = "https://files.pythonhosted.org/packages/ae/c8/c4a00fe7f2aa6970c2651df332a14c88f8baaedb2e32d6c3b8c8a003ea74/yarl-1.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:076b1ed2ac819933895b1a000904f62d615fe4533a5cf3e052ff9a1da560575c", size = 337132 }, + { url = "https://files.pythonhosted.org/packages/07/bf/84125f85f44bf2af03f3cf64e87214b42cd59dcc8a04960d610a9825f4d4/yarl-1.15.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f8cfd847e6b9ecf9f2f2531c8427035f291ec286c0a4944b0a9fce58c6446046", size = 326258 }, + { url = "https://files.pythonhosted.org/packages/00/19/73ad8122b2fa73fe22e32c24b82a6c053cf6c73e2f649b73f7ef97bee8d0/yarl-1.15.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:32b66be100ac5739065496c74c4b7f3015cef792c3174982809274d7e51b3e04", size = 336212 }, + { url = "https://files.pythonhosted.org/packages/39/1d/2fa4337d11f6587e9b7565f84eba549f2921494bc8b10bfe811079acaa70/yarl-1.15.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:34a2d76a1984cac04ff8b1bfc939ec9dc0914821264d4a9c8fd0ed6aa8d4cfd2", size = 330397 }, + { url = "https://files.pythonhosted.org/packages/39/ab/dce75e06806bcb4305966471ead03ce639d8230f4f52c32bd614d820c044/yarl-1.15.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0afad2cd484908f472c8fe2e8ef499facee54a0a6978be0e0cff67b1254fd747", size = 334985 }, + { url = "https://files.pythonhosted.org/packages/c1/98/3f679149347a5e34c952bf8f71a387bc96b3488fae81399a49f8b1a01134/yarl-1.15.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c68e820879ff39992c7f148113b46efcd6ec765a4865581f2902b3c43a5f4bbb", size = 356033 }, + { url = "https://files.pythonhosted.org/packages/f7/8c/96546061c19852d0a4b1b07084a58c2e8911db6bcf7838972cff542e09fb/yarl-1.15.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:98f68df80ec6ca3015186b2677c208c096d646ef37bbf8b49764ab4a38183931", size = 357710 }, + { url = "https://files.pythonhosted.org/packages/01/45/ade6fb3daf689816ebaddb3175c962731edf300425c3254c559b6d0dcc27/yarl-1.15.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c56ec1eacd0a5d35b8a29f468659c47f4fe61b2cab948ca756c39b7617f0aa5", size = 345532 }, + { url = "https://files.pythonhosted.org/packages/e7/d7/8de800d3aecda0e64c43e8fc844f7effc8731a6099fa0c055738a2247504/yarl-1.15.2-cp311-cp311-win32.whl", hash = "sha256:eedc3f247ee7b3808ea07205f3e7d7879bc19ad3e6222195cd5fbf9988853e4d", size = 78250 }, + { url = "https://files.pythonhosted.org/packages/3a/6c/69058bbcfb0164f221aa30e0cd1a250f6babb01221e27c95058c51c498ca/yarl-1.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:0ccaa1bc98751fbfcf53dc8dfdb90d96e98838010fc254180dd6707a6e8bb179", size = 84492 }, + { url = "https://files.pythonhosted.org/packages/e0/d1/17ff90e7e5b1a0b4ddad847f9ec6a214b87905e3a59d01bff9207ce2253b/yarl-1.15.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:82d5161e8cb8f36ec778fd7ac4d740415d84030f5b9ef8fe4da54784a1f46c94", size = 136721 }, + { url = "https://files.pythonhosted.org/packages/44/50/a64ca0577aeb9507f4b672f9c833d46cf8f1e042ce2e80c11753b936457d/yarl-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fa2bea05ff0a8fb4d8124498e00e02398f06d23cdadd0fe027d84a3f7afde31e", size = 88954 }, + { url = "https://files.pythonhosted.org/packages/c9/0a/a30d0b02046d4088c1fd32d85d025bd70ceb55f441213dee14d503694f41/yarl-1.15.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:99e12d2bf587b44deb74e0d6170fec37adb489964dbca656ec41a7cd8f2ff178", size = 86692 }, + { url = "https://files.pythonhosted.org/packages/06/0b/7613decb8baa26cba840d7ea2074bd3c5e27684cbcb6d06e7840d6c5226c/yarl-1.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:243fbbbf003754fe41b5bdf10ce1e7f80bcc70732b5b54222c124d6b4c2ab31c", size = 325762 }, + { url = "https://files.pythonhosted.org/packages/97/f5/b8c389a58d1eb08f89341fc1bbcc23a0341f7372185a0a0704dbdadba53a/yarl-1.15.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:856b7f1a7b98a8c31823285786bd566cf06226ac4f38b3ef462f593c608a9bd6", size = 335037 }, + { url = "https://files.pythonhosted.org/packages/cb/f9/d89b93a7bb8b66e01bf722dcc6fec15e11946e649e71414fd532b05c4d5d/yarl-1.15.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:553dad9af802a9ad1a6525e7528152a015b85fb8dbf764ebfc755c695f488367", size = 334221 }, + { url = "https://files.pythonhosted.org/packages/10/77/1db077601998e0831a540a690dcb0f450c31f64c492e993e2eaadfbc7d31/yarl-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30c3ff305f6e06650a761c4393666f77384f1cc6c5c0251965d6bfa5fbc88f7f", size = 330167 }, + { url = "https://files.pythonhosted.org/packages/3b/c2/e5b7121662fd758656784fffcff2e411c593ec46dc9ec68e0859a2ffaee3/yarl-1.15.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:353665775be69bbfc6d54c8d134bfc533e332149faeddd631b0bc79df0897f46", size = 317472 }, + { url = "https://files.pythonhosted.org/packages/c6/f3/41e366c17e50782651b192ba06a71d53500cc351547816bf1928fb043c4f/yarl-1.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f4fe99ce44128c71233d0d72152db31ca119711dfc5f2c82385ad611d8d7f897", size = 330896 }, + { url = "https://files.pythonhosted.org/packages/79/a2/d72e501bc1e33e68a5a31f584fe4556ab71a50a27bfd607d023f097cc9bb/yarl-1.15.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9c1e3ff4b89cdd2e1a24c214f141e848b9e0451f08d7d4963cb4108d4d798f1f", size = 328787 }, + { url = "https://files.pythonhosted.org/packages/9d/ba/890f7e1ea17f3c247748548eee876528ceb939e44566fa7d53baee57e5aa/yarl-1.15.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:711bdfae4e699a6d4f371137cbe9e740dc958530cb920eb6f43ff9551e17cfbc", size = 332631 }, + { url = "https://files.pythonhosted.org/packages/48/c7/27b34206fd5dfe76b2caa08bf22f9212b2d665d5bb2df8a6dd3af498dcf4/yarl-1.15.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4388c72174868884f76affcdd3656544c426407e0043c89b684d22fb265e04a5", size = 344023 }, + { url = "https://files.pythonhosted.org/packages/88/e7/730b130f4f02bd8b00479baf9a57fdea1dc927436ed1d6ba08fa5c36c68e/yarl-1.15.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f0e1844ad47c7bd5d6fa784f1d4accc5f4168b48999303a868fe0f8597bde715", size = 352290 }, + { url = "https://files.pythonhosted.org/packages/84/9b/e8dda28f91a0af67098cddd455e6b540d3f682dda4c0de224215a57dee4a/yarl-1.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a5cafb02cf097a82d74403f7e0b6b9df3ffbfe8edf9415ea816314711764a27b", size = 343742 }, + { url = "https://files.pythonhosted.org/packages/66/47/b1c6bb85f2b66decbe189e27fcc956ab74670a068655df30ef9a2e15c379/yarl-1.15.2-cp312-cp312-win32.whl", hash = "sha256:156ececdf636143f508770bf8a3a0498de64da5abd890c7dbb42ca9e3b6c05b8", size = 78051 }, + { url = "https://files.pythonhosted.org/packages/7d/9e/1a897e5248ec53e96e9f15b3e6928efd5e75d322c6cf666f55c1c063e5c9/yarl-1.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:435aca062444a7f0c884861d2e3ea79883bd1cd19d0a381928b69ae1b85bc51d", size = 84313 }, + { url = "https://files.pythonhosted.org/packages/46/ab/be3229898d7eb1149e6ba7fe44f873cf054d275a00b326f2a858c9ff7175/yarl-1.15.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:416f2e3beaeae81e2f7a45dc711258be5bdc79c940a9a270b266c0bec038fb84", size = 135006 }, + { url = "https://files.pythonhosted.org/packages/10/10/b91c186b1b0e63951f80481b3e6879bb9f7179d471fe7c4440c9e900e2a3/yarl-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:173563f3696124372831007e3d4b9821746964a95968628f7075d9231ac6bb33", size = 88121 }, + { url = "https://files.pythonhosted.org/packages/bf/1d/4ceaccf836b9591abfde775e84249b847ac4c6c14ee2dd8d15b5b3cede44/yarl-1.15.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9ce2e0f6123a60bd1a7f5ae3b2c49b240c12c132847f17aa990b841a417598a2", size = 85967 }, + { url = "https://files.pythonhosted.org/packages/93/bd/c924f22bdb2c5d0ca03a9e64ecc5e041aace138c2a91afff7e2f01edc3a1/yarl-1.15.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaea112aed589131f73d50d570a6864728bd7c0c66ef6c9154ed7b59f24da611", size = 325615 }, + { url = "https://files.pythonhosted.org/packages/59/a5/6226accd5c01cafd57af0d249c7cf9dd12569cd9c78fbd93e8198e7a9d84/yarl-1.15.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4ca3b9f370f218cc2a0309542cab8d0acdfd66667e7c37d04d617012485f904", size = 334945 }, + { url = "https://files.pythonhosted.org/packages/4c/c1/cc6ccdd2bcd0ff7291602d5831754595260f8d2754642dfd34fef1791059/yarl-1.15.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23ec1d3c31882b2a8a69c801ef58ebf7bae2553211ebbddf04235be275a38548", size = 336701 }, + { url = "https://files.pythonhosted.org/packages/ef/ff/39a767ee249444e4b26ea998a526838238f8994c8f274befc1f94dacfb43/yarl-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75119badf45f7183e10e348edff5a76a94dc19ba9287d94001ff05e81475967b", size = 330977 }, + { url = "https://files.pythonhosted.org/packages/dd/ba/b1fed73f9d39e3e7be8f6786be5a2ab4399c21504c9168c3cadf6e441c2e/yarl-1.15.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78e6fdc976ec966b99e4daa3812fac0274cc28cd2b24b0d92462e2e5ef90d368", size = 317402 }, + { url = "https://files.pythonhosted.org/packages/82/e8/03e3ebb7f558374f29c04868b20ca484d7997f80a0a191490790a8c28058/yarl-1.15.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8657d3f37f781d987037f9cc20bbc8b40425fa14380c87da0cb8dfce7c92d0fb", size = 331776 }, + { url = "https://files.pythonhosted.org/packages/1f/83/90b0f4fd1ecf2602ba4ac50ad0bbc463122208f52dd13f152bbc0d8417dd/yarl-1.15.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:93bed8a8084544c6efe8856c362af08a23e959340c87a95687fdbe9c9f280c8b", size = 331585 }, + { url = "https://files.pythonhosted.org/packages/c7/f6/1ed7e7f270ae5f9f1174c1f8597b29658f552fee101c26de8b2eb4ca147a/yarl-1.15.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:69d5856d526802cbda768d3e6246cd0d77450fa2a4bc2ea0ea14f0d972c2894b", size = 336395 }, + { url = "https://files.pythonhosted.org/packages/e0/3a/4354ed8812909d9ec54a92716a53259b09e6b664209231f2ec5e75f4820d/yarl-1.15.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ccad2800dfdff34392448c4bf834be124f10a5bc102f254521d931c1c53c455a", size = 342810 }, + { url = "https://files.pythonhosted.org/packages/de/cc/39e55e16b1415a87f6d300064965d6cfb2ac8571e11339ccb7dada2444d9/yarl-1.15.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:a880372e2e5dbb9258a4e8ff43f13888039abb9dd6d515f28611c54361bc5644", size = 351441 }, + { url = "https://files.pythonhosted.org/packages/fb/19/5cd4757079dc9d9f3de3e3831719b695f709a8ce029e70b33350c9d082a7/yarl-1.15.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c998d0558805860503bc3a595994895ca0f7835e00668dadc673bbf7f5fbfcbe", size = 345875 }, + { url = "https://files.pythonhosted.org/packages/83/a0/ef09b54634f73417f1ea4a746456a4372c1b044f07b26e16fa241bd2d94e/yarl-1.15.2-cp313-cp313-win32.whl", hash = "sha256:533a28754e7f7439f217550a497bb026c54072dbe16402b183fdbca2431935a9", size = 302609 }, + { url = "https://files.pythonhosted.org/packages/20/9f/f39c37c17929d3975da84c737b96b606b68c495cc4ee86408f10523a1635/yarl-1.15.2-cp313-cp313-win_amd64.whl", hash = "sha256:5838f2b79dc8f96fdc44077c9e4e2e33d7089b10788464609df788eb97d03aad", size = 308252 }, + { url = "https://files.pythonhosted.org/packages/46/cf/a28c494decc9c8776b0d7b729c68d26fdafefcedd8d2eab5d9cd767376b2/yarl-1.15.2-py3-none-any.whl", hash = "sha256:0d3105efab7c5c091609abacad33afff33bdff0035bece164c98bcf5a85ef90a", size = 38891 }, ] [[package]] name = "zipp" -version = "3.20.1" +version = "3.20.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d3/8b/1239a3ef43a0d0ebdca623fb6413bc7702c321400c5fdd574f0b7aa0fbb4/zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b", size = 23848 } +sdist = { url = "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29", size = 24199 } wheels = [ - { url = "https://files.pythonhosted.org/packages/07/9e/c96f7a4cd0bf5625bb409b7e61e99b1130dc63a98cb8b24aeabae62d43e8/zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064", size = 8988 }, + { url = "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", size = 9200 }, ] -- 2.45.3 From 335882befda43fc0a3f15a40c15ad5e11e93f749 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 24 Jan 2025 23:05:24 +0000 Subject: [PATCH 371/376] chore(devcontainer): change volume name --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e480715..23d0b75 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -29,7 +29,7 @@ "UV_PYTHON_DOWNLOADS": "never", "PROJECT_DIR": "/workspaces/SeaCogs" }, - "mounts": ["source=uv-persistent-data,target=/workspaces/SeaCogs/.data,type=volume"], + "mounts": ["source=seacogs-persistent-data,target=/workspaces/SeaCogs/.data,type=volume"], "postCreateCommand": "uv sync --frozen", "remoteUser": "vscode" } -- 2.45.3 From f5b591c31e1bfb1d30b87161b1528b481b5e4cfb Mon Sep 17 00:00:00 2001 From: Renovate Date: Fri, 24 Jan 2025 22:53:50 +0000 Subject: [PATCH 372/376] chore(deps): update www.coastalcommits.com/cswimr/actions:docs docker digest to e405cd6 --- .forgejo/workflows/workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/workflow.yaml b/.forgejo/workflows/workflow.yaml index 1f1df5b..732b227 100644 --- a/.forgejo/workflows/workflow.yaml +++ b/.forgejo/workflows/workflow.yaml @@ -29,7 +29,7 @@ jobs: name: Build Documentation (MkDocs) if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: docker - container: www.coastalcommits.com/cswimr/actions:docs@sha256:187a6986dba977a73a20ae30a89ceeba3d053e55b659dcc0ae7bab917571460d + container: www.coastalcommits.com/cswimr/actions:docs@sha256:e405cd6b9b1182a570ddee32ed8dd1b2f899edc625d006c8b4b2f18c100e724f steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 -- 2.45.3 From fb9a208dd4d6b758fc0cd2e1e472fed5e4107132 Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 24 Jan 2025 23:12:52 +0000 Subject: [PATCH 373/376] chore(repo): add vscode run and debug configuration --- .vscode/launch.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..1d4d69e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Red-DiscordBot", + "type": "debugpy", + "request": "launch", + "module": "redbot", + "args": ["local"] + } + ] +} -- 2.45.3 From 062b788ef014d3294dd6f156b5784a471e03457f Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 24 Jan 2025 23:31:53 +0000 Subject: [PATCH 374/376] chore(vscode): set `-vvv` in the launch and debug options --- .vscode/launch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 1d4d69e..44c2cf3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,7 @@ "type": "debugpy", "request": "launch", "module": "redbot", - "args": ["local"] + "args": ["local", "-vvv"] } ] } -- 2.45.3 From 3d4c438f373a29172470a7b58334f4df600562cc Mon Sep 17 00:00:00 2001 From: cswimr Date: Fri, 24 Jan 2025 23:35:53 +0000 Subject: [PATCH 375/376] chore(vscode): change formatOnSave --- .vscode/settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6808e51..b314c1c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,7 @@ "editor.defaultFormatter": "charliermarsh.ruff" }, "[json]": { + "editor.formatOnSave": true, "editor.defaultFormatter": "vscode.json-language-features" } } -- 2.45.3 From 374a0835286c363308d7bfbebf02642155d36e36 Mon Sep 17 00:00:00 2001 From: cswimr Date: Sat, 25 Jan 2025 19:45:04 +0000 Subject: [PATCH 376/376] fix(aurora): fix some ruff errors --- aurora/aurora.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/aurora/aurora.py b/aurora/aurora.py index 8702e52..2cfd78a 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -585,10 +585,10 @@ class Aurora(commands.Cog): try: before = parse(before) except (ParserError, OverflowError) as e: - if e == ParserError: + if isinstance(e, ParserError): await interaction.response.send_message(content=error("Invalid date format for `before` parameter!"), ephemeral=True) return - if e == OverflowError: + if isinstance(e, OverflowError): await interaction.response.send_message(content=error("Date is too far in the future!"), ephemeral=True) return @@ -596,10 +596,10 @@ class Aurora(commands.Cog): try: after = parse(after) except (ParserError, OverflowError) as e: - if e == ParserError: + if isinstance(e, ParserError): await interaction.response.send_message(content=error("Invalid date format for `after` parameter!"), ephemeral=True) return - if e == OverflowError: + if isinstance(e, OverflowError): await interaction.response.send_message(content=error("Date is too far in the future!"), ephemeral=True) return @@ -607,10 +607,10 @@ class Aurora(commands.Cog): try: on = parse(on) except (ParserError, OverflowError) as e: - if e == ParserError: + if isinstance(e, ParserError): await interaction.response.send_message(content=error("Invalid date format for `on` parameter!"), ephemeral=True) return - if e == OverflowError: + if isinstance(e, OverflowError): await interaction.response.send_message(content=error("Date is too far in the future!"), ephemeral=True) return @@ -777,9 +777,9 @@ class Aurora(commands.Cog): try: success, msg = await moderation.resolve(interaction.user.id, reason) except (ValueError, TypeError) as e: - if e == ValueError: + if isinstance(e, ValueError): await interaction.response.send_message(content=error("This case has already been resolved!"), ephemeral=True) - elif e == TypeError: + elif isinstance(e, TypeError): await interaction.response.send_message(content=error("This case type cannot be resolved!"), ephemeral=True) embed = await case_factory( @@ -1142,9 +1142,9 @@ class Aurora(commands.Cog): parsed_date = parse(date) await ctx.send(f"`{parsed_date}`") except (ParserError, OverflowError) as e: - if e == ParserError: + if isinstance(e, ParserError): await ctx.send(error("Invalid date format!")) - if e == OverflowError: + if isinstance(e, OverflowError): await ctx.send(error("Date is too far in the future!")) @aurora_convert.command(aliases=["td"]) -- 2.45.3