diff --git a/.env.example b/.env.example
index 14bdf060bf..972eca4517 100644
--- a/.env.example
+++ b/.env.example
@@ -3,3 +3,4 @@ LOG_URL=https://logviewername.herokuapp.com/
GUILD_ID=1234567890
OWNERS=Owner1ID,Owner2ID,Owner3ID
CONNECTION_URI=mongodb+srv://mongodburi
+DISABLE_AUTOUPDATES=true
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000..176a458f94
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+* text=auto
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index fbcb038e69..8125c1756a 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1 +1 @@
-patreon: kyber
+buy_me_a_coffee: modmaildev
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 99779ab4f3..35fc2bedb1 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -20,7 +20,7 @@ body:
- Heroku
- Systemd
- PM2
- - Patreon
+ - Buy Me A Coffee / Patreon
- Other
validations:
required: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4ec54e0f8a..2b7a7e28ea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,103 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html);
however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/modmail-dev/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section.
+# v4.2.1
+
+### Added
+
+**New Configuration Options:**
+* `unsnooze_history_limit`: Limits the number of messages replayed when unsnoozing (genesis message and notes are always shown).
+* `snooze_behavior`: Choose between `delete` (legacy) or `move` behavior for snoozing.
+* `snoozed_category_id`: Target category for `move` snoozing; required when `snooze_behavior` is `move`.
+* `snooze_store_attachments`: When enabled, image attachments are stored as base64 when snoozing with delete behavior, allowing them to be re-uploaded on unsnooze.
+* `snooze_attachment_max_bytes`: Maximum size per attachment to store as base64 (default: 4 MiB).
+* `thread_creation_menu_timeout`: Timeout duration for user interaction with the menu (default: 30 seconds).
+* `thread_creation_menu_close_on_timeout`: Silently abort thread creation if user doesn't select an option.
+* `thread_creation_menu_anonymous_menu`: Anonymize the initial menu prompt relayed to staff.
+* `thread_creation_menu_embed_text`: Text shown in the embed above the selection dropdown.
+* `thread_creation_menu_dropdown_placeholder`: Placeholder text in the dropdown before selection.
+* `thread_creation_menu_selection_log`: Log the chosen menu option in the newly created thread channel.
+* `thread_creation_menu_precreate_channel`: Create thread channel immediately upon first DM even if menu is enabled.
+* `thread_creation_menu_embed_title`: Optional title for the thread-creation menu embed.
+* `thread_creation_menu_embed_footer`: Optional footer text for the menu embed.
+* `thread_creation_menu_embed_footer_icon_url`: Optional URL for the footer icon.
+* `thread_creation_menu_embed_thumbnail_url`: Optional thumbnail image URL.
+* `thread_creation_menu_embed_image_url`: Optional large hero image URL for the menu embed.
+* `thread_creation_menu_embed_large_image`: Promote thumbnail to large hero image if no separate image URL is set.
+* `thread_creation_menu_embed_color`: Color for the menu embed's side strip.
+
+**Thread-Creation Menu Feature:**
+* Full thread-creation menu system with interactive select menus:
+ * `?threadmenu toggle`: Enable/disable the menu globally.
+ * `?threadmenu show`: List current top-level options.
+ * `?threadmenu option add`: Interactive wizard to create an option.
+ * `?threadmenu option edit/remove/show`: Manage or inspect existing options.
+ * `?threadmenu submenu create/delete/list/show`: Manage submenus (nested menu levels).
+ * `?threadmenu submenu option add/edit/remove`: Manage options inside submenus.
+ * `?threadmenu dump_config`: Export current configuration to a file.
+ * `?threadmenu load_config`: Import configuration from a file.
+ * `?threadmenu reset`: Reset all thread-creation menu settings to defaults.
+* Per-option category targeting: Each menu option can specify a target category where threads are created.
+* Submenu support: Create up to 25 main-level options, each with up to 24 nested options.
+* Optional selection logging: Log which menu option was chosen in the newly created thread channel.
+* Anonymous menu support: Hide original prompt author context from staff when menu is anonymized.
+* Category fallback: If an option's category is invalid/missing, creation falls back to `main_category_id`.
+
+**Snooze Enhancements:**
+* Attachment persistence for delete-behavior snoozing: Image attachments can now be stored as base64 data.
+* Enhanced unsnooze functionality with configurable message replay limits.
+* Auto-unsnooze task continuously monitors and automatically unsnoozes threads when duration expires.
+
+### Changed
+- Renamed `max_snooze_time` to `snooze_default_duration` (accepts seconds or human-readable time like "7 days").
+- When `snooze_behavior` is set to `move`, the snoozed category now has a hard limit of 49 channels. New snoozes are blocked once it’s full until space is freed.
+- When switching `snooze_behavior` to `move` via `?config set`, the bot reminds admins to set `snoozed_category_id` if it’s missing.
+- Thread-creation menu options and submenu options now support per-option `category` targeting.
+- Category selection in menu option wizards allows specifying ID, name, or mention format.
+- Snoozed thread restoration now respects `unsnooze_history_limit` (if set) to replay only the last N messages.
+- Enhanced auto-unsnooze task monitors and automatically unsnoozes threads when their snooze duration expires.
+- Snoozed threads can now be moved to a dedicated category instead of being deleted (via `snooze_behavior: move`).
+
+### Fixed
+
+- Corrected behavior when snooze channel count reaches the 49-channel limit in move-based snoozing.
+- Improved category resolution in threadmenu wizards (handles ID, name, and mention formats reliably).
+- Enhanced thread state restoration after unsnoozing to properly re-add all recipients.
+
+
+# v4.2.0
+
+Upgraded discord.py to version 2.6.3, added support for CV2.
+Forwarded messages now properly show in threads, rather than showing as an empty embed.
+
+### Fixed
+- Make Modmail keep working when typing is disabled due to an outage caused by Discord.
+- Resolved an issue where forwarded messages appeared as empty embeds.
+- Fixed internal message handling and restoration processes.
+- Eliminated duplicate logs and notes.
+- Addressed inconsistent use of `logkey` after ticket restoration.
+- Fixed issues with identifying the user who sent internal messages.
+- Solved an ancient bug where closing with words like `evening` wouldn't work.
+- Fixed the command from being included in the reply in rare conditions.
+
+### Added
+Commands:
+* `snooze`: Initiates a snooze action.
+* `snoozed`: Displays snoozed items.
+* `unsnooze`: Reverses the snooze action.
+* `clearsnoozed`: Clears all snoozed items.
+
+Configuration Options:
+* `max_snooze_time`: Sets the maximum duration for snooze.
+* `snooze_title`: Customizes the title for snooze notifications.
+* `snooze_text`: Customizes the text for snooze notifications.
+* `unsnooze_text`: Customizes the text for unsnooze notifications.
+* `unsnooze_notify_channel`: Specifies the channel for unsnooze notifications.
+* `thread_min_characters`: Minimum number of characters required.
+* `thread_min_characters_title`: Title shown when the message is too short.
+* `thread_min_characters_response`: Response shown to the user if their message is too short.
+* `thread_min_characters_footer`: Footer displaying the minimum required characters.
+
# v4.1.2
### Fixed
diff --git a/Pipfile b/Pipfile
index 21205b36f5..6feb42454e 100644
--- a/Pipfile
+++ b/Pipfile
@@ -7,24 +7,29 @@ verify_ssl = true
bandit = ">=1.7.5"
black = "==23.11.0"
pylint = "==3.0.2"
-typing-extensions = "==4.8.0"
+tomli = "==2.2.1"
[packages]
-aiohttp = "==3.9.0"
+aiohttp = "==3.13.2"
+async-timeout = {version = "==5.0.1", markers = "python_version < '3.11'"}
+typing-extensions = "==4.15.0"
colorama = "==0.4.6"
-"discord.py" = {version = "==2.3.2", extras = ["speed"]}
+"discord.py" = {version = "==2.6.3", extras = ["speed"]}
emoji = "==2.8.0"
isodate = "==0.6.1"
-motor = "==3.3.2"
-natural = "==0.2.0" # Why is this needed?
+motor = "==3.7.1"
+natural = "==0.2.0"
packaging = "==23.2"
parsedatetime = "==2.6"
-pymongo = {extras = ["srv"], version = "*"} # Required by motor
+dnspython = "==2.8.0"
+pymongo = "==4.15.3"
python-dateutil = "==2.8.2"
python-dotenv = "==1.0.0"
-uvloop = {version = ">=0.19.0", markers = "sys_platform != 'win32'"}
-lottie = {version = "==0.7.0", extras = ["pdf"]}
+uvloop = {version = "==0.22.1", markers = "sys_platform != 'win32'"}
+lottie = {version = "==0.7.2", extras = ["pdf"]}
+setuptools = "==80.9.0"
requests = "==2.31.0"
+orjson = "==3.11.4"
[scripts]
bot = "python bot.py"
diff --git a/Pipfile.lock b/Pipfile.lock
index 5f07c7b131..011514b29b 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "7fee393ea9ea4c0b923033f0da0fdc590ba3f75c6072812062cdc458b84bf9ae"
+ "sha256": "6dc9fd3ca0aa2c413384ee16afb30290a840f6755cbf0bf828d0661171604db4"
},
"pipfile-spec": 6,
"requires": {},
@@ -14,385 +14,502 @@
]
},
"default": {
- "aiodns": {
+ "aiohappyeyeballs": {
"hashes": [
- "sha256:1073eac48185f7a4150cad7f96a5192d6911f12b4fb894de80a088508c9b3a99",
- "sha256:a387b63da4ced6aad35b1dda2d09620ad608a1c7c0fb71efa07ebb4cd511928d"
+ "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558",
+ "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8"
],
- "version": "==3.1.1"
+ "markers": "python_version >= '3.9'",
+ "version": "==2.6.1"
},
"aiohttp": {
"hashes": [
- "sha256:05857848da443c8c12110d99285d499b4e84d59918a21132e45c3f0804876994",
- "sha256:05a183f1978802588711aed0dea31e697d760ce9055292db9dc1604daa9a8ded",
- "sha256:09f23292d29135025e19e8ff4f0a68df078fe4ee013bca0105b2e803989de92d",
- "sha256:11ca808f9a6b63485059f5f6e164ef7ec826483c1212a44f268b3653c91237d8",
- "sha256:1736d87dad8ef46a8ec9cddd349fa9f7bd3a064c47dd6469c0d6763d3d49a4fc",
- "sha256:1df43596b826022b14998f0460926ce261544fedefe0d2f653e1b20f49e96454",
- "sha256:23170247ef89ffa842a02bbfdc425028574d9e010611659abeb24d890bc53bb8",
- "sha256:2779f5e7c70f7b421915fd47db332c81de365678180a9f3ab404088f87ba5ff9",
- "sha256:28185e36a78d247c55e9fbea2332d16aefa14c5276a582ce7a896231c6b1c208",
- "sha256:2cbc14a13fb6b42d344e4f27746a4b03a2cb0c1c3c5b932b0d6ad8881aa390e3",
- "sha256:2d71abc15ff7047412ef26bf812dfc8d0d1020d664617f4913df2df469f26b76",
- "sha256:2d820162c8c2bdbe97d328cd4f417c955ca370027dce593345e437b2e9ffdc4d",
- "sha256:317719d7f824eba55857fe0729363af58e27c066c731bc62cd97bc9c3d9c7ea4",
- "sha256:35a68cd63ca6aaef5707888f17a70c36efe62b099a4e853d33dc2e9872125be8",
- "sha256:3607375053df58ed6f23903aa10cf3112b1240e8c799d243bbad0f7be0666986",
- "sha256:366bc870d7ac61726f32a489fbe3d1d8876e87506870be66b01aeb84389e967e",
- "sha256:3abf0551874fecf95f93b58f25ef4fc9a250669a2257753f38f8f592db85ddea",
- "sha256:3d7f6235c7475658acfc1769d968e07ab585c79f6ca438ddfecaa9a08006aee2",
- "sha256:3dd8119752dd30dd7bca7d4bc2a92a59be6a003e4e5c2cf7e248b89751b8f4b7",
- "sha256:42fe4fd9f0dfcc7be4248c162d8056f1d51a04c60e53366b0098d1267c4c9da8",
- "sha256:45820ddbb276113ead8d4907a7802adb77548087ff5465d5c554f9aa3928ae7d",
- "sha256:4790e44f46a4aa07b64504089def5744d3b6780468c4ec3a1a36eb7f2cae9814",
- "sha256:4afa8f71dba3a5a2e1e1282a51cba7341ae76585345c43d8f0e624882b622218",
- "sha256:4b777c9286b6c6a94f50ddb3a6e730deec327e9e2256cb08b5530db0f7d40fd8",
- "sha256:4ee1b4152bc3190cc40ddd6a14715e3004944263ea208229ab4c297712aa3075",
- "sha256:51a4cd44788ea0b5e6bb8fa704597af3a30be75503a7ed1098bc5b8ffdf6c982",
- "sha256:536b01513d67d10baf6f71c72decdf492fb7433c5f2f133e9a9087379d4b6f31",
- "sha256:571760ad7736b34d05597a1fd38cbc7d47f7b65deb722cb8e86fd827404d1f6b",
- "sha256:5a2eb5311a37fe105aa35f62f75a078537e1a9e4e1d78c86ec9893a3c97d7a30",
- "sha256:5ab16c254e2312efeb799bc3c06897f65a133b38b69682bf75d1f1ee1a9c43a9",
- "sha256:65b0a70a25456d329a5e1426702dde67be0fb7a4ead718005ba2ca582d023a94",
- "sha256:673343fbc0c1ac44d0d2640addc56e97a052504beacd7ade0dc5e76d3a4c16e8",
- "sha256:6777a390e41e78e7c45dab43a4a0196c55c3b8c30eebe017b152939372a83253",
- "sha256:6896b8416be9ada4d22cd359d7cb98955576ce863eadad5596b7cdfbf3e17c6c",
- "sha256:694df243f394629bcae2d8ed94c589a181e8ba8604159e6e45e7b22e58291113",
- "sha256:70e851f596c00f40a2f00a46126c95c2e04e146015af05a9da3e4867cfc55911",
- "sha256:7276fe0017664414fdc3618fca411630405f1aaf0cc3be69def650eb50441787",
- "sha256:76a86a9989ebf82ee61e06e2bab408aec4ea367dc6da35145c3352b60a112d11",
- "sha256:7a94bde005a8f926d0fa38b88092a03dea4b4875a61fbcd9ac6f4351df1b57cd",
- "sha256:7ae5f99a32c53731c93ac3075abd3e1e5cfbe72fc3eaac4c27c9dd64ba3b19fe",
- "sha256:7e8a3b79b6d186a9c99761fd4a5e8dd575a48d96021f220ac5b5fa856e5dd029",
- "sha256:816f4db40555026e4cdda604a1088577c1fb957d02f3f1292e0221353403f192",
- "sha256:8303531e2c17b1a494ffaeba48f2da655fe932c4e9a2626c8718403c83e5dd2b",
- "sha256:8488519aa05e636c5997719fe543c8daf19f538f4fa044f3ce94bee608817cff",
- "sha256:87c8b0a6487e8109427ccf638580865b54e2e3db4a6e0e11c02639231b41fc0f",
- "sha256:8c9e5f4d7208cda1a2bb600e29069eecf857e6980d0ccc922ccf9d1372c16f4b",
- "sha256:94697c7293199c2a2551e3e3e18438b4cba293e79c6bc2319f5fd652fccb7456",
- "sha256:9623cfd9e85b76b83ef88519d98326d4731f8d71869867e47a0b979ffec61c73",
- "sha256:98d21092bf2637c5fa724a428a69e8f5955f2182bff61f8036827cf6ce1157bf",
- "sha256:99ae01fb13a618b9942376df77a1f50c20a281390dad3c56a6ec2942e266220d",
- "sha256:9c196b30f1b1aa3363a69dd69079ae9bec96c2965c4707eaa6914ba099fb7d4f",
- "sha256:a00ce44c21612d185c5275c5cba4bab8d7c1590f248638b667ed8a782fa8cd6f",
- "sha256:a1b66dbb8a7d5f50e9e2ea3804b01e766308331d0cac76eb30c563ac89c95985",
- "sha256:a1d7edf74a36de0e5ca50787e83a77cf352f5504eb0ffa3f07000a911ba353fb",
- "sha256:a1e3b3c107ccb0e537f309f719994a55621acd2c8fdf6d5ce5152aed788fb940",
- "sha256:a486ddf57ab98b6d19ad36458b9f09e6022de0381674fe00228ca7b741aacb2f",
- "sha256:ac9669990e2016d644ba8ae4758688534aabde8dbbc81f9af129c3f5f01ca9cd",
- "sha256:b1a2ea8252cacc7fd51df5a56d7a2bb1986ed39be9397b51a08015727dfb69bd",
- "sha256:c5b7bf8fe4d39886adc34311a233a2e01bc10eb4e842220235ed1de57541a896",
- "sha256:c67a51ea415192c2e53e4e048c78bab82d21955b4281d297f517707dc836bf3d",
- "sha256:ca4fddf84ac7d8a7d0866664936f93318ff01ee33e32381a115b19fb5a4d1202",
- "sha256:d5b9345ab92ebe6003ae11d8092ce822a0242146e6fa270889b9ba965457ca40",
- "sha256:d97c3e286d0ac9af6223bc132dc4bad6540b37c8d6c0a15fe1e70fb34f9ec411",
- "sha256:db04d1de548f7a62d1dd7e7cdf7c22893ee168e22701895067a28a8ed51b3735",
- "sha256:dcf71c55ec853826cd70eadb2b6ac62ec577416442ca1e0a97ad875a1b3a0305",
- "sha256:de3cc86f4ea8b4c34a6e43a7306c40c1275e52bfa9748d869c6b7d54aa6dad80",
- "sha256:deac0a32aec29608eb25d730f4bc5a261a65b6c48ded1ed861d2a1852577c932",
- "sha256:e18d92c3e9e22553a73e33784fcb0ed484c9874e9a3e96c16a8d6a1e74a0217b",
- "sha256:eb6dfd52063186ac97b4caa25764cdbcdb4b10d97f5c5f66b0fa95052e744eb7",
- "sha256:f09960b5bb1017d16c0f9e9f7fc42160a5a49fa1e87a175fd4a2b1a1833ea0af",
- "sha256:f1e4f254e9c35d8965d377e065c4a8a55d396fe87c8e7e8429bcfdeeb229bfb3",
- "sha256:f32c86dc967ab8c719fd229ce71917caad13cc1e8356ee997bf02c5b368799bf",
- "sha256:f50b4663c3e0262c3a361faf440761fbef60ccdde5fe8545689a4b3a3c149fb4",
- "sha256:f8e05f5163528962ce1d1806fce763ab893b1c5b7ace0a3538cd81a90622f844",
- "sha256:f929f4c9b9a00f3e6cc0587abb95ab9c05681f8b14e0fe1daecfa83ea90f8318",
- "sha256:f9e09a1c83521d770d170b3801eea19b89f41ccaa61d53026ed111cb6f088887"
+ "sha256:04c3971421576ed24c191f610052bcb2f059e395bc2489dd99e397f9bc466329",
+ "sha256:05c4dd3c48fb5f15db31f57eb35374cb0c09afdde532e7fb70a75aede0ed30f6",
+ "sha256:070599407f4954021509193404c4ac53153525a19531051661440644728ba9a7",
+ "sha256:0740f31a60848d6edb296a0df827473eede90c689b8f9f2a4cdde74889eb2254",
+ "sha256:088912a78b4d4f547a1f19c099d5a506df17eacec3c6f4375e2831ec1d995742",
+ "sha256:0a3d54e822688b56e9f6b5816fb3de3a3a64660efac64e4c2dc435230ad23bad",
+ "sha256:0db1e24b852f5f664cd728db140cf11ea0e82450471232a394b3d1a540b0f906",
+ "sha256:0e87dff73f46e969af38ab3f7cb75316a7c944e2e574ff7c933bc01b10def7f5",
+ "sha256:1237c1375eaef0db4dcd7c2559f42e8af7b87ea7d295b118c60c36a6e61cb811",
+ "sha256:16f15a4eac3bc2d76c45f7ebdd48a65d41b242eb6c31c2245463b40b34584ded",
+ "sha256:1f9b2c2d4b9d958b1f9ae0c984ec1dd6b6689e15c75045be8ccb4011426268ca",
+ "sha256:204ffff2426c25dfda401ba08da85f9c59525cdc42bda26660463dd1cbcfec6f",
+ "sha256:20b10bbfbff766294fe99987f7bb3b74fdd2f1a2905f2562132641ad434dcf98",
+ "sha256:20db2d67985d71ca033443a1ba2001c4b5693fe09b0e29f6d9358a99d4d62a8a",
+ "sha256:228a1cd556b3caca590e9511a89444925da87d35219a49ab5da0c36d2d943a6a",
+ "sha256:2372b15a5f62ed37789a6b383ff7344fc5b9f243999b0cd9b629d8bc5f5b4155",
+ "sha256:23ad365e30108c422d0b4428cf271156dd56790f6dd50d770b8e360e6c5ab2e6",
+ "sha256:23fb0783bc1a33640036465019d3bba069942616a6a2353c6907d7fe1ccdaf4e",
+ "sha256:2475391c29230e063ef53a66669b7b691c9bfc3f1426a0f7bcdf1216bdbac38b",
+ "sha256:27e569eb9d9e95dbd55c0fc3ec3a9335defbf1d8bc1d20171a49f3c4c607b93e",
+ "sha256:29562998ec66f988d49fb83c9b01694fa927186b781463f376c5845c121e4e0b",
+ "sha256:2adebd4577724dcae085665f294cc57c8701ddd4d26140504db622b8d566d7aa",
+ "sha256:2ca6ffef405fc9c09a746cb5d019c1672cd7f402542e379afc66b370833170cf",
+ "sha256:2e1a9bea6244a1d05a4e57c295d69e159a5c50d8ef16aa390948ee873478d9a5",
+ "sha256:364e25edaabd3d37b1db1f0cbcee8c73c9a3727bfa262b83e5e4cf3489a2a9dc",
+ "sha256:364f55663085d658b8462a1c3f17b2b84a5c2e1ba858e1b79bff7b2e24ad1514",
+ "sha256:39d02cb6025fe1aabca329c5632f48c9532a3dabccd859e7e2f110668972331f",
+ "sha256:3a92cf4b9bea33e15ecbaa5c59921be0f23222608143d025c989924f7e3e0c07",
+ "sha256:40176a52c186aefef6eb3cad2cdd30cd06e3afbe88fe8ab2af9c0b90f228daca",
+ "sha256:4356474ad6333e41ccefd39eae869ba15a6c5299c9c01dfdcfdd5c107be4363e",
+ "sha256:43dff14e35aba17e3d6d5ba628858fb8cb51e30f44724a2d2f0c75be492c55e9",
+ "sha256:4647d02df098f6434bafd7f32ad14942f05a9caa06c7016fdcc816f343997dd0",
+ "sha256:47f438b1a28e926c37632bff3c44df7d27c9b57aaf4e34b1def3c07111fdb782",
+ "sha256:4dd3db9d0f4ebca1d887d76f7cdbcd1116ac0d05a9221b9dad82c64a62578c4d",
+ "sha256:4ebf9cfc9ba24a74cf0718f04aac2a3bbe745902cc7c5ebc55c0f3b5777ef213",
+ "sha256:5276807b9de9092af38ed23ce120539ab0ac955547b38563a9ba4f5b07b95293",
+ "sha256:53b07472f235eb80e826ad038c9d106c2f653584753f3ddab907c83f49eedead",
+ "sha256:550bf765101ae721ee1d37d8095f47b1f220650f85fe1af37a90ce75bab89d04",
+ "sha256:56d36e80d2003fa3fc0207fac644216d8532e9504a785ef9a8fd013f84a42c61",
+ "sha256:585542825c4bc662221fb257889e011a5aa00f1ae4d75d1d246a5225289183e3",
+ "sha256:5b927cf9b935a13e33644cbed6c8c4b2d0f25b713d838743f8fe7191b33829c4",
+ "sha256:5d7f02042c1f009ffb70067326ef183a047425bb2ff3bc434ead4dd4a4a66a2b",
+ "sha256:6315fb6977f1d0dd41a107c527fee2ed5ab0550b7d885bc15fee20ccb17891da",
+ "sha256:66bac29b95a00db411cd758fea0e4b9bdba6d549dfe333f9a945430f5f2cc5a6",
+ "sha256:6c00dbcf5f0d88796151e264a8eab23de2997c9303dd7c0bf622e23b24d3ce22",
+ "sha256:6e7352512f763f760baaed2637055c49134fd1d35b37c2dedfac35bfe5cf8725",
+ "sha256:7519bdc7dfc1940d201651b52bf5e03f5503bda45ad6eacf64dda98be5b2b6be",
+ "sha256:78cd586d8331fb8e241c2dd6b2f4061778cc69e150514b39a9e28dd050475661",
+ "sha256:7a653d872afe9f33497215745da7a943d1dc15b728a9c8da1c3ac423af35178e",
+ "sha256:7c3a50345635a02db61792c85bb86daffac05330f6473d524f1a4e3ef9d0046d",
+ "sha256:7fbdf5ad6084f1940ce88933de34b62358d0f4a0b6ec097362dcd3e5a65a4989",
+ "sha256:7fd19df530c292542636c2a9a85854fab93474396a52f1695e799186bbd7f24c",
+ "sha256:868e195e39b24aaa930b063c08bb0c17924899c16c672a28a65afded9c46c6ec",
+ "sha256:8709a0f05d59a71f33fd05c17fc11fcb8c30140506e13c2f5e8ee1b8964e1b45",
+ "sha256:88d6c017966a78c5265d996c19cdb79235be5e6412268d7e2ce7dee339471b7a",
+ "sha256:8aa7c807df234f693fed0ecd507192fc97692e61fee5702cdc11155d2e5cadc8",
+ "sha256:8b2f1414f6a1e0683f212ec80e813f4abef94c739fd090b66c9adf9d2a05feac",
+ "sha256:93655083005d71cd6c072cdab54c886e6570ad2c4592139c3fb967bfc19e4694",
+ "sha256:939ced4a7add92296b0ad38892ce62b98c619288a081170695c6babe4f50e636",
+ "sha256:9434bc0d80076138ea986833156c5a48c9c7a8abb0c96039ddbb4afc93184169",
+ "sha256:94f05348c4406450f9d73d38efb41d669ad6cd90c7ee194810d0eefbfa875a7a",
+ "sha256:960c2fc686ba27b535f9fd2b52d87ecd7e4fd1cf877f6a5cba8afb5b4a8bd204",
+ "sha256:96581619c57419c3d7d78703d5b78c1e5e5fc0172d60f555bdebaced82ded19a",
+ "sha256:97a0895a8e840ab3520e2288db7cace3a1981300d48babeb50e7425609e2e0ab",
+ "sha256:98c4fb90bb82b70a4ed79ca35f656f4281885be076f3f970ce315402b53099ae",
+ "sha256:99c5280a329d5fa18ef30fd10c793a190d996567667908bef8a7f81f8202b948",
+ "sha256:9acda8604a57bb60544e4646a4615c1866ee6c04a8edef9b8ee6fd1d8fa2ddc8",
+ "sha256:9c705601e16c03466cb72011bd1af55d68fa65b045356d8f96c216e5f6db0fa5",
+ "sha256:9e8f8afb552297aca127c90cb840e9a1d4bfd6a10d7d8f2d9176e1acc69bad30",
+ "sha256:9eb3e33fdbe43f88c3c75fa608c25e7c47bbd80f48d012763cb67c47f39a7e16",
+ "sha256:9ec49dff7e2b3c85cdeaa412e9d438f0ecd71676fde61ec57027dd392f00c693",
+ "sha256:9f377d0a924e5cc94dc620bc6366fc3e889586a7f18b748901cf016c916e2084",
+ "sha256:a09a6d073fb5789456545bdee2474d14395792faa0527887f2f4ec1a486a59d3",
+ "sha256:a2713a95b47374169409d18103366de1050fe0ea73db358fc7a7acb2880422d4",
+ "sha256:a3b6fb0c207cc661fa0bf8c66d8d9b657331ccc814f4719468af61034b478592",
+ "sha256:a4b88ebe35ce54205c7074f7302bd08a4cb83256a3e0870c72d6f68a3aaf8e49",
+ "sha256:a88d13e7ca367394908f8a276b89d04a3652044612b9a408a0bb22a5ed976a1a",
+ "sha256:ac6cde5fba8d7d8c6ac963dbb0256a9854e9fafff52fbcc58fdf819357892c3e",
+ "sha256:ae32f24bbfb7dbb485a24b30b1149e2f200be94777232aeadba3eecece4d0aa4",
+ "sha256:b009194665bcd128e23eaddef362e745601afa4641930848af4c8559e88f18f9",
+ "sha256:b1e56bab2e12b2b9ed300218c351ee2a3d8c8fdab5b1ec6193e11a817767e47b",
+ "sha256:b395bbca716c38bef3c764f187860e88c724b342c26275bc03e906142fc5964f",
+ "sha256:b59d13c443f8e049d9e94099c7e412e34610f1f49be0f230ec656a10692a5802",
+ "sha256:ba2715d842ffa787be87cbfce150d5e88c87a98e0b62e0f5aa489169a393dbbb",
+ "sha256:bb7fb776645af5cc58ab804c58d7eba545a97e047254a52ce89c157b5af6cd0b",
+ "sha256:c038a8fdc8103cd51dbd986ecdce141473ffd9775a7a8057a6ed9c3653478011",
+ "sha256:c20423ce14771d98353d2e25e83591fa75dfa90a3c1848f3d7c68243b4fbded3",
+ "sha256:c5c94825f744694c4b8db20b71dba9a257cd2ba8e010a803042123f3a25d50d7",
+ "sha256:cf00e5db968c3f67eccd2778574cf64d8b27d95b237770aa32400bd7a1ca4f6c",
+ "sha256:d23b5fe492b0805a50d3371e8a728a9134d8de5447dce4c885f5587294750734",
+ "sha256:d7bc4b7f9c4921eba72677cd9fedd2308f4a4ca3e12fab58935295ad9ea98700",
+ "sha256:d8a9b889aeabd7a4e9af0b7f4ab5ad94d42e7ff679aaec6d0db21e3b639ad58d",
+ "sha256:dacd50501cd017f8cccb328da0c90823511d70d24a323196826d923aad865901",
+ "sha256:e036a3a645fe92309ec34b918394bb377950cbb43039a97edae6c08db64b23e2",
+ "sha256:e09a0a06348a2dd73e7213353c90d709502d9786219f69b731f6caa0efeb46f5",
+ "sha256:e0c8e31cfcc4592cb200160344b2fb6ae0f9e4effe06c644b5a125d4ae5ebe23",
+ "sha256:e1b4951125ec10c70802f2cb09736c895861cd39fd9dcb35107b4dc8ae6220b8",
+ "sha256:e2a9ea08e8c58bb17655630198833109227dea914cd20be660f52215f6de5613",
+ "sha256:e3403f24bcb9c3b29113611c3c16a2a447c3953ecf86b79775e7be06f7ae7ccb",
+ "sha256:e574a7d61cf10351d734bcddabbe15ede0eaa8a02070d85446875dc11189a251",
+ "sha256:e67446b19e014d37342f7195f592a2a948141d15a312fe0e700c2fd2f03124f6",
+ "sha256:e736c93e9c274fce6419af4aac199984d866e55f8a4cec9114671d0ea9688780",
+ "sha256:e7c952aefdf2460f4ae55c5e9c3e80aa72f706a6317e06020f80e96253b1accd",
+ "sha256:e7f8659a48995edee7229522984bd1009c1213929c769c2daa80b40fe49a180c",
+ "sha256:e96eb1a34396e9430c19d8338d2ec33015e4a87ef2b4449db94c22412e25ccdf",
+ "sha256:ec7534e63ae0f3759df3a1ed4fa6bc8f75082a924b590619c0dd2f76d7043caa",
+ "sha256:ed2f9c7216e53c3df02264f25d824b079cc5914f9e2deba94155190ef648ee40",
+ "sha256:eeacf451c99b4525f700f078becff32c32ec327b10dcf31306a8a52d78166de7",
+ "sha256:f10d9c0b0188fe85398c61147bbd2a657d616c876863bfeff43376e0e3134673",
+ "sha256:f2bef8237544f4e42878c61cef4e2839fee6346dc60f5739f876a9c50be7fcdb",
+ "sha256:f33c8748abef4d8717bb20e8fb1b3e07c6adacb7fd6beaae971a764cf5f30d61",
+ "sha256:f7c183e786e299b5d6c49fb43a769f8eb8e04a2726a2bd5887b98b5cc2d67940",
+ "sha256:fa4dcb605c6f82a80c7f95713c2b11c3b8e9893b3ebd2bc9bde93165ed6107be",
+ "sha256:fa89cb11bc71a63b69568d5b8a25c3ca25b6d54c15f907ca1c130d72f320b76b",
+ "sha256:fe242cd381e0fb65758faf5ad96c2e460df6ee5b2de1072fe97e4127927e00b4",
+ "sha256:fe91b87fc295973096251e2d25a811388e7d8adf3bd2b97ef6ae78bc4ac6c476",
+ "sha256:fed38a5edb7945f4d1bcabe2fcd05db4f6ec7e0e82560088b754f7e08d93772d",
+ "sha256:ff0a7b0a82a7ab905cbda74006318d1b12e37c797eb1b0d4eb3e316cf47f658f",
+ "sha256:ff15c147b2ad66da1f2cbb0622313f2242d8e6e8f9b79b5206c84523a4473248",
+ "sha256:ff5e771f5dcbc81c64898c597a434f7682f2259e0cd666932a913d53d1341d1a"
],
"index": "pypi",
- "markers": "python_version >= '3.8'",
- "version": "==3.9.0"
+ "markers": "python_version >= '3.9'",
+ "version": "==3.13.2"
},
"aiosignal": {
"hashes": [
- "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc",
- "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"
+ "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e",
+ "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7"
],
- "markers": "python_version >= '3.7'",
- "version": "==1.3.1"
+ "markers": "python_version >= '3.9'",
+ "version": "==1.4.0"
},
"async-timeout": {
"hashes": [
- "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f",
- "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"
+ "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c",
+ "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"
],
"markers": "python_version < '3.11'",
- "version": "==4.0.3"
+ "version": "==5.0.1"
},
"attrs": {
"hashes": [
- "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04",
- "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"
+ "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11",
+ "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"
],
- "markers": "python_version >= '3.7'",
- "version": "==23.1.0"
+ "markers": "python_version >= '3.9'",
+ "version": "==25.4.0"
},
"brotli": {
"hashes": [
- "sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208",
- "sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48",
- "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354",
- "sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a",
- "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128",
- "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c",
- "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088",
- "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9",
- "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a",
- "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3",
- "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438",
- "sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578",
- "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b",
- "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b",
- "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68",
- "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d",
- "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd",
- "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409",
- "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da",
- "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50",
- "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0",
- "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180",
- "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d",
- "sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112",
- "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc",
- "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265",
- "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327",
- "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95",
- "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd",
- "sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914",
- "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0",
- "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a",
- "sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7",
- "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0",
- "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451",
- "sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f",
- "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e",
- "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248",
- "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91",
- "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724",
- "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966",
- "sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97",
- "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d",
- "sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf",
- "sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac",
- "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951",
- "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74",
- "sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60",
- "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c",
- "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1",
- "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8",
- "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d",
- "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc",
- "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61",
- "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460",
- "sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751",
- "sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9",
- "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1",
- "sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474",
- "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2",
- "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6",
- "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9",
- "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2",
- "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467",
- "sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619",
- "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf",
- "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408",
- "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579",
- "sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84",
- "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b",
- "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59",
- "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752",
- "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80",
- "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0",
- "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2",
- "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3",
- "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64",
- "sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643",
- "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e",
- "sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985",
- "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596",
- "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2",
- "sha256:fdc3ff3bfccdc6b9cc7c342c03aa2400683f0cb891d46e94b64a197910dc4064"
- ],
- "version": "==1.1.0"
+ "sha256:022426c9e99fd65d9475dce5c195526f04bb8be8907607e27e747893f6ee3e24",
+ "sha256:072e7624b1fc4d601036ab3f4f27942ef772887e876beff0301d261210bca97f",
+ "sha256:09ac247501d1909e9ee47d309be760c89c990defbb2e0240845c892ea5ff0de4",
+ "sha256:0bbd5b5ccd157ae7913750476d48099aaf507a79841c0d04a9db4415b14842de",
+ "sha256:0cf8c3b8ba93d496b2fae778039e2f5ecc7cff99df84df337ca31d8f2252896c",
+ "sha256:14ef29fc5f310d34fc7696426071067462c9292ed98b5ff5a27ac70a200e5470",
+ "sha256:15b33fe93cedc4caaff8a0bd1eb7e3dab1c61bb22a0bf5bdfdfd97cd7da79744",
+ "sha256:1b1d6a4efedd53671c793be6dd760fcf2107da3a52331ad9ea429edf0902f27a",
+ "sha256:1b557b29782a643420e08d75aea889462a4a8796e9a6cf5621ab05a3f7da8ef2",
+ "sha256:1b71754d5b6eda54d16fbbed7fce2d8bc6c052a1b91a35c320247946ee103502",
+ "sha256:1ce223652fd4ed3eb2b7f78fbea31c52314baecfac68db44037bb4167062a937",
+ "sha256:1e68cdf321ad05797ee41d1d09169e09d40fdf51a725bb148bff892ce04583d7",
+ "sha256:260d3692396e1895c5034f204f0db022c056f9e2ac841593a4cf9426e2a3faca",
+ "sha256:26e8d3ecb0ee458a9804f47f21b74845cc823fd1bb19f02272be70774f56e2a6",
+ "sha256:2881416badd2a88a7a14d981c103a52a23a276a553a8aacc1346c2ff47c8dc17",
+ "sha256:29b7e6716ee4ea0c59e3b241f682204105f7da084d6254ec61886508efeb43bc",
+ "sha256:2a7f1d03727130fc875448b65b127a9ec5d06d19d0148e7554384229706f9d1b",
+ "sha256:2d39b54b968f4b49b5e845758e202b1035f948b0561ff5e6385e855c96625971",
+ "sha256:2e1ad3fda65ae0d93fec742a128d72e145c9c7a99ee2fcd667785d99eb25a7fe",
+ "sha256:3173e1e57cebb6d1de186e46b5680afbd82fd4301d7b2465beebe83ed317066d",
+ "sha256:3219bd9e69868e57183316ee19c84e03e8f8b5a1d1f2667e1aa8c2f91cb061ac",
+ "sha256:350c8348f0e76fff0a0fd6c26755d2653863279d086d3aa2c290a6a7251135dd",
+ "sha256:35d382625778834a7f3061b15423919aa03e4f5da34ac8e02c074e4b75ab4f84",
+ "sha256:3b90b767916ac44e93a8e28ce6adf8d551e43affb512f2377c732d486ac6514e",
+ "sha256:3e1b35d56856f3ed326b140d3c6d9db91740f22e14b06e840fe4bb1923439a18",
+ "sha256:3ebe801e0f4e56d17cd386ca6600573e3706ce1845376307f5d2cbd32149b69a",
+ "sha256:3f3c908bcc404c90c77d5a073e55271a0a498f4e0756e48127c35d91cf155947",
+ "sha256:40d918bce2b427a0c4ba189df7a006ac0c7277c180aee4617d99e9ccaaf59e6a",
+ "sha256:465a0d012b3d3e4f1d6146ea019b5c11e3e87f03d1676da1cc3833462e672fb0",
+ "sha256:4735a10f738cb5516905a121f32b24ce196ab82cfc1e4ba2e3ad1b371085fd46",
+ "sha256:4ecdb3b6dc36e6d6e14d3a1bdc6c1057c8cbf80db04031d566eb6080ce283a48",
+ "sha256:50b1b799f45da91292ffaa21a473ab3a3054fa78560e8ff67082a185274431c8",
+ "sha256:54a50a9dad16b32136b2241ddea9e4df159b41247b2ce6aac0b3276a66a8f1e5",
+ "sha256:5732eff8973dd995549a18ecbd8acd692ac611c5c0bb3f59fa3541ae27b33be3",
+ "sha256:598e88c736f63a0efec8363f9eb34e5b5536b7b6b1821e401afcb501d881f59a",
+ "sha256:640fe199048f24c474ec6f3eae67c48d286de12911110437a36a87d7c89573a6",
+ "sha256:66c02c187ad250513c2f4fce973ef402d22f80e0adce734ee4e4efd657b6cb64",
+ "sha256:67a91c5187e1eec76a61625c77a6c8c785650f5b576ca732bd33ef58b0dff49c",
+ "sha256:6be67c19e0b0c56365c6a76e393b932fb0e78b3b56b711d180dd7013cb1fd984",
+ "sha256:6c12dad5cd04530323e723787ff762bac749a7b256a5bece32b2243dd5c27b21",
+ "sha256:71a66c1c9be66595d628467401d5976158c97888c2c9379c034e1e2312c5b4f5",
+ "sha256:7274942e69b17f9cef76691bcf38f2b2d4c8a5f5dba6ec10958363dcb3308a0a",
+ "sha256:7547369c4392b47d30a3467fe8c3330b4f2e0f7730e45e3103d7d636678a808b",
+ "sha256:7a47ce5c2288702e09dc22a44d0ee6152f2c7eda97b3c8482d826a1f3cfc7da7",
+ "sha256:7a61c06b334bd99bc5ae84f1eeb36bfe01400264b3c352f968c6e30a10f9d08b",
+ "sha256:7ad8cec81f34edf44a1c6a7edf28e7b7806dfb8886e371d95dcf789ccd4e4982",
+ "sha256:7e9053f5fb4e0dfab89243079b3e217f2aea4085e4d58c5c06115fc34823707f",
+ "sha256:7fa18d65a213abcfbb2f6cafbb4c58863a8bd6f2103d65203c520ac117d1944b",
+ "sha256:81da1b229b1889f25adadc929aeb9dbc4e922bd18561b65b08dd9343cfccca84",
+ "sha256:82676c2781ecf0ab23833796062786db04648b7aae8be139f6b8065e5e7b1518",
+ "sha256:832c115a020e463c2f67664560449a7bea26b0c1fdd690352addad6d0a08714d",
+ "sha256:844a8ceb8483fefafc412f85c14f2aae2fb69567bf2a0de53cdb88b73e7c43ae",
+ "sha256:865cedc7c7c303df5fad14a57bc5db1d4f4f9b2b4d0a7523ddd206f00c121a16",
+ "sha256:88ef7d55b7bcf3331572634c3fd0ed327d237ceb9be6066810d39020a3ebac7a",
+ "sha256:898be2be399c221d2671d29eed26b6b2713a02c2119168ed914e7d00ceadb56f",
+ "sha256:8d4f47f284bdd28629481c97b5f29ad67544fa258d9091a6ed1fda47c7347cd1",
+ "sha256:92edab1e2fd6cd5ca605f57d4545b6599ced5dea0fd90b2bcdf8b247a12bd190",
+ "sha256:9322b9f8656782414b37e6af884146869d46ab85158201d82bab9abbcb971dc7",
+ "sha256:95db242754c21a88a79e01504912e537808504465974ebb92931cfca2510469e",
+ "sha256:963a08f3bebd8b75ac57661045402da15991468a621f014be54e50f53a58d19e",
+ "sha256:96fbe82a58cdb2f872fa5d87dedc8477a12993626c446de794ea025bbda625ea",
+ "sha256:99cfa69813d79492f0e5d52a20fd18395bc82e671d5d40bd5a91d13e75e468e8",
+ "sha256:9c79f57faa25d97900bfb119480806d783fba83cd09ee0b33c17623935b05fa3",
+ "sha256:9e5825ba2c9998375530504578fd4d5d1059d09621a02065d1b6bfc41a8e05ab",
+ "sha256:9fe11467c42c133f38d42289d0861b6b4f9da31e8087ca2c0d7ebb4543625526",
+ "sha256:a1778532b978d2536e79c05dac2d8cd857f6c55cd0c95ace5b03740824e0e2f1",
+ "sha256:a387225a67f619bf16bd504c37655930f910eb03675730fc2ad69d3d8b5e7e92",
+ "sha256:a56ef534b66a749759ebd091c19c03ef81eb8cd96f0d1d16b59127eaf1b97a12",
+ "sha256:aa47441fa3026543513139cb8926a92a8e305ee9c71a6209ef7a97d91640ea03",
+ "sha256:ac27a70bda257ae3f380ec8310b0a06680236bea547756c277b5dfe55a2452a8",
+ "sha256:acec55bb7c90f1dfc476126f9711a8e81c9af7fb617409a9ee2953115343f08d",
+ "sha256:adedc4a67e15327dfdd04884873c6d5a01d3e3b6f61406f99b1ed4865a2f6d28",
+ "sha256:af43b8711a8264bb4e7d6d9a6d004c3a2019c04c01127a868709ec29962b6036",
+ "sha256:b232029d100d393ae3c603c8ffd7e3fe6f798c5e28ddca5feabb8e8fdb732997",
+ "sha256:b35c13ce241abdd44cb8ca70683f20c0c079728a36a996297adb5334adfc1c44",
+ "sha256:b63daa43d82f0cdabf98dee215b375b4058cce72871fd07934f179885aad16e8",
+ "sha256:b908d1a7b28bc72dfb743be0d4d3f8931f8309f810af66c906ae6cd4127c93cb",
+ "sha256:ba76177fd318ab7b3b9bf6522be5e84c2ae798754b6cc028665490f6e66b5533",
+ "sha256:bba6e7e6cfe1e6cb6eb0b7c2736a6059461de1fa2c0ad26cf845de6c078d16c8",
+ "sha256:c0d6770111d1879881432f81c369de5cde6e9467be7c682a983747ec800544e2",
+ "sha256:c16ab1ef7bb55651f5836e8e62db1f711d55b82ea08c3b8083ff037157171a69",
+ "sha256:c1702888c9f3383cc2f09eb3e88b8babf5965a54afb79649458ec7c3c7a63e96",
+ "sha256:c25332657dee6052ca470626f18349fc1fe8855a56218e19bd7a8c6ad4952c49",
+ "sha256:c8565e3cdc1808b1a34714b553b262c5de5fbda202285782173ec137fd13709f",
+ "sha256:cf9cba6f5b78a2071ec6fb1e7bd39acf35071d90a81231d67e92d637776a6a63",
+ "sha256:d206a36b4140fbb5373bf1eb73fb9de589bb06afd0d22376de23c5e91d0ab35f",
+ "sha256:d2d085ded05278d1c7f65560aae97b3160aeb2ea2c0b3e26204856beccb60888",
+ "sha256:d8c05b1dfb61af28ef37624385b0029df902ca896a639881f594060b30ffc9a7",
+ "sha256:e310f77e41941c13340a95976fe66a8a95b01e783d430eeaf7a2f87e0a57dd0a",
+ "sha256:e7c0af964e0b4e3412a0ebf341ea26ec767fa0b4cf81abb5e897c9338b5ad6a3",
+ "sha256:e80a28f2b150774844c8b454dd288be90d76ba6109670fe33d7ff54d96eb5cb8",
+ "sha256:e813da3d2d865e9793ef681d3a6b66fa4b7c19244a45b817d0cceda67e615990",
+ "sha256:e85190da223337a6b7431d92c799fca3e2982abd44e7b8dec69938dcc81c8e9e",
+ "sha256:e99befa0b48f3cd293dafeacdd0d191804d105d279e0b387a32054c1180f3161",
+ "sha256:eda5a6d042c698e28bda2507a89b16555b9aa954ef1d750e1c20473481aff675",
+ "sha256:ef87b8ab2704da227e83a246356a2b179ef826f550f794b2c52cddb4efbd0196",
+ "sha256:f16dace5e4d3596eaeb8af334b4d2c820d34b8278da633ce4a00020b2eac981c",
+ "sha256:f8d635cafbbb0c61327f942df2e3f474dde1cff16c3cd0580564774eaba1ee13",
+ "sha256:fc1530af5c3c275b8524f2e24841cbe2599d74462455e9bae5109e9ff42e9361",
+ "sha256:ff09cd8c5eec3b9d02d2408db41be150d8891c5566addce57513bf546e3d6c6d"
+ ],
+ "version": "==1.2.0"
},
"cairocffi": {
"hashes": [
- "sha256:78e6bbe47357640c453d0be929fa49cd05cce2e1286f3d2a1ca9cbda7efdb8b7",
- "sha256:aa78ee52b9069d7475eeac457389b6275aa92111895d78fbaa2202a52dac112e"
+ "sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b",
+ "sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f"
],
- "markers": "python_version >= '3.7'",
- "version": "==1.6.1"
+ "markers": "python_version >= '3.8'",
+ "version": "==1.7.1"
},
"cairosvg": {
"hashes": [
- "sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0",
- "sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b"
+ "sha256:07cbf4e86317b27a92318a4cac2a4bb37a5e9c1b8a27355d06874b22f85bef9f",
+ "sha256:eab46dad4674f33267a671dce39b64be245911c901c70d65d2b7b0821e852bf5"
],
- "markers": "python_version >= '3.5'",
- "version": "==2.7.1"
+ "markers": "python_version >= '3.9'",
+ "version": "==2.8.2"
},
"certifi": {
"hashes": [
- "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1",
- "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"
+ "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b",
+ "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"
],
- "markers": "python_version >= '3.6'",
- "version": "==2023.11.17"
+ "markers": "python_version >= '3.7'",
+ "version": "==2025.11.12"
},
"cffi": {
"hashes": [
- "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc",
- "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a",
- "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417",
- "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab",
- "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520",
- "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36",
- "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743",
- "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8",
- "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed",
- "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684",
- "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56",
- "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324",
- "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d",
- "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235",
- "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e",
- "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088",
- "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000",
- "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7",
- "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e",
- "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673",
- "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c",
- "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe",
- "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2",
- "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098",
- "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8",
- "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a",
- "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0",
- "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b",
- "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896",
- "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e",
- "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9",
- "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2",
- "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b",
- "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6",
- "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404",
- "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f",
- "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0",
- "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4",
- "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc",
- "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936",
- "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba",
- "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872",
- "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb",
- "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614",
- "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1",
- "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d",
- "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969",
- "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b",
- "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4",
- "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627",
- "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956",
- "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==1.16.0"
+ "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb",
+ "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b",
+ "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f",
+ "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9",
+ "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44",
+ "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2",
+ "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c",
+ "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75",
+ "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65",
+ "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e",
+ "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a",
+ "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e",
+ "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25",
+ "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a",
+ "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe",
+ "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b",
+ "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91",
+ "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592",
+ "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187",
+ "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c",
+ "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1",
+ "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94",
+ "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba",
+ "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb",
+ "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165",
+ "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529",
+ "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca",
+ "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c",
+ "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6",
+ "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c",
+ "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0",
+ "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743",
+ "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63",
+ "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5",
+ "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5",
+ "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4",
+ "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d",
+ "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b",
+ "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93",
+ "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205",
+ "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27",
+ "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512",
+ "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d",
+ "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c",
+ "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037",
+ "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26",
+ "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322",
+ "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb",
+ "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c",
+ "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8",
+ "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4",
+ "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414",
+ "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9",
+ "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664",
+ "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9",
+ "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775",
+ "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739",
+ "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc",
+ "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062",
+ "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe",
+ "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9",
+ "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92",
+ "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5",
+ "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13",
+ "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d",
+ "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26",
+ "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f",
+ "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495",
+ "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b",
+ "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6",
+ "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c",
+ "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef",
+ "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5",
+ "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18",
+ "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad",
+ "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3",
+ "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7",
+ "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5",
+ "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534",
+ "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49",
+ "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2",
+ "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5",
+ "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453",
+ "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==2.0.0"
},
"charset-normalizer": {
"hashes": [
- "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027",
- "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087",
- "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786",
- "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8",
- "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09",
- "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185",
- "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574",
- "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e",
- "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519",
- "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898",
- "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269",
- "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3",
- "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f",
- "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6",
- "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8",
- "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a",
- "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73",
- "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc",
- "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714",
- "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2",
- "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc",
- "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce",
- "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d",
- "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e",
- "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6",
- "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269",
- "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96",
- "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d",
- "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a",
- "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4",
- "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77",
- "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d",
- "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0",
- "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed",
- "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068",
- "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac",
- "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25",
- "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8",
- "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab",
- "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26",
- "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2",
- "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db",
- "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f",
- "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5",
- "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99",
- "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c",
- "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d",
- "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811",
- "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa",
- "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a",
- "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03",
- "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b",
- "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04",
- "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c",
- "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001",
- "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458",
- "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389",
- "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99",
- "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985",
- "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537",
- "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238",
- "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f",
- "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d",
- "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796",
- "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a",
- "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143",
- "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8",
- "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c",
- "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5",
- "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5",
- "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711",
- "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4",
- "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6",
- "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c",
- "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7",
- "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4",
- "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b",
- "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae",
- "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12",
- "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c",
- "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae",
- "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8",
- "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887",
- "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b",
- "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4",
- "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f",
- "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5",
- "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33",
- "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519",
- "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"
- ],
- "markers": "python_full_version >= '3.7.0'",
- "version": "==3.3.2"
+ "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad",
+ "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93",
+ "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394",
+ "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89",
+ "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc",
+ "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86",
+ "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63",
+ "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d",
+ "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f",
+ "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8",
+ "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0",
+ "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505",
+ "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161",
+ "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af",
+ "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152",
+ "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318",
+ "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72",
+ "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4",
+ "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e",
+ "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3",
+ "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576",
+ "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c",
+ "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1",
+ "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8",
+ "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1",
+ "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2",
+ "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44",
+ "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26",
+ "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88",
+ "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016",
+ "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede",
+ "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf",
+ "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a",
+ "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc",
+ "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0",
+ "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84",
+ "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db",
+ "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1",
+ "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7",
+ "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed",
+ "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8",
+ "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133",
+ "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e",
+ "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef",
+ "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14",
+ "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2",
+ "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0",
+ "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d",
+ "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828",
+ "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f",
+ "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf",
+ "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6",
+ "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328",
+ "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090",
+ "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa",
+ "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381",
+ "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c",
+ "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb",
+ "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc",
+ "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a",
+ "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec",
+ "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc",
+ "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac",
+ "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e",
+ "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313",
+ "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569",
+ "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3",
+ "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d",
+ "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525",
+ "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894",
+ "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3",
+ "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9",
+ "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a",
+ "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9",
+ "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14",
+ "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25",
+ "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50",
+ "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf",
+ "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1",
+ "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3",
+ "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac",
+ "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e",
+ "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815",
+ "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c",
+ "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6",
+ "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6",
+ "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e",
+ "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4",
+ "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84",
+ "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69",
+ "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15",
+ "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191",
+ "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0",
+ "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897",
+ "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd",
+ "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2",
+ "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794",
+ "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d",
+ "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074",
+ "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3",
+ "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224",
+ "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838",
+ "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a",
+ "sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d",
+ "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d",
+ "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f",
+ "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8",
+ "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490",
+ "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966",
+ "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9",
+ "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3",
+ "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e",
+ "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==3.4.4"
},
"colorama": {
"hashes": [
@@ -405,11 +522,11 @@
},
"cssselect2": {
"hashes": [
- "sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a",
- "sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969"
+ "sha256:46fc70ebc41ced7a32cd42d58b1884d72ade23d21e5a4eaaf022401c13f0e76e",
+ "sha256:7674ffb954a3b46162392aee2a3a0aedb2e14ecf99fcc28644900f4e6e3e9d3a"
],
- "markers": "python_version >= '3.7'",
- "version": "==0.7.0"
+ "markers": "python_version >= '3.9'",
+ "version": "==0.8.0"
},
"defusedxml": {
"hashes": [
@@ -424,19 +541,20 @@
"speed"
],
"hashes": [
- "sha256:4560f70f2eddba7e83370ecebd237ac09fbb4980dc66507482b0c0e5b8f76b9c",
- "sha256:9da4679fc3cb10c64b388284700dc998663e0e57328283bbfcfc2525ec5960a6"
+ "sha256:69835269d73d9889a2f0efff4c91264a18998db0fdc4295a3c886fe9196dea4e",
+ "sha256:92bb3ef9dbe08525803be1e357bc0191f59ae16956690fc96c34f40bcd02c649"
],
- "markers": "python_full_version >= '3.8.0'",
- "version": "==2.3.2"
+ "markers": "python_version >= '3.8'",
+ "version": "==2.6.3"
},
"dnspython": {
"hashes": [
- "sha256:57c6fbaaeaaf39c891292012060beb141791735dbb4004798328fc2c467402d8",
- "sha256:8dcfae8c7460a2f84b4072e26f1c9f4101ca20c071649cb7c34e8b6a93d58984"
+ "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af",
+ "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f"
],
- "markers": "python_version >= '3.8' and python_version < '4.0'",
- "version": "==2.4.2"
+ "index": "pypi",
+ "markers": "python_version >= '3.10'",
+ "version": "==2.8.0"
},
"emoji": {
"hashes": [
@@ -449,78 +567,147 @@
},
"frozenlist": {
"hashes": [
- "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6",
- "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01",
- "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251",
- "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9",
- "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b",
- "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87",
- "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf",
- "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f",
- "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0",
- "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2",
- "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b",
- "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc",
- "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c",
- "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467",
- "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9",
- "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1",
- "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a",
- "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79",
- "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167",
- "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300",
- "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf",
- "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea",
- "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2",
- "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab",
- "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3",
- "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb",
- "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087",
- "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc",
- "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8",
- "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62",
- "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f",
- "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326",
- "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c",
- "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431",
- "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963",
- "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7",
- "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef",
- "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3",
- "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956",
- "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781",
- "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472",
- "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc",
- "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839",
- "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672",
- "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3",
- "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503",
- "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d",
- "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8",
- "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b",
- "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc",
- "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f",
- "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559",
- "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b",
- "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95",
- "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb",
- "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963",
- "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919",
- "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f",
- "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3",
- "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1",
- "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==1.4.0"
+ "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686",
+ "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0",
+ "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121",
+ "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd",
+ "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7",
+ "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c",
+ "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84",
+ "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d",
+ "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b",
+ "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79",
+ "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967",
+ "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f",
+ "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4",
+ "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7",
+ "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef",
+ "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9",
+ "sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3",
+ "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd",
+ "sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087",
+ "sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068",
+ "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7",
+ "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed",
+ "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b",
+ "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f",
+ "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25",
+ "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe",
+ "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143",
+ "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e",
+ "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930",
+ "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37",
+ "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128",
+ "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2",
+ "sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675",
+ "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f",
+ "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746",
+ "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df",
+ "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8",
+ "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c",
+ "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0",
+ "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad",
+ "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82",
+ "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29",
+ "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c",
+ "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30",
+ "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf",
+ "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62",
+ "sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5",
+ "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383",
+ "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c",
+ "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52",
+ "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d",
+ "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1",
+ "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a",
+ "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714",
+ "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65",
+ "sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95",
+ "sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1",
+ "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506",
+ "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888",
+ "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6",
+ "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41",
+ "sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459",
+ "sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a",
+ "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608",
+ "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa",
+ "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8",
+ "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1",
+ "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186",
+ "sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6",
+ "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed",
+ "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e",
+ "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52",
+ "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231",
+ "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450",
+ "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496",
+ "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a",
+ "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3",
+ "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24",
+ "sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178",
+ "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695",
+ "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7",
+ "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4",
+ "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e",
+ "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e",
+ "sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61",
+ "sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca",
+ "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad",
+ "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b",
+ "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a",
+ "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8",
+ "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51",
+ "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011",
+ "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8",
+ "sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103",
+ "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b",
+ "sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda",
+ "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806",
+ "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042",
+ "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e",
+ "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b",
+ "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef",
+ "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d",
+ "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567",
+ "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a",
+ "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2",
+ "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0",
+ "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e",
+ "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b",
+ "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d",
+ "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a",
+ "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52",
+ "sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47",
+ "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1",
+ "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94",
+ "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f",
+ "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff",
+ "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822",
+ "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a",
+ "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11",
+ "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581",
+ "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51",
+ "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565",
+ "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40",
+ "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92",
+ "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2",
+ "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5",
+ "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4",
+ "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93",
+ "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027",
+ "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==1.8.0"
},
"idna": {
"hashes": [
- "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4",
- "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"
+ "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea",
+ "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"
],
- "markers": "python_version >= '3.5'",
- "version": "==3.4"
+ "markers": "python_version >= '3.8'",
+ "version": "==3.11"
},
"isodate": {
"hashes": [
@@ -535,99 +722,171 @@
"pdf"
],
"hashes": [
- "sha256:a3242f8ba37051fbdd7503ecd168203a08e4af26f17be2ecca08a64af1e7d3c1"
+ "sha256:85304ac152cd042c9fe98a527b5d136a31c6fe2aacd859ce1c58189bb946d127"
],
"markers": "python_version >= '3'",
- "version": "==0.7.0"
+ "version": "==0.7.2"
},
"motor": {
"hashes": [
- "sha256:6fe7e6f0c4f430b9e030b9d22549b732f7c2226af3ab71ecc309e4a1b7d19953",
- "sha256:d2fc38de15f1c8058f389c1a44a4d4105c0405c48c061cd492a654496f7bc26a"
+ "sha256:27b4d46625c87928f331a6ca9d7c51c2f518ba0e270939d395bc1ddc89d64526",
+ "sha256:8a63b9049e38eeeb56b4fdd57c3312a6d1f25d01db717fe7d82222393c410298"
],
"index": "pypi",
- "markers": "python_version >= '3.7'",
- "version": "==3.3.2"
+ "markers": "python_version >= '3.9'",
+ "version": "==3.7.1"
},
"multidict": {
"hashes": [
- "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9",
- "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8",
- "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03",
- "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710",
- "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161",
- "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664",
- "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569",
- "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067",
- "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313",
- "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706",
- "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2",
- "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636",
- "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49",
- "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93",
- "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603",
- "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0",
- "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60",
- "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4",
- "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e",
- "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1",
- "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60",
- "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951",
- "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc",
- "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe",
- "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95",
- "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d",
- "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8",
- "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed",
- "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2",
- "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775",
- "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87",
- "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c",
- "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2",
- "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98",
- "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3",
- "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe",
- "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78",
- "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660",
- "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176",
- "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e",
- "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988",
- "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c",
- "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c",
- "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0",
- "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449",
- "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f",
- "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde",
- "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5",
- "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d",
- "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac",
- "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a",
- "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9",
- "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca",
- "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11",
- "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35",
- "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063",
- "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b",
- "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982",
- "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258",
- "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1",
- "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52",
- "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480",
- "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7",
- "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461",
- "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d",
- "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc",
- "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779",
- "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a",
- "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547",
- "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0",
- "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171",
- "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf",
- "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d",
- "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==6.0.4"
+ "sha256:03ca744319864e92721195fa28c7a3b2bc7b686246b35e4078c1e4d0eb5466d3",
+ "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec",
+ "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd",
+ "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b",
+ "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb",
+ "sha256:08325c9e5367aa379a3496aa9a022fe8837ff22e00b94db256d3a1378c76ab32",
+ "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f",
+ "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7",
+ "sha256:096f52730c3fb8ed419db2d44391932b63891b2c5ed14850a7e215c0ba9ade36",
+ "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd",
+ "sha256:0a13fb8e748dfc94749f622de065dd5c1def7e0d2216dba72b1d8069a389c6ff",
+ "sha256:0db4956f82723cc1c270de9c6e799b4c341d327762ec78ef82bb962f79cc07d8",
+ "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d",
+ "sha256:14c9e076eede3b54c636f8ce1c9c252b5f057c62131211f0ceeec273810c9721",
+ "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0",
+ "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3",
+ "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d",
+ "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa",
+ "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10",
+ "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202",
+ "sha256:23bfeee5316266e5ee2d625df2d2c602b829435fc3a235c2ba2131495706e4a0",
+ "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718",
+ "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e",
+ "sha256:295a92a76188917c7f99cda95858c822f9e4aae5824246bba9b6b44004ddd0a6",
+ "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1",
+ "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2",
+ "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754",
+ "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c",
+ "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390",
+ "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128",
+ "sha256:329aa225b085b6f004a4955271a7ba9f1087e39dcb7e65f6284a988264a63912",
+ "sha256:363eb68a0a59bd2303216d2346e6c441ba10d36d1f9969fcb6f1ba700de7bb5c",
+ "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3",
+ "sha256:3996b50c3237c4aec17459217c1e7bbdead9a22a0fcd3c365564fbd16439dde6",
+ "sha256:39f1719f57adbb767ef592a50ae5ebb794220d1188f9ca93de471336401c34d2",
+ "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f",
+ "sha256:3ba3ef510467abb0667421a286dc906e30eb08569365f5cdb131d7aff7c2dd84",
+ "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842",
+ "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9",
+ "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6",
+ "sha256:3e56d780c238f9e1ae66a22d2adf8d16f485381878250db8d496623cd38b22bd",
+ "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8",
+ "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599",
+ "sha256:478cc36476687bac1514d651cbbaa94b86b0732fb6855c60c673794c7dd2da62",
+ "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec",
+ "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34",
+ "sha256:4b73189894398d59131a66ff157837b1fafea9974be486d036bb3d32331fdbf0",
+ "sha256:4b7a9db5a870f780220e931d0002bbfd88fb53aceb6293251e2c839415c1b20e",
+ "sha256:4c09703000a9d0fa3c3404b27041e574cc7f4df4c6563873246d0e11812a94b6",
+ "sha256:4d409aa42a94c0b3fa617708ef5276dfe81012ba6753a0370fcc9d0195d0a1fc",
+ "sha256:4d72a9a2d885f5c208b0cb91ff2ed43636bb7e345ec839ff64708e04f69a13cc",
+ "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c",
+ "sha256:51cb455de290ae462593e5b1cb1118c5c22ea7f0d3620d9940bf695cea5a4bd7",
+ "sha256:521f33e377ff64b96c4c556b81c55d0cfffb96a11c194fd0c3f1e56f3d8dd5a4",
+ "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4",
+ "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38",
+ "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5",
+ "sha256:661709cdcd919a2ece2234f9bae7174e5220c80b034585d7d8a755632d3e2111",
+ "sha256:680878b9f3d45c31e1f730eef731f9b0bc1da456155688c6745ee84eb818e90e",
+ "sha256:6843b28b0364dc605f21481c90fadb5f60d9123b442eb8a726bb74feef588a84",
+ "sha256:68af405971779d8b37198726f2b6fe3955db846fee42db7a4286fc542203934c",
+ "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1",
+ "sha256:6bdce131e14b04fd34a809b6380dbfd826065c3e2fe8a50dbae659fa0c390546",
+ "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a",
+ "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c",
+ "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036",
+ "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38",
+ "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99",
+ "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64",
+ "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e",
+ "sha256:7e73299c99939f089dd9b2120a04a516b95cdf8c1cd2b18c53ebf0de80b1f18f",
+ "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159",
+ "sha256:7f5170993a0dd3ab871c74f45c0a21a4e2c37a2f2b01b5f722a2ad9c6650469e",
+ "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12",
+ "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1",
+ "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0",
+ "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184",
+ "sha256:8b55d5497b51afdfde55925e04a022f1de14d4f4f25cdfd4f5d9b0aa96166851",
+ "sha256:8cfc12a8630a29d601f48d47787bd7eb730e475e83edb5d6c5084317463373eb",
+ "sha256:9281bf5b34f59afbc6b1e477a372e9526b66ca446f4bf62592839c195a718b32",
+ "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b",
+ "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288",
+ "sha256:95b5ffa4349df2887518bb839409bcf22caa72d82beec453216802f475b23c81",
+ "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd",
+ "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45",
+ "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a",
+ "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca",
+ "sha256:9cf41880c991716f3c7cec48e2f19ae4045fc9db5fc9cff27347ada24d710bb5",
+ "sha256:9d14baca2ee12c1a64740d4531356ba50b82543017f3ad6de0deb943c5979abb",
+ "sha256:9f474ad5acda359c8758c8accc22032c6abe6dc87a8be2440d097785e27a9349",
+ "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b",
+ "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f",
+ "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32",
+ "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5",
+ "sha256:a048ce45dcdaaf1defb76b2e684f997fb5abf74437b6cb7b22ddad934a964e34",
+ "sha256:a265acbb7bb33a3a2d626afbe756371dce0279e7b17f4f4eda406459c2b5ff1c",
+ "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4",
+ "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17",
+ "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60",
+ "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394",
+ "sha256:a90af66facec4cebe4181b9e62a68be65e45ac9b52b67de9eec118701856e7ff",
+ "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00",
+ "sha256:afa8a2978ec65d2336305550535c9c4ff50ee527914328c8677b3973ade52b85",
+ "sha256:b15b3afff74f707b9275d5ba6a91ae8f6429c3ffb29bbfd216b0b375a56f13d7",
+ "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304",
+ "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13",
+ "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e",
+ "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e",
+ "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792",
+ "sha256:b61189b29081a20c7e4e0b49b44d5d44bb0dc92be3c6d06a11cc043f81bf9329",
+ "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb",
+ "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b",
+ "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000",
+ "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6",
+ "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62",
+ "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63",
+ "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5",
+ "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e",
+ "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c",
+ "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827",
+ "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8",
+ "sha256:ce8fdc2dca699f8dbf055a61d73eaa10482569ad20ee3c36ef9641f69afa8c91",
+ "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96",
+ "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad",
+ "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6",
+ "sha256:d874eb056410ca05fed180b6642e680373688efafc7f077b2a2f61811e873a40",
+ "sha256:db99677b4457c7a5c5a949353e125ba72d62b35f74e26da141530fbb012218a7",
+ "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4",
+ "sha256:df0e3bf7993bdbeca5ac25aa859cf40d39019e015c9c91809ba7093967f7a648",
+ "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064",
+ "sha256:e2862408c99f84aa571ab462d25236ef9cb12a602ea959ba9c9009a54902fc73",
+ "sha256:e3aa16de190d29a0ea1b48253c57d99a68492c8dd8948638073ab9e74dc9410b",
+ "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762",
+ "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e",
+ "sha256:eb866162ef2f45063acc7a53a88ef6fe8bf121d45c30ea3c9cd87ce7e191a8d4",
+ "sha256:ec81878ddf0e98817def1e77d4f50dae5ef5b0e4fe796fae3bd674304172416e",
+ "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546",
+ "sha256:f0e77e3c0008bc9316e662624535b88d360c3a5d3f81e15cf12c139a75250046",
+ "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6",
+ "sha256:f470f68adc395e0183b92a2f4689264d1ea4b40504a24d9882c27375e6662bb9",
+ "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d",
+ "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf",
+ "sha256:f8e5c0031b90ca9ce555e2e8fd5c3b02a25f14989cbc310701823832c99eb687",
+ "sha256:fb287618b9c7aa3bf8d825f02d9201b2f13078a5ed3b293c8f4d953917d84d5e",
+ "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885",
+ "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==6.7.0"
},
"natural": {
"hashes": [
@@ -638,58 +897,97 @@
},
"orjson": {
"hashes": [
- "sha256:06ad5543217e0e46fd7ab7ea45d506c76f878b87b1b4e369006bdb01acc05a83",
- "sha256:0a73160e823151f33cdc05fe2cea557c5ef12fdf276ce29bb4f1c571c8368a60",
- "sha256:1234dc92d011d3554d929b6cf058ac4a24d188d97be5e04355f1b9223e98bbe9",
- "sha256:1d0dc4310da8b5f6415949bd5ef937e60aeb0eb6b16f95041b5e43e6200821fb",
- "sha256:2a11b4b1a8415f105d989876a19b173f6cdc89ca13855ccc67c18efbd7cbd1f8",
- "sha256:2e2ecd1d349e62e3960695214f40939bbfdcaeaaa62ccc638f8e651cf0970e5f",
- "sha256:3a2ce5ea4f71681623f04e2b7dadede3c7435dfb5e5e2d1d0ec25b35530e277b",
- "sha256:3e892621434392199efb54e69edfff9f699f6cc36dd9553c5bf796058b14b20d",
- "sha256:3fb205ab52a2e30354640780ce4587157a9563a68c9beaf52153e1cea9aa0921",
- "sha256:4689270c35d4bb3102e103ac43c3f0b76b169760aff8bcf2d401a3e0e58cdb7f",
- "sha256:49f8ad582da6e8d2cf663c4ba5bf9f83cc052570a3a767487fec6af839b0e777",
- "sha256:4bd176f528a8151a6efc5359b853ba3cc0e82d4cd1fab9c1300c5d957dc8f48c",
- "sha256:4cf7837c3b11a2dfb589f8530b3cff2bd0307ace4c301e8997e95c7468c1378e",
- "sha256:4fd72fab7bddce46c6826994ce1e7de145ae1e9e106ebb8eb9ce1393ca01444d",
- "sha256:5148bab4d71f58948c7c39d12b14a9005b6ab35a0bdf317a8ade9a9e4d9d0bd5",
- "sha256:5869e8e130e99687d9e4be835116c4ebd83ca92e52e55810962446d841aba8de",
- "sha256:602a8001bdf60e1a7d544be29c82560a7b49319a0b31d62586548835bbe2c862",
- "sha256:61804231099214e2f84998316f3238c4c2c4aaec302df12b21a64d72e2a135c7",
- "sha256:666c6fdcaac1f13eb982b649e1c311c08d7097cbda24f32612dae43648d8db8d",
- "sha256:674eb520f02422546c40401f4efaf8207b5e29e420c17051cddf6c02783ff5ca",
- "sha256:7ec960b1b942ee3c69323b8721df2a3ce28ff40e7ca47873ae35bfafeb4555ca",
- "sha256:7f433be3b3f4c66016d5a20e5b4444ef833a1f802ced13a2d852c637f69729c1",
- "sha256:7f8fb7f5ecf4f6355683ac6881fd64b5bb2b8a60e3ccde6ff799e48791d8f864",
- "sha256:81a3a3a72c9811b56adf8bcc829b010163bb2fc308877e50e9910c9357e78521",
- "sha256:858379cbb08d84fe7583231077d9a36a1a20eb72f8c9076a45df8b083724ad1d",
- "sha256:8b9ba0ccd5a7f4219e67fbbe25e6b4a46ceef783c42af7dbc1da548eb28b6531",
- "sha256:92af0d00091e744587221e79f68d617b432425a7e59328ca4c496f774a356071",
- "sha256:9ebbdbd6a046c304b1845e96fbcc5559cd296b4dfd3ad2509e33c4d9ce07d6a1",
- "sha256:9edd2856611e5050004f4722922b7b1cd6268da34102667bd49d2a2b18bafb81",
- "sha256:a353bf1f565ed27ba71a419b2cd3db9d6151da426b61b289b6ba1422a702e643",
- "sha256:b5b7d4a44cc0e6ff98da5d56cde794385bdd212a86563ac321ca64d7f80c80d1",
- "sha256:b90f340cb6397ec7a854157fac03f0c82b744abdd1c0941a024c3c29d1340aff",
- "sha256:c18a4da2f50050a03d1da5317388ef84a16013302a5281d6f64e4a3f406aabc4",
- "sha256:c338ed69ad0b8f8f8920c13f529889fe0771abbb46550013e3c3d01e5174deef",
- "sha256:c5a02360e73e7208a872bf65a7554c9f15df5fe063dc047f79738998b0506a14",
- "sha256:c62b6fa2961a1dcc51ebe88771be5319a93fd89bd247c9ddf732bc250507bc2b",
- "sha256:c812312847867b6335cfb264772f2a7e85b3b502d3a6b0586aa35e1858528ab1",
- "sha256:c943b35ecdf7123b2d81d225397efddf0bce2e81db2f3ae633ead38e85cd5ade",
- "sha256:ce0a29c28dfb8eccd0f16219360530bc3cfdf6bf70ca384dacd36e6c650ef8e8",
- "sha256:cf80b550092cc480a0cbd0750e8189247ff45457e5a023305f7ef1bcec811616",
- "sha256:cff7570d492bcf4b64cc862a6e2fb77edd5e5748ad715f487628f102815165e9",
- "sha256:d2c1e559d96a7f94a4f581e2a32d6d610df5840881a8cba8f25e446f4d792df3",
- "sha256:deeb3922a7a804755bbe6b5be9b312e746137a03600f488290318936c1a2d4dc",
- "sha256:e28a50b5be854e18d54f75ef1bb13e1abf4bc650ab9d635e4258c58e71eb6ad5",
- "sha256:e99c625b8c95d7741fe057585176b1b8783d46ed4b8932cf98ee145c4facf499",
- "sha256:ec6f18f96b47299c11203edfbdc34e1b69085070d9a3d1f302810cc23ad36bf3",
- "sha256:ed8bc367f725dfc5cabeed1ae079d00369900231fbb5a5280cf0736c30e2adf7",
- "sha256:ee5926746232f627a3be1cc175b2cfad24d0170d520361f4ce3fa2fd83f09e1d",
- "sha256:f295efcd47b6124b01255d1491f9e46f17ef40d3d7eabf7364099e463fb45f0f",
- "sha256:fb0b361d73f6b8eeceba47cd37070b5e6c9de5beaeaa63a1cb35c7e1a73ef088"
- ],
- "version": "==3.9.10"
+ "sha256:01ee5487fefee21e6910da4c2ee9eef005bee568a0879834df86f888d2ffbdd9",
+ "sha256:03bfa548cf35e3f8b3a96c4e8e41f753c686ff3d8e182ce275b1751deddab58c",
+ "sha256:04b69c14615fb4434ab867bf6f38b2d649f6f300af30a6705397e895f7aec67a",
+ "sha256:09bf242a4af98732db9f9a1ec57ca2604848e16f132e3f72edfd3c5c96de009a",
+ "sha256:0a54d6635fa3aaa438ae32e8570b9f0de36f3f6562c308d2a2a452e8b0592db1",
+ "sha256:0b2eba969ea4203c177c7b38b36c69519e6067ee68c34dc37081fac74c796e10",
+ "sha256:0baa0ea43cfa5b008a28d3c07705cf3ada40e5d347f0f44994a64b1b7b4b5350",
+ "sha256:1469d254b9884f984026bd9b0fa5bbab477a4bfe558bba6848086f6d43eb5e73",
+ "sha256:149d95d5e018bdd822e3f38c103b1a7c91f88d38a88aada5c4e9b3a73a244241",
+ "sha256:1e3704d35e47d5bee811fb1cbd8599f0b4009b14d451c4c57be5a7e25eb89a13",
+ "sha256:1e539e382cf46edec157ad66b0b0872a90d829a6b71f17cb633d6c160a223155",
+ "sha256:23ef7abc7fca96632d8174ac115e668c1e931b8fe4dde586e92a500bf1914dcc",
+ "sha256:26a20f3fbc6c7ff2cb8e89c4c5897762c9d88cf37330c6a117312365d6781d54",
+ "sha256:2c82e4f0b1c712477317434761fbc28b044c838b6b1240d895607441412371ac",
+ "sha256:2d6737d0e616a6e053c8b4acc9eccea6b6cce078533666f32d140e4f85002534",
+ "sha256:3740bffd9816fc0326ddc406098a3a8f387e42223f5f455f2a02a9f834ead80c",
+ "sha256:38aa9e65c591febb1b0aed8da4d469eba239d434c218562df179885c94e1a3ad",
+ "sha256:39485f4ab4c9b30a3943cfe99e1a213c4776fb69e8abd68f66b83d5a0b0fdc6d",
+ "sha256:3b2427ed5791619851c52a1261b45c233930977e7de8cf36de05636c708fa905",
+ "sha256:3c36e524af1d29982e9b190573677ea02781456b2e537d5840e4538a5ec41907",
+ "sha256:3d40d46f348c0321df01507f92b95a377240c4ec31985225a6668f10e2676f9a",
+ "sha256:3e0a700c4b82144b72946b6629968df9762552ee1344bfdb767fecdd634fbd5a",
+ "sha256:405261b0a8c62bcbd8e2931c26fdc08714faf7025f45531541e2b29e544b545b",
+ "sha256:41bf25fb39a34cf8edb4398818523277ee7096689db352036a9e8437f2f3ee6b",
+ "sha256:42d43a1f552be1a112af0b21c10a5f553983c2a0938d2bbb8ecd8bc9fb572803",
+ "sha256:4806363144bb6e7297b8e95870e78d30a649fdc4e23fc84daa80c8ebd366ce44",
+ "sha256:525021896afef44a68148f6ed8a8bf8375553d6066c7f48537657f64823565b9",
+ "sha256:5c3aedecfc1beb988c27c79d52ebefab93b6c3921dbec361167e6559aba2d36d",
+ "sha256:5c8b2769dc31883c44a9cd126560327767f848eb95f99c36c9932f51090bfce9",
+ "sha256:5d7feb0741ebb15204e748f26c9638e6665a5fa93c37a2c73d64f1669b0ddc63",
+ "sha256:5e59d23cd93ada23ec59a96f215139753fbfe3a4d989549bcb390f8c00370b39",
+ "sha256:600e0e9ca042878c7fdf189cf1b028fe2c1418cc9195f6cb9824eb6ed99cb938",
+ "sha256:622463ab81d19ef3e06868b576551587de8e4d518892d1afab71e0fbc1f9cffc",
+ "sha256:624f3951181eb46fc47dea3d221554e98784c823e7069edb5dbd0dc826ac909b",
+ "sha256:639c3735b8ae7f970066930e58cf0ed39a852d417c24acd4a25fc0b3da3c39a6",
+ "sha256:65fd2f5730b1bf7f350c6dc896173d3460d235c4be007af73986d7cd9a2acd23",
+ "sha256:68e44722541983614e37117209a194e8c3ad07838ccb3127d96863c95ec7f1e0",
+ "sha256:6bb6bb41b14c95d4f2702bce9975fda4516f1db48e500102fc4d8119032ff045",
+ "sha256:6c13879c0d2964335491463302a6ca5ad98105fc5db3565499dcb80b1b4bd839",
+ "sha256:6e18a5c15e764e5f3fc569b47872450b4bcea24f2a6354c0a0e95ad21045d5a9",
+ "sha256:6e3f20be9048941c7ffa8fc523ccbd17f82e24df1549d1d1fe9317712d19938e",
+ "sha256:724ca721ecc8a831b319dcd72cfa370cc380db0bf94537f08f7edd0a7d4e1780",
+ "sha256:78b999999039db3cf58f6d230f524f04f75f129ba3d1ca2ed121f8657e575d3d",
+ "sha256:7bbf9b333f1568ef5da42bc96e18bf30fd7f8d54e9ae066d711056add508e415",
+ "sha256:80fd082f5dcc0e94657c144f1b2a3a6479c44ad50be216cf0c244e567f5eae19",
+ "sha256:842289889de515421f3f224ef9c1f1efb199a32d76d8d2ca2706fa8afe749549",
+ "sha256:87255b88756eab4a68ec61837ca754e5d10fa8bc47dc57f75cedfeaec358d54c",
+ "sha256:8873812c164a90a79f65368f8f96817e59e35d0cc02786a5356f0e2abed78040",
+ "sha256:89216ff3dfdde0e4070932e126320a1752c9d9a758d6a32ec54b3b9334991a6a",
+ "sha256:8e7805fda9672c12be2f22ae124dcd7b03928d6c197544fe12174b86553f3196",
+ "sha256:94f206766bf1ea30e1382e4890f763bd1eefddc580e08fec1ccdc20ddd95c827",
+ "sha256:95713e5fc8af84d8edc75b785d2386f653b63d62b16d681687746734b4dfc0be",
+ "sha256:977c393f2e44845ce1b540e19a786e9643221b3323dae190668a98672d43fb23",
+ "sha256:97eb5942c7395a171cbfecc4ef6701fc3c403e762194683772df4c54cfbb2210",
+ "sha256:9daa26ca8e97fae0ce8aa5d80606ef8f7914e9b129b6b5df9104266f764ce436",
+ "sha256:9fdc3ae730541086158d549c97852e2eea6820665d4faf0f41bf99df41bc11ea",
+ "sha256:a69ab657a4e6733133a3dca82768f2f8b884043714e8d2b9ba9f52b6efef5c44",
+ "sha256:a85f0adf63319d6c1ba06fb0dbf997fced64a01179cf17939a6caca662bf92de",
+ "sha256:aac364c758dc87a52e68e349924d7e4ded348dedff553889e4d9f22f74785316",
+ "sha256:ad355e8308493f527d41154e9053b86a5be892b3b359a5c6d5d95cda23601cb2",
+ "sha256:ad73ede24f9083614d6c4ca9a85fe70e33be7bf047ec586ee2363bc7418fe4d7",
+ "sha256:af02ff34059ee9199a3546f123a6ab4c86caf1708c79042caf0820dc290a6d4f",
+ "sha256:afb14052690aa328cc118a8e09f07c651d301a72e44920b887c519b313d892ff",
+ "sha256:b13c478fa413d4b4ee606ec8e11c3b2e52683a640b006bb586b3041c2ca5f606",
+ "sha256:b58430396687ce0f7d9eeb3dd47761ca7d8fda8e9eb92b3077a7a353a75efefa",
+ "sha256:bba5118143373a86f91dadb8df41d9457498226698ebdf8e11cbb54d5b0e802d",
+ "sha256:bfc2a484cad3585e4ba61985a6062a4c2ed5c7925db6d39f1fa267c9d166487f",
+ "sha256:c6dbf422894e1e3c80a177133c0dda260f81428f9de16d61041949f6a2e5c140",
+ "sha256:c8a7517482667fb9f0ff1b2f16fe5829296ed7a655d04d68cd9711a4d8a4e708",
+ "sha256:caa447f2b5356779d914658519c874cf3b7629e99e63391ed519c28c8aea4919",
+ "sha256:d38d2bc06d6415852224fcc9c0bfa834c25431e466dc319f0edd56cca81aa96e",
+ "sha256:d4371de39319d05d3f482f372720b841c841b52f5385bd99c61ed69d55d9ab50",
+ "sha256:d58c166a18f44cc9e2bad03a327dc2d1a3d2e85b847133cfbafd6bfc6719bd79",
+ "sha256:d5c54a6d76e3d741dcc3f2707f8eeb9ba2a791d3adbf18f900219b62942803b1",
+ "sha256:d63076d625babab9db5e7836118bdfa086e60f37d8a174194ae720161eb12394",
+ "sha256:da9e5301f1c2caa2a9a4a303480d79c9ad73560b2e7761de742ab39fe59d9175",
+ "sha256:e10b4d65901da88845516ce9f7f9736f9638d19a1d483b3883dc0182e6e5edba",
+ "sha256:e2985ce8b8c42d00492d0ed79f2bd2b6460d00f2fa671dfde4bf2e02f49bf5c6",
+ "sha256:e2d5d5d798aba9a0e1fede8d853fa899ce2cb930ec0857365f700dffc2c7af6a",
+ "sha256:e34dbd508cb91c54f9c9788923daca129fe5b55c5b4eebe713bf5ed3791280cf",
+ "sha256:e3aa2118a3ece0d25489cbe48498de8a5d580e42e8d9979f65bf47900a15aba1",
+ "sha256:e41fd3b3cac850eaae78232f37325ed7d7436e11c471246b87b2cd294ec94853",
+ "sha256:f28485bdca8617b79d44627f5fb04336897041dfd9fa66d383a49d09d86798bc",
+ "sha256:f2cf4dfaf9163b0728d061bebc1e08631875c51cd30bf47cb9e3293bfbd7dcd5",
+ "sha256:fa9627eba4e82f99ca6d29bc967f09aba446ee2b5a1ea728949ede73d313f5d3",
+ "sha256:fb1c37c71cad991ef4d89c7a634b5ffb4447dbd7ae3ae13e8f5ee7f1775e7ab1",
+ "sha256:fb6a03a678085f64b97f9d4a9ae69376ce91a3a9e9b56a82b1580d8e1d501aff"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.9'",
+ "version": "==3.11.4"
},
"packaging": {
"hashes": [
@@ -710,217 +1008,314 @@
},
"pillow": {
"hashes": [
- "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d",
- "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de",
- "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616",
- "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839",
- "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099",
- "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a",
- "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219",
- "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106",
- "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b",
- "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412",
- "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b",
- "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7",
- "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2",
- "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7",
- "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14",
- "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f",
- "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27",
- "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57",
- "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262",
- "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28",
- "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610",
- "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172",
- "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273",
- "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e",
- "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d",
- "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818",
- "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f",
- "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9",
- "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01",
- "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7",
- "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651",
- "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312",
- "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80",
- "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666",
- "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061",
- "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b",
- "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992",
- "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593",
- "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4",
- "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db",
- "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba",
- "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd",
- "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e",
- "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212",
- "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb",
- "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2",
- "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34",
- "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256",
- "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f",
- "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2",
- "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38",
- "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996",
- "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a",
- "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==10.1.0"
- },
- "pycares": {
- "hashes": [
- "sha256:112a4979c695b1c86f6782163d7dec58d57a3b9510536dcf4826550f9053dd9a",
- "sha256:1168a48a834813aa80f412be2df4abaf630528a58d15c704857448b20b1675c0",
- "sha256:21a5a0468861ec7df7befa69050f952da13db5427ae41ffe4713bc96291d1d95",
- "sha256:229a1675eb33bc9afb1fc463e73ee334950ccc485bc83a43f6ae5839fb4d5fa3",
- "sha256:22c00bf659a9fa44d7b405cf1cd69b68b9d37537899898d8cbe5dffa4016b273",
- "sha256:23aa3993a352491a47fcf17867f61472f32f874df4adcbb486294bd9fbe8abee",
- "sha256:24da119850841d16996713d9c3374ca28a21deee056d609fbbed29065d17e1f6",
- "sha256:2eeec144bcf6a7b6f2d74d6e70cbba7886a84dd373c886f06cb137a07de4954c",
- "sha256:34736a2ffaa9c08ca9c707011a2d7b69074bbf82d645d8138bba771479b2362f",
- "sha256:3aebc73e5ad70464f998f77f2da2063aa617cbd8d3e8174dd7c5b4518f967153",
- "sha256:3eaa6681c0a3e3f3868c77aca14b7760fed35fdfda2fe587e15c701950e7bc69",
- "sha256:4afc2644423f4eef97857a9fd61be9758ce5e336b4b0bd3d591238bb4b8b03e0",
- "sha256:52084961262232ec04bd75f5043aed7e5d8d9695e542ff691dfef0110209f2d4",
- "sha256:56cf3349fa3a2e67ed387a7974c11d233734636fe19facfcda261b411af14d80",
- "sha256:5ed4e04af4012f875b78219d34434a6d08a67175150ac1b79eb70ab585d4ba8c",
- "sha256:64965dc19c578a683ea73487a215a8897276224e004d50eeb21f0bc7a0b63c88",
- "sha256:6ef64649eba56448f65e26546d85c860709844d2fc22ef14d324fe0b27f761a9",
- "sha256:77cf5a2fd5583c670de41a7f4a7b46e5cbabe7180d8029f728571f4d2e864084",
- "sha256:7bddc6adba8f699728f7fc1c9ce8cef359817ad78e2ed52b9502cb5f8dc7f741",
- "sha256:813d661cbe2e37d87da2d16b7110a6860e93ddb11735c6919c8a3545c7b9c8d8",
- "sha256:82bba2ab77eb5addbf9758d514d9bdef3c1bfe7d1649a47bd9a0d55a23ef478b",
- "sha256:8bf2eaa83a5987e48fa63302f0fe7ce3275cfda87b34d40fef9ce703fb3ac002",
- "sha256:8d186dafccdaa3409194c0f94db93c1a5d191145a275f19da6591f9499b8e7b8",
- "sha256:8f64cb58729689d4d0e78f0bfb4c25ce2f851d0274c0273ac751795c04b8798a",
- "sha256:902461a92b6a80fd5041a2ec5235680c7cc35e43615639ec2a40e63fca2dfb51",
- "sha256:917f08f0b5d9324e9a34211e68d27447c552b50ab967044776bbab7e42a553a2",
- "sha256:94d6962db81541eb0396d2f0dfcbb18cdb8c8b251d165efc2d974ae652c547d4",
- "sha256:97892cced5794d721fb4ff8765764aa4ea48fe8b2c3820677505b96b83d4ef47",
- "sha256:9a0303428d013ccf5c51de59c83f9127aba6200adb7fd4be57eddb432a1edd2a",
- "sha256:9dc04c54c6ea615210c1b9e803d0e2d2255f87a3d5d119b6482c8f0dfa15b26b",
- "sha256:a0c5368206057884cde18602580083aeaad9b860e2eac14fd253543158ce1e93",
- "sha256:ad58e284a658a8a6a84af2e0b62f2f961f303cedfe551854d7bd40c3cbb61912",
- "sha256:afb91792f1556f97be7f7acb57dc7756d89c5a87bd8b90363a77dbf9ea653817",
- "sha256:b61579cecf1f4d616e5ea31a6e423a16680ab0d3a24a2ffe7bb1d4ee162477ff",
- "sha256:b7af06968cbf6851566e806bf3e72825b0e6671832a2cbe840be1d2d65350710",
- "sha256:bce8db2fc6f3174bd39b81405210b9b88d7b607d33e56a970c34a0c190da0490",
- "sha256:bfb89ca9e3d0a9b5332deeb666b2ede9d3469107742158f4aeda5ce032d003f4",
- "sha256:c680fef1b502ee680f8f0b95a41af4ec2c234e50e16c0af5bbda31999d3584bd",
- "sha256:c6a8bde63106f162fca736e842a916853cad3c8d9d137e11c9ffa37efa818b02",
- "sha256:cb49d5805cd347c404f928c5ae7c35e86ba0c58ffa701dbe905365e77ce7d641",
- "sha256:ceb12974367b0a68a05d52f4162b29f575d241bd53de155efe632bf2c943c7f6",
- "sha256:d33e2a1120887e89075f7f814ec144f66a6ce06a54f5722ccefc62fbeda83cff",
- "sha256:db24c4e7fea4a052c6e869cbf387dd85d53b9736cfe1ef5d8d568d1ca925e977",
- "sha256:e3a6f7cfdfd11eb5493d6d632e582408c8f3b429f295f8799c584c108b28db6f",
- "sha256:eb66c30eb11e877976b7ead13632082a8621df648c408b8e15cdb91a452dd502",
- "sha256:ed2a38e34bec6f2586435f6ff0bc5fe11d14bebd7ed492cf739a424e81681540",
- "sha256:f36bdc1562142e3695555d2f4ac0cb69af165eddcefa98efc1c79495b533481f",
- "sha256:f47579d508f2f56eddd16ce72045782ad3b1b3b678098699e2b6a1b30733e1c2",
- "sha256:f5f646eec041db6ffdbcaf3e0756fb92018f7af3266138c756bb09d2b5baadec",
- "sha256:fd644505a8cfd7f6584d33a9066d4e3d47700f050ef1490230c962de5dfb28c6",
- "sha256:fff16b09042ba077f7b8aa5868d1d22456f0002574d0ba43462b10a009331677"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==4.4.0"
+ "sha256:0869154a2d0546545cde61d1789a6524319fc1897d9ee31218eae7a60ccc5643",
+ "sha256:09f2d0abef9e4e2f349305a4f8cc784a8a6c2f58a8c4892eea13b10a943bd26e",
+ "sha256:0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e",
+ "sha256:0fd00cac9c03256c8b2ff58f162ebcd2587ad3e1f2e397eab718c47e24d231cc",
+ "sha256:110486b79f2d112cf6add83b28b627e369219388f64ef2f960fef9ebaf54c642",
+ "sha256:1979f4566bb96c1e50a62d9831e2ea2d1211761e5662afc545fa766f996632f6",
+ "sha256:1ac11e8ea4f611c3c0147424eae514028b5e9077dd99ab91e1bd7bc33ff145e1",
+ "sha256:1b1b133e6e16105f524a8dec491e0586d072948ce15c9b914e41cdadd209052b",
+ "sha256:1ee80a59f6ce048ae13cda1abf7fbd2a34ab9ee7d401c46be3ca685d1999a399",
+ "sha256:21f241bdd5080a15bc86d3466a9f6074a9c2c2b314100dd896ac81ee6db2f1ba",
+ "sha256:266cd5f2b63ff316d5a1bba46268e603c9caf5606d44f38c2873c380950576ad",
+ "sha256:26d9f7d2b604cd23aba3e9faf795787456ac25634d82cd060556998e39c6fa47",
+ "sha256:27f95b12453d165099c84f8a8bfdfd46b9e4bda9e0e4b65f0635430027f55739",
+ "sha256:2c54c1a783d6d60595d3514f0efe9b37c8808746a66920315bfd34a938d7994b",
+ "sha256:2fa5f0b6716fc88f11380b88b31fe591a06c6315e955c096c35715788b339e3f",
+ "sha256:32ed80ea8a90ee3e6fa08c21e2e091bba6eda8eccc83dbc34c95169507a91f10",
+ "sha256:3830c769decf88f1289680a59d4f4c46c72573446352e2befec9a8512104fa52",
+ "sha256:38df9b4bfd3db902c9c2bd369bcacaf9d935b2fff73709429d95cc41554f7b3d",
+ "sha256:3adfb466bbc544b926d50fe8f4a4e6abd8c6bffd28a26177594e6e9b2b76572b",
+ "sha256:3e42edad50b6909089750e65c91aa09aaf1e0a71310d383f11321b27c224ed8a",
+ "sha256:4078242472387600b2ce8d93ade8899c12bf33fa89e55ec89fe126e9d6d5d9e9",
+ "sha256:455247ac8a4cfb7b9bc45b7e432d10421aea9fc2e74d285ba4072688a74c2e9d",
+ "sha256:4cc6b3b2efff105c6a1656cfe59da4fdde2cda9af1c5e0b58529b24525d0a098",
+ "sha256:4cf7fed4b4580601c4345ceb5d4cbf5a980d030fd5ad07c4d2ec589f95f09905",
+ "sha256:5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b",
+ "sha256:5269cc1caeedb67e6f7269a42014f381f45e2e7cd42d834ede3c703a1d915fe3",
+ "sha256:53561a4ddc36facb432fae7a9d8afbfaf94795414f5cdc5fc52f28c1dca90371",
+ "sha256:55f818bd74fe2f11d4d7cbc65880a843c4075e0ac7226bc1a23261dbea531953",
+ "sha256:58eea5ebe51504057dd95c5b77d21700b77615ab0243d8152793dc00eb4faf01",
+ "sha256:5d5c411a8eaa2299322b647cd932586b1427367fd3184ffbb8f7a219ea2041ca",
+ "sha256:6846bd2d116ff42cba6b646edf5bf61d37e5cbd256425fa089fee4ff5c07a99e",
+ "sha256:6ace95230bfb7cd79ef66caa064bbe2f2a1e63d93471c3a2e1f1348d9f22d6b7",
+ "sha256:6e51b71417049ad6ab14c49608b4a24d8fb3fe605e5dfabfe523b58064dc3d27",
+ "sha256:71db6b4c1653045dacc1585c1b0d184004f0d7e694c7b34ac165ca70c0838082",
+ "sha256:7438839e9e053ef79f7112c881cef684013855016f928b168b81ed5835f3e75e",
+ "sha256:759de84a33be3b178a64c8ba28ad5c135900359e85fb662bc6e403ad4407791d",
+ "sha256:792a2c0be4dcc18af9d4a2dfd8a11a17d5e25274a1062b0ec1c2d79c76f3e7f8",
+ "sha256:7d87ef5795da03d742bf49439f9ca4d027cde49c82c5371ba52464aee266699a",
+ "sha256:7dfb439562f234f7d57b1ac6bc8fe7f838a4bd49c79230e0f6a1da93e82f1fad",
+ "sha256:7fa22993bac7b77b78cae22bad1e2a987ddf0d9015c63358032f84a53f23cdc3",
+ "sha256:805ebf596939e48dbb2e4922a1d3852cfc25c38160751ce02da93058b48d252a",
+ "sha256:82240051c6ca513c616f7f9da06e871f61bfd7805f566275841af15015b8f98d",
+ "sha256:87d4f8125c9988bfbed67af47dd7a953e2fc7b0cc1e7800ec6d2080d490bb353",
+ "sha256:8d8ca2b210ada074d57fcee40c30446c9562e542fc46aedc19baf758a93532ee",
+ "sha256:8dc232e39d409036af549c86f24aed8273a40ffa459981146829a324e0848b4b",
+ "sha256:90387104ee8400a7b4598253b4c406f8958f59fcf983a6cea2b50d59f7d63d0b",
+ "sha256:905b0365b210c73afb0ebe9101a32572152dfd1c144c7e28968a331b9217b94a",
+ "sha256:99353a06902c2e43b43e8ff74ee65a7d90307d82370604746738a1e0661ccca7",
+ "sha256:99a7f72fb6249302aa62245680754862a44179b545ded638cf1fef59befb57ef",
+ "sha256:9f0b04c6b8584c2c193babcccc908b38ed29524b29dd464bc8801bf10d746a3a",
+ "sha256:9fe611163f6303d1619bbcb653540a4d60f9e55e622d60a3108be0d5b441017a",
+ "sha256:a3475b96f5908b3b16c47533daaa87380c491357d197564e0ba34ae75c0f3257",
+ "sha256:a6597ff2b61d121172f5844b53f21467f7082f5fb385a9a29c01414463f93b07",
+ "sha256:a7921c5a6d31b3d756ec980f2f47c0cfdbce0fc48c22a39347a895f41f4a6ea4",
+ "sha256:aa5129de4e174daccbc59d0a3b6d20eaf24417d59851c07ebb37aeb02947987c",
+ "sha256:aeaefa96c768fc66818730b952a862235d68825c178f1b3ffd4efd7ad2edcb7c",
+ "sha256:afbefa430092f71a9593a99ab6a4e7538bc9eabbf7bf94f91510d3503943edc4",
+ "sha256:aff9e4d82d082ff9513bdd6acd4f5bd359f5b2c870907d2b0a9c5e10d40c88fe",
+ "sha256:b22bd8c974942477156be55a768f7aa37c46904c175be4e158b6a86e3a6b7ca8",
+ "sha256:b290fd8aa38422444d4b50d579de197557f182ef1068b75f5aa8558638b8d0a5",
+ "sha256:b2e4b27a6e15b04832fe9bf292b94b5ca156016bbc1ea9c2c20098a0320d6cf6",
+ "sha256:b583dc9070312190192631373c6c8ed277254aa6e6084b74bdd0a6d3b221608e",
+ "sha256:b87843e225e74576437fd5b6a4c2205d422754f84a06942cfaf1dc32243e45a8",
+ "sha256:bc91a56697869546d1b8f0a3ff35224557ae7f881050e99f615e0119bf934b4e",
+ "sha256:bd87e140e45399c818fac4247880b9ce719e4783d767e030a883a970be632275",
+ "sha256:bde737cff1a975b70652b62d626f7785e0480918dece11e8fef3c0cf057351c3",
+ "sha256:bdee52571a343d721fb2eb3b090a82d959ff37fc631e3f70422e0c2e029f3e76",
+ "sha256:bee2a6db3a7242ea309aa7ee8e2780726fed67ff4e5b40169f2c940e7eb09227",
+ "sha256:beeae3f27f62308f1ddbcfb0690bf44b10732f2ef43758f169d5e9303165d3f9",
+ "sha256:c50f36a62a22d350c96e49ad02d0da41dbd17ddc2e29750dbdba4323f85eb4a5",
+ "sha256:c607c90ba67533e1b2355b821fef6764d1dd2cbe26b8c1005ae84f7aea25ff79",
+ "sha256:c7b2a63fd6d5246349f3d3f37b14430d73ee7e8173154461785e43036ffa96ca",
+ "sha256:c828a1ae702fc712978bda0320ba1b9893d99be0badf2647f693cc01cf0f04fa",
+ "sha256:c85de1136429c524e55cfa4e033b4a7940ac5c8ee4d9401cc2d1bf48154bbc7b",
+ "sha256:c98fa880d695de164b4135a52fd2e9cd7b7c90a9d8ac5e9e443a24a95ef9248e",
+ "sha256:cae81479f77420d217def5f54b5b9d279804d17e982e0f2fa19b1d1e14ab5197",
+ "sha256:d034140032870024e6b9892c692fe2968493790dd57208b2c37e3fb35f6df3ab",
+ "sha256:d120c38a42c234dc9a8c5de7ceaaf899cf33561956acb4941653f8bdc657aa79",
+ "sha256:d4827615da15cd59784ce39d3388275ec093ae3ee8d7f0c089b76fa87af756c2",
+ "sha256:d49e2314c373f4c2b39446fb1a45ed333c850e09d0c59ac79b72eb3b95397363",
+ "sha256:d52610d51e265a51518692045e372a4c363056130d922a7351429ac9f27e70b0",
+ "sha256:d64317d2587c70324b79861babb9c09f71fbb780bad212018874b2c013d8600e",
+ "sha256:d77153e14b709fd8b8af6f66a3afbb9ed6e9fc5ccf0b6b7e1ced7b036a228782",
+ "sha256:d7e091d464ac59d2c7ad8e7e08105eaf9dafbc3883fd7265ffccc2baad6ac925",
+ "sha256:dd333073e0cacdc3089525c7df7d39b211bcdf31fc2824e49d01c6b6187b07d0",
+ "sha256:e5d8efac84c9afcb40914ab49ba063d94f5dbdf5066db4482c66a992f47a3a3b",
+ "sha256:f135c702ac42262573fe9714dfe99c944b4ba307af5eb507abef1667e2cbbced",
+ "sha256:f13711b1a5ba512d647a0e4ba79280d3a9a045aaf7e0cc6fbe96b91d4cdf6b0c",
+ "sha256:f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344",
+ "sha256:fa3ed2a29a9e9d2d488b4da81dcb54720ac3104a20bf0bd273f1e4648aff5af9",
+ "sha256:fb3096c30df99fd01c7bf8e544f392103d0795b9f98ba71a8054bcbf56b255f1"
+ ],
+ "markers": "python_version >= '3.10'",
+ "version": "==12.0.0"
+ },
+ "propcache": {
+ "hashes": [
+ "sha256:0002004213ee1f36cfb3f9a42b5066100c44276b9b72b4e1504cddd3d692e86e",
+ "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4",
+ "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be",
+ "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3",
+ "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85",
+ "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b",
+ "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367",
+ "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf",
+ "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393",
+ "sha256:182b51b421f0501952d938dc0b0eb45246a5b5153c50d42b495ad5fb7517c888",
+ "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37",
+ "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8",
+ "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60",
+ "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1",
+ "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4",
+ "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717",
+ "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7",
+ "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc",
+ "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe",
+ "sha256:357f5bb5c377a82e105e44bd3d52ba22b616f7b9773714bff93573988ef0a5fb",
+ "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75",
+ "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6",
+ "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e",
+ "sha256:3d233076ccf9e450c8b3bc6720af226b898ef5d051a2d145f7d765e6e9f9bcff",
+ "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566",
+ "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12",
+ "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367",
+ "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874",
+ "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf",
+ "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566",
+ "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a",
+ "sha256:4b536b39c5199b96fc6245eb5fb796c497381d3942f169e44e8e392b29c9ebcc",
+ "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a",
+ "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1",
+ "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6",
+ "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61",
+ "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726",
+ "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49",
+ "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44",
+ "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af",
+ "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa",
+ "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153",
+ "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc",
+ "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5",
+ "sha256:5fd37c406dd6dc85aa743e214cef35dc54bbdd1419baac4f6ae5e5b1a2976938",
+ "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf",
+ "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925",
+ "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8",
+ "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c",
+ "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85",
+ "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e",
+ "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0",
+ "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1",
+ "sha256:71b749281b816793678ae7f3d0d84bd36e694953822eaad408d682efc5ca18e0",
+ "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992",
+ "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db",
+ "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f",
+ "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d",
+ "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1",
+ "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e",
+ "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900",
+ "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89",
+ "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a",
+ "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b",
+ "sha256:948dab269721ae9a87fd16c514a0a2c2a1bdb23a9a61b969b0f9d9ee2968546f",
+ "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f",
+ "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1",
+ "sha256:99d43339c83aaf4d32bda60928231848eee470c6bda8d02599cc4cebe872d183",
+ "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66",
+ "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21",
+ "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db",
+ "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded",
+ "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb",
+ "sha256:a129e76735bc792794d5177069691c3217898b9f5cee2b2661471e52ffe13f19",
+ "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0",
+ "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165",
+ "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778",
+ "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455",
+ "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f",
+ "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b",
+ "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237",
+ "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81",
+ "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859",
+ "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c",
+ "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835",
+ "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393",
+ "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5",
+ "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641",
+ "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144",
+ "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74",
+ "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db",
+ "sha256:cbc3b6dfc728105b2a57c06791eb07a94229202ea75c59db644d7d496b698cac",
+ "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403",
+ "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9",
+ "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f",
+ "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311",
+ "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581",
+ "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36",
+ "sha256:daede9cd44e0f8bdd9e6cc9a607fc81feb80fae7a5fc6cecaff0e0bb32e42d00",
+ "sha256:db65d2af507bbfbdcedb254a11149f894169d90488dd3e7190f7cdcb2d6cd57a",
+ "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f",
+ "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2",
+ "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7",
+ "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239",
+ "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757",
+ "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72",
+ "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9",
+ "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4",
+ "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24",
+ "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207",
+ "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e",
+ "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1",
+ "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d",
+ "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37",
+ "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c",
+ "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e",
+ "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570",
+ "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af",
+ "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f",
+ "sha256:fd2dbc472da1f772a4dae4fa24be938a6c544671a912e30529984dd80400cd88",
+ "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48",
+ "sha256:fe49d0a85038f36ba9e3ffafa1103e61170b28e95b16622e11be0a0ea07c6781"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==0.4.1"
},
"pycparser": {
"hashes": [
- "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9",
- "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"
+ "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2",
+ "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"
],
- "version": "==2.21"
+ "markers": "python_version >= '3.8'",
+ "version": "==2.23"
},
"pymongo": {
- "extras": [
- "srv"
- ],
- "hashes": [
- "sha256:014e7049dd019a6663747ca7dae328943e14f7261f7c1381045dfc26a04fa330",
- "sha256:055f5c266e2767a88bb585d01137d9c7f778b0195d3dbf4a487ef0638be9b651",
- "sha256:05c30fd35cc97f14f354916b45feea535d59060ef867446b5c3c7f9b609dd5dc",
- "sha256:0634994b026336195778e5693583c060418d4ab453eff21530422690a97e1ee8",
- "sha256:09c7de516b08c57647176b9fc21d929d628e35bcebc7422220c89ae40b62126a",
- "sha256:107a234dc55affc5802acb3b6d83cbb8c87355b38a9457fcd8806bdeb8bce161",
- "sha256:10a379fb60f1b2406ae57b8899bacfe20567918c8e9d2d545e1b93628fcf2050",
- "sha256:128b1485753106c54af481789cdfea12b90a228afca0b11fb3828309a907e10e",
- "sha256:1394c4737b325166a65ae7c145af1ebdb9fb153ebedd37cf91d676313e4a67b8",
- "sha256:1c63e3a2e8fb815c4b1f738c284a4579897e37c3cfd95fdb199229a1ccfb638a",
- "sha256:1e4ed21029d80c4f62605ab16398fe1ce093fff4b5f22d114055e7d9fbc4adb0",
- "sha256:1ec71ac633b126c0775ed4604ca8f56c3540f5c21a1220639f299e7a544b55f9",
- "sha256:21812453354b151200034750cd30b0140e82ec2a01fd4357390f67714a1bfbde",
- "sha256:256c503a75bd71cf7fb9ebf889e7e222d49c6036a48aad5a619f98a0adf0e0d7",
- "sha256:2703a9f8f5767986b4f51c259ff452cc837c5a83c8ed5f5361f6e49933743b2f",
- "sha256:288c21ab9531b037f7efa4e467b33176bc73a0c27223c141b822ab4a0e66ff2a",
- "sha256:2972dd1f1285866aba027eff2f4a2bbf8aa98563c2ced14cb34ee5602b36afdf",
- "sha256:2973f113e079fb98515722cd728e1820282721ec9fd52830e4b73cabdbf1eb28",
- "sha256:2ca0ba501898b2ec31e6c3acf90c31910944f01d454ad8e489213a156ccf1bda",
- "sha256:2d2be5c9c3488fa8a70f83ed925940f488eac2837a996708d98a0e54a861f212",
- "sha256:2f8c04277d879146eacda920476e93d520eff8bec6c022ac108cfa6280d84348",
- "sha256:325701ae7b56daa5b0692305b7cb505ca50f80a1288abb32ff420a8a209b01ca",
- "sha256:3729b8db02063da50eeb3db88a27670d85953afb9a7f14c213ac9e3dca93034b",
- "sha256:3919708594b86d0f5cdc713eb6fccd3f9b9532af09ea7a5d843c933825ef56c4",
- "sha256:39a1cd5d383b37285641d5a7a86be85274466ae336a61b51117155936529f9b3",
- "sha256:3ec6c20385c5a58e16b1ea60c5e4993ea060540671d7d12664f385f2fb32fe79",
- "sha256:47aa128be2e66abd9d1a9b0437c62499d812d291f17b55185cb4aa33a5f710a4",
- "sha256:49f2af6cf82509b15093ce3569229e0d53c90ad8ae2eef940652d4cf1f81e045",
- "sha256:4a0269811661ba93c472c8a60ea82640e838c2eb148d252720a09b5123f2c2fe",
- "sha256:518c90bdd6e842c446d01a766b9136fec5ec6cc94f3b8c3f8b4a332786ee6b64",
- "sha256:5717a308a703dda2886a5796a07489c698b442f5e409cf7dc2ac93de8d61d764",
- "sha256:5802acc012bbb4bce4dff92973dff76482f30ef35dd4cb8ab5b0e06aa8f08c80",
- "sha256:5e63146dbdb1eac207464f6e0cfcdb640c9c5ff0f57b754fa96fe252314a1dc6",
- "sha256:6695d7136a435c1305b261a9ddb9b3ecec9863e05aab3935b96038145fd3a977",
- "sha256:680fa0fc719e1a3dcb81130858368f51d83667d431924d0bcf249644bce8f303",
- "sha256:6b18276f14b4b6d92e707ab6db19b938e112bd2f1dc3f9f1a628df58e4fd3f0d",
- "sha256:6bafea6061d63059d8bc2ffc545e2f049221c8a4457d236c5cd6a66678673eab",
- "sha256:6d6a1b1361f118e7fefa17ae3114e77f10ee1b228b20d50c47c9f351346180c8",
- "sha256:747c84f4e690fbe6999c90ac97246c95d31460d890510e4a3fa61b7d2b87aa34",
- "sha256:79f41576b3022c2fe9780ae3e44202b2438128a25284a8ddfa038f0785d87019",
- "sha256:7b0e6361754ac596cd16bfc6ed49f69ffcd9b60b7bc4bcd3ea65c6a83475e4ff",
- "sha256:7e3b0127b260d4abae7b62203c4c7ef0874c901b55155692353db19de4b18bc4",
- "sha256:7fc2bb8a74dcfcdd32f89528e38dcbf70a3a6594963d60dc9595e3b35b66e414",
- "sha256:806e094e9e85d8badc978af8c95b69c556077f11844655cb8cd2d1758769e521",
- "sha256:81dd1308bd5630d2bb5980f00aa163b986b133f1e9ed66c66ce2a5bc3572e891",
- "sha256:82e620842e12e8cb4050d2643a81c8149361cd82c0a920fa5a15dc4ca8a4000f",
- "sha256:85f2cdc400ee87f5952ebf2a117488f2525a3fb2e23863a8efe3e4ee9e54e4d1",
- "sha256:8ab6bcc8e424e07c1d4ba6df96f7fb963bcb48f590b9456de9ebd03b88084fe8",
- "sha256:8adf014f2779992eba3b513e060d06f075f0ab2fb3ad956f413a102312f65cdf",
- "sha256:9b0f98481ad5dc4cb430a60bbb8869f05505283b9ae1c62bdb65eb5e020ee8e3",
- "sha256:9bea9138b0fc6e2218147e9c6ce1ff76ff8e29dc00bb1b64842bd1ca107aee9f",
- "sha256:a09bfb51953930e7e838972ddf646c5d5f984992a66d79da6ba7f6a8d8a890cd",
- "sha256:a0be99b599da95b7a90a918dd927b20c434bea5e1c9b3efc6a3c6cd67c23f813",
- "sha256:a49aca4d961823b2846b739380c847e8964ff7ae0f0a683992b9d926054f0d6d",
- "sha256:a4dc1319d0c162919ee7f4ee6face076becae2abbd351cc14f1fe70af5fb20d9",
- "sha256:a8273e1abbcff1d7d29cbbb1ea7e57d38be72f1af3c597c854168508b91516c2",
- "sha256:a8f7f9feecae53fa18d6a3ea7c75f9e9a1d4d20e5c3f9ce3fba83f07bcc4eee2",
- "sha256:ad4f66fbb893b55f96f03020e67dcab49ffde0177c6565ccf9dec4fdf974eb61",
- "sha256:af425f323fce1b07755edd783581e7283557296946212f5b1a934441718e7528",
- "sha256:b14dd73f595199f4275bed4fb509277470d9b9059310537e3b3daba12b30c157",
- "sha256:b4ad70d7cac4ca0c7b31444a0148bd3af01a2662fa12b1ad6f57cd4a04e21766",
- "sha256:b80a4ee19b3442c57c38afa978adca546521a8822d663310b63ae2a7d7b13f3a",
- "sha256:ba51129fcc510824b6ca6e2ce1c27e3e4d048b6e35d3ae6f7e517bed1b8b25ce",
- "sha256:c011bd5ad03cc096f99ffcfdd18a1817354132c1331bed7a837a25226659845f",
- "sha256:cc94f9fea17a5af8cf1a343597711a26b0117c0b812550d99934acb89d526ed2",
- "sha256:ccd785fafa1c931deff6a7116e9a0d402d59fabe51644b0d0c268295ff847b25",
- "sha256:d16a534da0e39785687b7295e2fcf9a339f4a20689024983d11afaa4657f8507",
- "sha256:d3077a31633beef77d057c6523f5de7271ddef7bde5e019285b00c0cc9cac1e3",
- "sha256:d603edea1ff7408638b2504905c032193b7dcee7af269802dbb35bc8c3310ed5",
- "sha256:db082f728160369d9a6ed2e722438291558fc15ce06d0a7d696a8dad735c236b",
- "sha256:ddef295aaf80cefb0c1606f1995899efcb17edc6b327eb6589e234e614b87756",
- "sha256:e16ade71c93f6814d095d25cd6d28a90d63511ea396bd96e9ffcb886b278baaa",
- "sha256:e3db7d833a7c38c317dc95b54e27f1d27012e031b45a7c24e360b53197d5f6e7",
- "sha256:e5e193f89f4f8c1fe273f9a6e6df915092c9f2af6db2d1afb8bd53855025c11f",
- "sha256:eb438a8bf6b695bf50d57e6a059ff09652a07968b2041178b3744ea785fcef9b",
- "sha256:ebf02c32afa6b67e5861a27183dd98ed88419a94a2ab843cc145fb0bafcc5b28",
- "sha256:ecd9e1fa97aa11bf67472220285775fa15e896da108f425e55d23d7540a712ce",
- "sha256:ef67fedd863ffffd4adfd46d9d992b0f929c7f61a8307366d664d93517f2c78e",
- "sha256:f28ae33dc5a0b9cee06e95fd420e42155d83271ab75964baf747ce959cac5f52",
- "sha256:fb1c56d891f9e34303c451998ef62ba52659648bb0d75b03c5e4ac223a3342c2",
- "sha256:fe03bf25fae4b95d8afe40004a321df644400fdcba4c8e5e1a19c1085b740888"
+ "hashes": [
+ "sha256:07bcc36d11252f24fe671e7e64044d39a13d997b0502c6401161f28cc144f584",
+ "sha256:09440e78dff397b2f34a624f445ac8eb44c9756a2688b85b3bf344d351d198e1",
+ "sha256:1246a82fa6dd73ac2c63aa7e463752d5d1ca91e0c7a23396b78f21273befd3a7",
+ "sha256:17d13458baf4a6a9f2e787d95adf8ec50d412accb9926a044bd1c41029c323b2",
+ "sha256:17fc94d1e067556b122eeb09e25c003268e8c0ea1f2f78e745b33bb59a1209c4",
+ "sha256:1f681722c9f27e86c49c2e8a838e61b6ecf2285945fd1798bd01458134257834",
+ "sha256:21c0a95a4db72562fd0805e2f76496bf432ba2e27a5651f4b9c670466260c258",
+ "sha256:292fd5a3f045751a823a54cdea75809b2216a62cc5f74a1a96b337db613d46a8",
+ "sha256:2c96dde79bdccd167b930a709875b0cd4321ac32641a490aebfa10bdcd0aa99b",
+ "sha256:2f3d66f7c495efc3cfffa611b36075efe86da1860a7df75522a6fe499ee10383",
+ "sha256:2fd3b99520f2bb013960ac29dece1b43f2f1b6d94351ca33ba1b1211ecf79a09",
+ "sha256:300eaf83ad053e51966be1839324341b08eaf880d3dc63ada7942d5912e09c49",
+ "sha256:3561fa96c3123275ec5ccf919e595547e100c412ec0894e954aa0da93ecfdb9e",
+ "sha256:390c4954c774eda280898e73aea36482bf20cba3ecb958dbb86d6a68b9ecdd68",
+ "sha256:39a13d8f7141294404ce46dfbabb2f2d17e9b1192456651ae831fa351f86fbeb",
+ "sha256:446417a34ff6c2411ce3809e17ce9a67269c9f1cb4966b01e49e0c590cc3c6b3",
+ "sha256:45aebbd369ca79b7c46eaea5b04d2e4afca4eda117b68965a07a9da05d774e4d",
+ "sha256:47ffb068e16ae5e43580d5c4e3b9437f05414ea80c32a1e5cac44a835859c259",
+ "sha256:482ca9b775747562ce1589df10c97a0e62a604ce5addf933e5819dd967c5e23c",
+ "sha256:49fd6e158cf75771b2685a8a221a40ab96010ae34dd116abd06371dc6c38ab60",
+ "sha256:4a0a054e9937ec8fdb465835509b176f6b032851c8648f6a5d1b19932d0eacd6",
+ "sha256:52f40c4b8c00bc53d4e357fe0de13d031c4cddb5d201e1a027db437e8d2887f8",
+ "sha256:58d0f4123855f05c0649f9b8ee083acc5b26e7f4afde137cd7b8dc03e9107ff3",
+ "sha256:5bf879a6ed70264574d4d8fb5a467c2a64dc76ecd72c0cb467c4464f849c8c77",
+ "sha256:5c78237e878e0296130e398151b0d4aa6c9eaf82e38fb6e0aaae2029bc7ef0ce",
+ "sha256:5c85a4c72b7965033f95c94c42dac27d886c01dbc23fe337ccb14f052a0ccc29",
+ "sha256:5f6feb678f26171f2a6b2cbb340949889154c7067972bd4cc129b62161474f08",
+ "sha256:6a054d282dd922ac400b6f47ea3ef58d8b940968d76d855da831dc739b7a04de",
+ "sha256:71413cd8f091ae25b1fec3af7c2e531cf9bdb88ce4079470e64835f6a664282a",
+ "sha256:76a8d4de8dceb69f6e06736198ff6f7e1149515ef946f192ff2594d2cc98fc53",
+ "sha256:77353978be9fc9e5fe56369682efed0aac5f92a2a1570704d62b62a3c9e1a24f",
+ "sha256:7a981271347623b5319932796690c2d301668ac3a1965974ac9f5c3b8a22cea5",
+ "sha256:7c0fd3de3a12ff0a8113a3f64cedb01f87397ab8eaaffa88d7f18ca66cd39385",
+ "sha256:7dd2a49f088890ca08930bbf96121443b48e26b02b84ba0a3e1ae2bf2c5a9b48",
+ "sha256:82a490f1ade4ec6a72068e3676b04c126e3043e69b38ec474a87c6444cf79098",
+ "sha256:86b1b5b63f4355adffc329733733a9b71fdad88f37a9dc41e163aed2130f9abc",
+ "sha256:89e45d7fa987f4e246cdf43ff001e3f911f73eb19ba9dabc2a6d80df5c97883b",
+ "sha256:8bd6dd736f5d07a825caf52c38916d5452edc0fac7aee43ec67aba6f61c2dbb7",
+ "sha256:8d4b01a48369ea6d5bc83fea535f56279f806aa3e4991189f0477696dd736289",
+ "sha256:90ad56bd1d769d2f44af74f0fd0c276512361644a3c636350447994412cbc9a1",
+ "sha256:9483521c03f6017336f54445652ead3145154e8d3ea06418e52cea57fee43292",
+ "sha256:959ef69c5e687b6b749fbf2140c7062abdb4804df013ae0507caabf30cba6875",
+ "sha256:97f9babdb98c31676f97d468f7fe2dc49b8a66fb6900effddc4904c1450196c8",
+ "sha256:982107c667921e896292f4be09c057e2f1a40c645c9bfc724af5dd5fb8398094",
+ "sha256:9897a837677e3814873d0572f7e5d53c23ce18e274f3b5b87f05fb6eea22615b",
+ "sha256:9b03db2fe37c950aff94b29ded5c349b23729bccd90a0a5907bbf807d8c77298",
+ "sha256:9bc9f99e7702fdb0dcc3ff1dd490adc5d20b3941ad41e58f887d4998b9922a14",
+ "sha256:9df2db6bd91b07400879b6ec89827004c0c2b55fc606bb62db93cafb7677c340",
+ "sha256:a47a3218f7900f65bf0f36fcd1f2485af4945757360e7e143525db9d715d2010",
+ "sha256:b33d59bf6fa1ca1d7d96d4fccff51e41312358194190d53ef70a84c070f5287e",
+ "sha256:b3a0ec660d61efb91c16a5962ec937011fe3572c4338216831f102e53d294e5c",
+ "sha256:b63bac343b79bd209e830aac1f5d9d552ff415f23a924d3e51abbe3041265436",
+ "sha256:bd0497c564b0ae34fb816464ffc09986dd9ca29e2772a0f7af989e472fecc2ad",
+ "sha256:c4fdd8e6eab8ff77c1c8041792b5f760d48508623cd10b50d5639e73f1eec049",
+ "sha256:c57dad9f289d72af1d7c47a444c4d9fa401f951cedbbcc54c7dd0c2107d6d786",
+ "sha256:c7eb497519f42ac89c30919a51f80e68a070cfc2f3b0543cac74833cd45a6b9c",
+ "sha256:cfa4a0a0f024a0336640e1201994e780a17bda5e6a7c0b4d23841eb9152e868b",
+ "sha256:d09d895c7f08bcbed4d2e96a00e52e9e545ae5a37b32d2dc10099b205a21fc6d",
+ "sha256:d2d4ca446348d850ac4a5c3dc603485640ae2e7805dbb90765c3ba7d79129b37",
+ "sha256:d66da207ccb0d68c5792eaaac984a0d9c6c8ec609c6bcfa11193a35200dc5992",
+ "sha256:dc583a1130e2516440b93bb2ecb55cfdac6d5373615ae472a9d1f26801f58749",
+ "sha256:dcff15b9157c16bc796765d4d3d151df669322acfb0357e4c3ccd056153f0ff4",
+ "sha256:de3bc878c3be54ae41c2cabc9e9407549ed4fec41f4e279c04e840dddd7c630c",
+ "sha256:e7cde58ef6470c0da922b65e885fb1ffe04deef81e526bd5dea429290fa358ca",
+ "sha256:e84dec392cf5f72d365e0aac73f627b0a3170193ebb038c3f7e7df11b7983ee7",
+ "sha256:f6b0513e5765fdde39f36e6a29a36c67071122b5efa748940ae51075beb5e4bc",
+ "sha256:fae552767d8e5153ed498f1bca92d905d0d46311d831eefb0f06de38f7695c95",
+ "sha256:fb384623ece34db78d445dd578a52d28b74e8319f4d9535fbaff79d0eae82b3d",
+ "sha256:fe4bcb8acfb288e238190397d4a699aeb4adb70e8545a6f4e44f99d4e8096ab1",
+ "sha256:ff99864085d2c7f4bb672c7167680ceb7d273e9a93c1a8074c986a36dbb71cc6",
+ "sha256:ffe217d2502f3fba4e2b0dc015ce3b34f157b66dfe96835aa64432e909dd0d95"
],
- "markers": "python_version >= '3.7'",
- "version": "==4.6.0"
+ "index": "pypi",
+ "markers": "python_version >= '3.9'",
+ "version": "==4.15.3"
},
"python-dateutil": {
"hashes": [
@@ -928,7 +1323,7 @@
"sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
],
"index": "pypi",
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"version": "==2.8.2"
},
"python-dotenv": {
@@ -949,66 +1344,102 @@
"markers": "python_version >= '3.7'",
"version": "==2.31.0"
},
+ "setuptools": {
+ "hashes": [
+ "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922",
+ "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.9'",
+ "version": "==80.9.0"
+ },
"six": {
"hashes": [
- "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
- "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
+ "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==1.16.0"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
+ "version": "==1.17.0"
},
"tinycss2": {
"hashes": [
- "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847",
- "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"
+ "sha256:3415ba0f5839c062696996998176c4a3751d18b7edaaeeb658c9ce21ec150661",
+ "sha256:d339d2b616ba90ccce58da8495a78f46e55d4d25f9fd71dfd526f07e7d53f957"
],
- "markers": "python_version >= '3.7'",
- "version": "==1.2.1"
+ "markers": "python_version >= '3.10'",
+ "version": "==1.5.1"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466",
+ "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.9'",
+ "version": "==4.15.0"
},
"urllib3": {
"hashes": [
- "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3",
- "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"
+ "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760",
+ "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"
],
- "markers": "python_version >= '3.8'",
- "version": "==2.1.0"
+ "markers": "python_version >= '3.9'",
+ "version": "==2.5.0"
},
"uvloop": {
"hashes": [
- "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd",
- "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec",
- "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b",
- "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc",
- "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797",
- "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5",
- "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2",
- "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d",
- "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be",
- "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd",
- "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12",
- "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17",
- "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef",
- "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24",
- "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428",
- "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1",
- "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849",
- "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593",
- "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd",
- "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67",
- "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6",
- "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3",
- "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd",
- "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8",
- "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7",
- "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533",
- "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957",
- "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650",
- "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e",
- "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7",
- "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"
+ "sha256:017bd46f9e7b78e81606329d07141d3da446f8798c6baeec124260e22c262772",
+ "sha256:0530a5fbad9c9e4ee3f2b33b148c6a64d47bbad8000ea63704fa8260f4cf728e",
+ "sha256:05e4b5f86e621cf3927631789999e697e58f0d2d32675b67d9ca9eb0bca55743",
+ "sha256:0ae676de143db2b2f60a9696d7eca5bb9d0dd6cc3ac3dad59a8ae7e95f9e1b54",
+ "sha256:1489cf791aa7b6e8c8be1c5a080bae3a672791fcb4e9e12249b05862a2ca9cec",
+ "sha256:17d4e97258b0172dfa107b89aa1eeba3016f4b1974ce85ca3ef6a66b35cbf659",
+ "sha256:1cdf5192ab3e674ca26da2eada35b288d2fa49fdd0f357a19f0e7c4e7d5077c8",
+ "sha256:1f38ec5e3f18c8a10ded09742f7fb8de0108796eb673f30ce7762ce1b8550cad",
+ "sha256:286322a90bea1f9422a470d5d2ad82d38080be0a29c4dd9b3e6384320a4d11e7",
+ "sha256:297c27d8003520596236bdb2335e6b3f649480bd09e00d1e3a99144b691d2a35",
+ "sha256:37554f70528f60cad66945b885eb01f1bb514f132d92b6eeed1c90fd54ed6289",
+ "sha256:3879b88423ec7e97cd4eba2a443aa26ed4e59b45e6b76aabf13fe2f27023a142",
+ "sha256:3b7f102bf3cb1995cfeaee9321105e8f5da76fdb104cdad8986f85461a1b7b77",
+ "sha256:40631b049d5972c6755b06d0bfe8233b1bd9a8a6392d9d1c45c10b6f9e9b2733",
+ "sha256:481c990a7abe2c6f4fc3d98781cc9426ebd7f03a9aaa7eb03d3bfc68ac2a46bd",
+ "sha256:4a968a72422a097b09042d5fa2c5c590251ad484acf910a651b4b620acd7f193",
+ "sha256:4baa86acedf1d62115c1dc6ad1e17134476688f08c6efd8a2ab076e815665c74",
+ "sha256:512fec6815e2dd45161054592441ef76c830eddaad55c8aa30952e6fe1ed07c0",
+ "sha256:51eb9bd88391483410daad430813d982010f9c9c89512321f5b60e2cddbdddd6",
+ "sha256:535cc37b3a04f6cd2c1ef65fa1d370c9a35b6695df735fcff5427323f2cd5473",
+ "sha256:53c85520781d84a4b8b230e24a5af5b0778efdb39142b424990ff1ef7c48ba21",
+ "sha256:55502bc2c653ed2e9692e8c55cb95b397d33f9f2911e929dc97c4d6b26d04242",
+ "sha256:561577354eb94200d75aca23fbde86ee11be36b00e52a4eaf8f50fb0c86b7705",
+ "sha256:56a2d1fae65fd82197cb8c53c367310b3eabe1bbb9fb5a04d28e3e3520e4f702",
+ "sha256:57df59d8b48feb0e613d9b1f5e57b7532e97cbaf0d61f7aa9aa32221e84bc4b6",
+ "sha256:6c84bae345b9147082b17371e3dd5d42775bddce91f885499017f4607fdaf39f",
+ "sha256:6cde23eeda1a25c75b2e07d39970f3374105d5eafbaab2a4482be82f272d5a5e",
+ "sha256:6e2ea3d6190a2968f4a14a23019d3b16870dd2190cd69c8180f7c632d21de68d",
+ "sha256:700e674a166ca5778255e0e1dc4e9d79ab2acc57b9171b79e65feba7184b3370",
+ "sha256:7b5b1ac819a3f946d3b2ee07f09149578ae76066d70b44df3fa990add49a82e4",
+ "sha256:7cd375a12b71d33d46af85a3343b35d98e8116134ba404bd657b3b1d15988792",
+ "sha256:80eee091fe128e425177fbd82f8635769e2f32ec9daf6468286ec57ec0313efa",
+ "sha256:93f617675b2d03af4e72a5333ef89450dfaa5321303ede6e67ba9c9d26878079",
+ "sha256:a592b043a47ad17911add5fbd087c76716d7c9ccc1d64ec9249ceafd735f03c2",
+ "sha256:ac33ed96229b7790eb729702751c0e93ac5bc3bcf52ae9eccbff30da09194b86",
+ "sha256:b31dc2fccbd42adc73bc4e7cdbae4fc5086cf378979e53ca5d0301838c5682c6",
+ "sha256:b45649628d816c030dba3c80f8e2689bab1c89518ed10d426036cdc47874dfc4",
+ "sha256:b76324e2dc033a0b2f435f33eb88ff9913c156ef78e153fb210e03c13da746b3",
+ "sha256:b91328c72635f6f9e0282e4a57da7470c7350ab1c9f48546c0f2866205349d21",
+ "sha256:badb4d8e58ee08dad957002027830d5c3b06aea446a6a3744483c2b3b745345c",
+ "sha256:bc5ef13bbc10b5335792360623cc378d52d7e62c2de64660616478c32cd0598e",
+ "sha256:c1955d5a1dd43198244d47664a5858082a3239766a839b2102a269aaff7a4e25",
+ "sha256:c3e5c6727a57cb6558592a95019e504f605d1c54eb86463ee9f7a2dbd411c820",
+ "sha256:c60ebcd36f7b240b30788554b6f0782454826a0ed765d8430652621b5de674b9",
+ "sha256:daf620c2995d193449393d6c62131b3fbd40a63bf7b307a1527856ace637fe88",
+ "sha256:e047cc068570bac9866237739607d1313b9253c3051ad84738cbb095be0537b2",
+ "sha256:ea721dd3203b809039fcc2983f14608dae82b212288b346e0bfe46ec2fab0b7c",
+ "sha256:ef6f0d4cc8a9fa1f6a910230cd53545d9a14479311e87e3cb225495952eb672c",
+ "sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42"
],
"markers": "sys_platform != 'win32'",
- "version": "==0.19.0"
+ "version": "==0.22.1"
},
"webencodings": {
"hashes": [
@@ -1019,118 +1450,263 @@
},
"yarl": {
"hashes": [
- "sha256:09c19e5f4404574fcfb736efecf75844ffe8610606f3fccc35a1515b8b6712c4",
- "sha256:0ab5baaea8450f4a3e241ef17e3d129b2143e38a685036b075976b9c415ea3eb",
- "sha256:0d155a092bf0ebf4a9f6f3b7a650dc5d9a5bbb585ef83a52ed36ba46f55cc39d",
- "sha256:126638ab961633f0940a06e1c9d59919003ef212a15869708dcb7305f91a6732",
- "sha256:1a0a4f3aaa18580038cfa52a7183c8ffbbe7d727fe581300817efc1e96d1b0e9",
- "sha256:1d93461e2cf76c4796355494f15ffcb50a3c198cc2d601ad8d6a96219a10c363",
- "sha256:26a1a8443091c7fbc17b84a0d9f38de34b8423b459fb853e6c8cdfab0eacf613",
- "sha256:271d63396460b6607b588555ea27a1a02b717ca2e3f2cf53bdde4013d7790929",
- "sha256:28a108cb92ce6cf867690a962372996ca332d8cda0210c5ad487fe996e76b8bb",
- "sha256:29beac86f33d6c7ab1d79bd0213aa7aed2d2f555386856bb3056d5fdd9dab279",
- "sha256:2c757f64afe53a422e45e3e399e1e3cf82b7a2f244796ce80d8ca53e16a49b9f",
- "sha256:2dad8166d41ebd1f76ce107cf6a31e39801aee3844a54a90af23278b072f1ccf",
- "sha256:2dc72e891672343b99db6d497024bf8b985537ad6c393359dc5227ef653b2f17",
- "sha256:2f3c8822bc8fb4a347a192dd6a28a25d7f0ea3262e826d7d4ef9cc99cd06d07e",
- "sha256:32435d134414e01d937cd9d6cc56e8413a8d4741dea36af5840c7750f04d16ab",
- "sha256:3cfa4dbe17b2e6fca1414e9c3bcc216f6930cb18ea7646e7d0d52792ac196808",
- "sha256:3d5434b34100b504aabae75f0622ebb85defffe7b64ad8f52b8b30ec6ef6e4b9",
- "sha256:4003f380dac50328c85e85416aca6985536812c082387255c35292cb4b41707e",
- "sha256:44e91a669c43f03964f672c5a234ae0d7a4d49c9b85d1baa93dec28afa28ffbd",
- "sha256:4a14907b597ec55740f63e52d7fee0e9ee09d5b9d57a4f399a7423268e457b57",
- "sha256:4ce77d289f8d40905c054b63f29851ecbfd026ef4ba5c371a158cfe6f623663e",
- "sha256:4d6d74a97e898c1c2df80339aa423234ad9ea2052f66366cef1e80448798c13d",
- "sha256:51382c72dd5377861b573bd55dcf680df54cea84147c8648b15ac507fbef984d",
- "sha256:525cd69eff44833b01f8ef39aa33a9cc53a99ff7f9d76a6ef6a9fb758f54d0ff",
- "sha256:53ec65f7eee8655bebb1f6f1607760d123c3c115a324b443df4f916383482a67",
- "sha256:5f74b015c99a5eac5ae589de27a1201418a5d9d460e89ccb3366015c6153e60a",
- "sha256:6280353940f7e5e2efaaabd686193e61351e966cc02f401761c4d87f48c89ea4",
- "sha256:632c7aeb99df718765adf58eacb9acb9cbc555e075da849c1378ef4d18bf536a",
- "sha256:6465d36381af057d0fab4e0f24ef0e80ba61f03fe43e6eeccbe0056e74aadc70",
- "sha256:66a6dbf6ca7d2db03cc61cafe1ee6be838ce0fbc97781881a22a58a7c5efef42",
- "sha256:6d350388ba1129bc867c6af1cd17da2b197dff0d2801036d2d7d83c2d771a682",
- "sha256:7217234b10c64b52cc39a8d82550342ae2e45be34f5bff02b890b8c452eb48d7",
- "sha256:721ee3fc292f0d069a04016ef2c3a25595d48c5b8ddc6029be46f6158d129c92",
- "sha256:72a57b41a0920b9a220125081c1e191b88a4cdec13bf9d0649e382a822705c65",
- "sha256:73cc83f918b69110813a7d95024266072d987b903a623ecae673d1e71579d566",
- "sha256:778df71c8d0c8c9f1b378624b26431ca80041660d7be7c3f724b2c7a6e65d0d6",
- "sha256:79e1df60f7c2b148722fb6cafebffe1acd95fd8b5fd77795f56247edaf326752",
- "sha256:7c86d0d0919952d05df880a1889a4f0aeb6868e98961c090e335671dea5c0361",
- "sha256:7eaf13af79950142ab2bbb8362f8d8d935be9aaf8df1df89c86c3231e4ff238a",
- "sha256:828235a2a169160ee73a2fcfb8a000709edf09d7511fccf203465c3d5acc59e4",
- "sha256:8535e111a064f3bdd94c0ed443105934d6f005adad68dd13ce50a488a0ad1bf3",
- "sha256:88d2c3cc4b2f46d1ba73d81c51ec0e486f59cc51165ea4f789677f91a303a9a7",
- "sha256:8a2538806be846ea25e90c28786136932ec385c7ff3bc1148e45125984783dc6",
- "sha256:8dab30b21bd6fb17c3f4684868c7e6a9e8468078db00f599fb1c14e324b10fca",
- "sha256:8f18a7832ff85dfcd77871fe677b169b1bc60c021978c90c3bb14f727596e0ae",
- "sha256:946db4511b2d815979d733ac6a961f47e20a29c297be0d55b6d4b77ee4b298f6",
- "sha256:96758e56dceb8a70f8a5cff1e452daaeff07d1cc9f11e9b0c951330f0a2396a7",
- "sha256:9a172c3d5447b7da1680a1a2d6ecdf6f87a319d21d52729f45ec938a7006d5d8",
- "sha256:9a5211de242754b5e612557bca701f39f8b1a9408dff73c6db623f22d20f470e",
- "sha256:9df9a0d4c5624790a0dea2e02e3b1b3c69aed14bcb8650e19606d9df3719e87d",
- "sha256:aa4643635f26052401750bd54db911b6342eb1a9ac3e74f0f8b58a25d61dfe41",
- "sha256:aed37db837ecb5962469fad448aaae0f0ee94ffce2062cf2eb9aed13328b5196",
- "sha256:af52725c7c39b0ee655befbbab5b9a1b209e01bb39128dce0db226a10014aacc",
- "sha256:b0b8c06afcf2bac5a50b37f64efbde978b7f9dc88842ce9729c020dc71fae4ce",
- "sha256:b61e64b06c3640feab73fa4ff9cb64bd8182de52e5dc13038e01cfe674ebc321",
- "sha256:b7831566595fe88ba17ea80e4b61c0eb599f84c85acaa14bf04dd90319a45b90",
- "sha256:b8bc5b87a65a4e64bc83385c05145ea901b613d0d3a434d434b55511b6ab0067",
- "sha256:b8d51817cf4b8d545963ec65ff06c1b92e5765aa98831678d0e2240b6e9fd281",
- "sha256:b9f9cafaf031c34d95c1528c16b2fa07b710e6056b3c4e2e34e9317072da5d1a",
- "sha256:bb72d2a94481e7dc7a0c522673db288f31849800d6ce2435317376a345728225",
- "sha256:c25ec06e4241e162f5d1f57c370f4078797ade95c9208bd0c60f484834f09c96",
- "sha256:c405d482c320a88ab53dcbd98d6d6f32ada074f2d965d6e9bf2d823158fa97de",
- "sha256:c4472fe53ebf541113e533971bd8c32728debc4c6d8cc177f2bff31d011ec17e",
- "sha256:c4b1efb11a8acd13246ffb0bee888dd0e8eb057f8bf30112e3e21e421eb82d4a",
- "sha256:c5f3faeb8100a43adf3e7925d556801d14b5816a0ac9e75e22948e787feec642",
- "sha256:c6f034386e5550b5dc8ded90b5e2ff7db21f0f5c7de37b6efc5dac046eb19c10",
- "sha256:c99ddaddb2fbe04953b84d1651149a0d85214780e4d0ee824e610ab549d98d92",
- "sha256:ca6b66f69e30f6e180d52f14d91ac854b8119553b524e0e28d5291a724f0f423",
- "sha256:cccdc02e46d2bd7cb5f38f8cc3d9db0d24951abd082b2f242c9e9f59c0ab2af3",
- "sha256:cd49a908cb6d387fc26acee8b7d9fcc9bbf8e1aca890c0b2fdfd706057546080",
- "sha256:cf7a4e8de7f1092829caef66fd90eaf3710bc5efd322a816d5677b7664893c93",
- "sha256:cfd77e8e5cafba3fb584e0f4b935a59216f352b73d4987be3af51f43a862c403",
- "sha256:d34c4f80956227f2686ddea5b3585e109c2733e2d4ef12eb1b8b4e84f09a2ab6",
- "sha256:d61a0ca95503867d4d627517bcfdc28a8468c3f1b0b06c626f30dd759d3999fd",
- "sha256:d81657b23e0edb84b37167e98aefb04ae16cbc5352770057893bd222cdc6e45f",
- "sha256:d92d897cb4b4bf915fbeb5e604c7911021a8456f0964f3b8ebbe7f9188b9eabb",
- "sha256:dd318e6b75ca80bff0b22b302f83a8ee41c62b8ac662ddb49f67ec97e799885d",
- "sha256:dd952b9c64f3b21aedd09b8fe958e4931864dba69926d8a90c90d36ac4e28c9a",
- "sha256:e0e7e83f31e23c5d00ff618045ddc5e916f9e613d33c5a5823bc0b0a0feb522f",
- "sha256:e0f17d1df951336a02afc8270c03c0c6e60d1f9996fcbd43a4ce6be81de0bd9d",
- "sha256:e2a16ef5fa2382af83bef4a18c1b3bcb4284c4732906aa69422cf09df9c59f1f",
- "sha256:e36021db54b8a0475805acc1d6c4bca5d9f52c3825ad29ae2d398a9d530ddb88",
- "sha256:e73db54c967eb75037c178a54445c5a4e7461b5203b27c45ef656a81787c0c1b",
- "sha256:e741bd48e6a417bdfbae02e088f60018286d6c141639359fb8df017a3b69415a",
- "sha256:f7271d6bd8838c49ba8ae647fc06469137e1c161a7ef97d778b72904d9b68696",
- "sha256:fc391e3941045fd0987c77484b2799adffd08e4b6735c4ee5f054366a2e1551d",
- "sha256:fc94441bcf9cb8c59f51f23193316afefbf3ff858460cb47b5758bf66a14d130",
- "sha256:fe34befb8c765b8ce562f0200afda3578f8abb159c76de3ab354c80b72244c41",
- "sha256:fe8080b4f25dfc44a86bedd14bc4f9d469dfc6456e6f3c5d9077e81a5fedfba7",
- "sha256:ff34cb09a332832d1cf38acd0f604c068665192c6107a439a92abfd8acf90fe2"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==1.9.3"
+ "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a",
+ "sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8",
+ "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b",
+ "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da",
+ "sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf",
+ "sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890",
+ "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093",
+ "sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6",
+ "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79",
+ "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683",
+ "sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed",
+ "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2",
+ "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff",
+ "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02",
+ "sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b",
+ "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03",
+ "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511",
+ "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c",
+ "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124",
+ "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c",
+ "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da",
+ "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2",
+ "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0",
+ "sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba",
+ "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d",
+ "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53",
+ "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138",
+ "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4",
+ "sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748",
+ "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7",
+ "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d",
+ "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503",
+ "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d",
+ "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2",
+ "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa",
+ "sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737",
+ "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f",
+ "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1",
+ "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d",
+ "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694",
+ "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3",
+ "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a",
+ "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d",
+ "sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b",
+ "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a",
+ "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6",
+ "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b",
+ "sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea",
+ "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5",
+ "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f",
+ "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df",
+ "sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f",
+ "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b",
+ "sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba",
+ "sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9",
+ "sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0",
+ "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6",
+ "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b",
+ "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967",
+ "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2",
+ "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708",
+ "sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda",
+ "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8",
+ "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10",
+ "sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c",
+ "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b",
+ "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028",
+ "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e",
+ "sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147",
+ "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33",
+ "sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca",
+ "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590",
+ "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c",
+ "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53",
+ "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74",
+ "sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60",
+ "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f",
+ "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1",
+ "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27",
+ "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520",
+ "sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e",
+ "sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467",
+ "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca",
+ "sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859",
+ "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273",
+ "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e",
+ "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601",
+ "sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054",
+ "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376",
+ "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7",
+ "sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b",
+ "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb",
+ "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65",
+ "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784",
+ "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71",
+ "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b",
+ "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a",
+ "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c",
+ "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face",
+ "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d",
+ "sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e",
+ "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e",
+ "sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca",
+ "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9",
+ "sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb",
+ "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95",
+ "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed",
+ "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf",
+ "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca",
+ "sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2",
+ "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62",
+ "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df",
+ "sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a",
+ "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67",
+ "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f",
+ "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529",
+ "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486",
+ "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a",
+ "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e",
+ "sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b",
+ "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74",
+ "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d",
+ "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b",
+ "sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc",
+ "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2",
+ "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e",
+ "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8",
+ "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82",
+ "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd",
+ "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==1.22.0"
+ },
+ "zstandard": {
+ "hashes": [
+ "sha256:011d388c76b11a0c165374ce660ce2c8efa8e5d87f34996aa80f9c0816698b64",
+ "sha256:01582723b3ccd6939ab7b3a78622c573799d5d8737b534b86d0e06ac18dbde4a",
+ "sha256:05353cef599a7b0b98baca9b068dd36810c3ef0f42bf282583f438caf6ddcee3",
+ "sha256:05df5136bc5a011f33cd25bc9f506e7426c0c9b3f9954f056831ce68f3b6689f",
+ "sha256:06acb75eebeedb77b69048031282737717a63e71e4ae3f77cc0c3b9508320df6",
+ "sha256:07b527a69c1e1c8b5ab1ab14e2afe0675614a09182213f21a0717b62027b5936",
+ "sha256:0bbc9a0c65ce0eea3c34a691e3c4b6889f5f3909ba4822ab385fab9057099431",
+ "sha256:0be7622c37c183406f3dbf0cba104118eb16a4ea7359eeb5752f0794882fc250",
+ "sha256:106281ae350e494f4ac8a80470e66d1fe27e497052c8d9c3b95dc4cf1ade81aa",
+ "sha256:10ef2a79ab8e2974e2075fb984e5b9806c64134810fac21576f0668e7ea19f8f",
+ "sha256:1673b7199bbe763365b81a4f3252b8e80f44c9e323fc42940dc8843bfeaf9851",
+ "sha256:172de1f06947577d3a3005416977cce6168f2261284c02080e7ad0185faeced3",
+ "sha256:181eb40e0b6a29b3cd2849f825e0fa34397f649170673d385f3598ae17cca2e9",
+ "sha256:1869da9571d5e94a85a5e8d57e4e8807b175c9e4a6294e3b66fa4efb074d90f6",
+ "sha256:19796b39075201d51d5f5f790bf849221e58b48a39a5fc74837675d8bafc7362",
+ "sha256:1cd5da4d8e8ee0e88be976c294db744773459d51bb32f707a0f166e5ad5c8649",
+ "sha256:1f3689581a72eaba9131b1d9bdbfe520ccd169999219b41000ede2fca5c1bfdb",
+ "sha256:1f830a0dac88719af0ae43b8b2d6aef487d437036468ef3c2ea59c51f9d55fd5",
+ "sha256:223415140608d0f0da010499eaa8ccdb9af210a543fac54bce15babbcfc78439",
+ "sha256:22a06c5df3751bb7dc67406f5374734ccee8ed37fc5981bf1ad7041831fa1137",
+ "sha256:22a086cff1b6ceca18a8dd6096ec631e430e93a8e70a9ca5efa7561a00f826fa",
+ "sha256:23ebc8f17a03133b4426bcc04aabd68f8236eb78c3760f12783385171b0fd8bd",
+ "sha256:25f8f3cd45087d089aef5ba3848cd9efe3ad41163d3400862fb42f81a3a46701",
+ "sha256:2b6bd67528ee8b5c5f10255735abc21aa106931f0dbaf297c7be0c886353c3d0",
+ "sha256:2e54296a283f3ab5a26fc9b8b5d4978ea0532f37b231644f367aa588930aa043",
+ "sha256:3756b3e9da9b83da1796f8809dd57cb024f838b9eeafde28f3cb472012797ac1",
+ "sha256:37daddd452c0ffb65da00620afb8e17abd4adaae6ce6310702841760c2c26860",
+ "sha256:3a39c94ad7866160a4a46d772e43311a743c316942037671beb264e395bdd611",
+ "sha256:3b870ce5a02d4b22286cf4944c628e0f0881b11b3f14667c1d62185a99e04f53",
+ "sha256:3c83b0188c852a47cd13ef3bf9209fb0a77fa5374958b8c53aaa699398c6bd7b",
+ "sha256:4203ce3b31aec23012d3a4cf4a2ed64d12fea5269c49aed5e4c3611b938e4088",
+ "sha256:457ed498fc58cdc12fc48f7950e02740d4f7ae9493dd4ab2168a47c93c31298e",
+ "sha256:474d2596a2dbc241a556e965fb76002c1ce655445e4e3bf38e5477d413165ffa",
+ "sha256:4b14abacf83dfb5c25eb4e4a79520de9e7e205f72c9ee7702f91233ae57d33a2",
+ "sha256:4b6d83057e713ff235a12e73916b6d356e3084fd3d14ced499d84240f3eecee0",
+ "sha256:4d441506e9b372386a5271c64125f72d5df6d2a8e8a2a45a0ae09b03cb781ef7",
+ "sha256:4f187a0bb61b35119d1926aee039524d1f93aaf38a9916b8c4b78ac8514a0aaf",
+ "sha256:51526324f1b23229001eb3735bc8c94f9c578b1bd9e867a0a646a3b17109f388",
+ "sha256:53e08b2445a6bc241261fea89d065536f00a581f02535f8122eba42db9375530",
+ "sha256:53f94448fe5b10ee75d246497168e5825135d54325458c4bfffbaafabcc0a577",
+ "sha256:5a56ba0db2d244117ed744dfa8f6f5b366e14148e00de44723413b2f3938a902",
+ "sha256:5f1ad7bf88535edcf30038f6919abe087f606f62c00a87d7e33e7fc57cb69fcc",
+ "sha256:5f5e4c2a23ca271c218ac025bd7d635597048b366d6f31f420aaeb715239fc98",
+ "sha256:6a573a35693e03cf1d67799fd01b50ff578515a8aeadd4595d2a7fa9f3ec002a",
+ "sha256:6c0e5a65158a7946e7a7affa6418878ef97ab66636f13353b8502d7ea03c8097",
+ "sha256:6dffecc361d079bb48d7caef5d673c88c8988d3d33fb74ab95b7ee6da42652ea",
+ "sha256:7030defa83eef3e51ff26f0b7bfb229f0204b66fe18e04359ce3474ac33cbc09",
+ "sha256:7149623bba7fdf7e7f24312953bcf73cae103db8cae49f8154dd1eadc8a29ecb",
+ "sha256:72d35d7aa0bba323965da807a462b0966c91608ef3a48ba761678cb20ce5d8b7",
+ "sha256:75ffc32a569fb049499e63ce68c743155477610532da1eb38e7f24bf7cd29e74",
+ "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b",
+ "sha256:78228d8a6a1c177a96b94f7e2e8d012c55f9c760761980da16ae7546a15a8e9b",
+ "sha256:7b3c3a3ab9daa3eed242d6ecceead93aebbb8f5f84318d82cee643e019c4b73b",
+ "sha256:809c5bcb2c67cd0ed81e9229d227d4ca28f82d0f778fc5fea624a9def3963f91",
+ "sha256:81dad8d145d8fd981b2962b686b2241d3a1ea07733e76a2f15435dfb7fb60150",
+ "sha256:85304a43f4d513f5464ceb938aa02c1e78c2943b29f44a750b48b25ac999a049",
+ "sha256:89c4b48479a43f820b749df49cd7ba2dbc2b1b78560ecb5ab52985574fd40b27",
+ "sha256:8e735494da3db08694d26480f1493ad2cf86e99bdd53e8e9771b2752a5c0246a",
+ "sha256:913cbd31a400febff93b564a23e17c3ed2d56c064006f54efec210d586171c00",
+ "sha256:9174f4ed06f790a6869b41cba05b43eeb9a35f8993c4422ab853b705e8112bbd",
+ "sha256:9300d02ea7c6506f00e627e287e0492a5eb0371ec1670ae852fefffa6164b072",
+ "sha256:933b65d7680ea337180733cf9e87293cc5500cc0eb3fc8769f4d3c88d724ec5c",
+ "sha256:9654dbc012d8b06fc3d19cc825af3f7bf8ae242226df5f83936cb39f5fdc846c",
+ "sha256:98750a309eb2f020da61e727de7d7ba3c57c97cf6213f6f6277bb7fb42a8e065",
+ "sha256:99c0c846e6e61718715a3c9437ccc625de26593fea60189567f0118dc9db7512",
+ "sha256:a1a4ae2dec3993a32247995bdfe367fc3266da832d82f8438c8570f989753de1",
+ "sha256:a3f79487c687b1fc69f19e487cd949bf3aae653d181dfb5fde3bf6d18894706f",
+ "sha256:a4089a10e598eae6393756b036e0f419e8c1d60f44a831520f9af41c14216cf2",
+ "sha256:a51ff14f8017338e2f2e5dab738ce1ec3b5a851f23b18c1ae1359b1eecbee6df",
+ "sha256:a5a419712cf88862a45a23def0ae063686db3d324cec7edbe40509d1a79a0aab",
+ "sha256:a9ec8c642d1ec73287ae3e726792dd86c96f5681eb8df274a757bf62b750eae7",
+ "sha256:aaf21ba8fb76d102b696781bddaa0954b782536446083ae3fdaa6f16b25a1c4b",
+ "sha256:ab85470ab54c2cb96e176f40342d9ed41e58ca5733be6a893b730e7af9c40550",
+ "sha256:b9af1fe743828123e12b41dd8091eca1074d0c1569cc42e6e1eee98027f2bbd0",
+ "sha256:bfc4e20784722098822e3eee42b8e576b379ed72cca4a7cb856ae733e62192ea",
+ "sha256:bfd06b1c5584b657a2892a6014c2f4c20e0db0208c159148fa78c65f7e0b0277",
+ "sha256:c19bcdd826e95671065f8692b5a4aa95c52dc7a02a4c5a0cac46deb879a017a2",
+ "sha256:c2ba942c94e0691467ab901fc51b6f2085ff48f2eea77b1a48240f011e8247c7",
+ "sha256:c8e167d5adf59476fa3e37bee730890e389410c354771a62e3c076c86f9f7778",
+ "sha256:ca54090275939dc8ec5dea2d2afb400e0f83444b2fc24e07df7fdef677110859",
+ "sha256:d7541afd73985c630bafcd6338d2518ae96060075f9463d7dc14cfb33514383d",
+ "sha256:d8c56bb4e6c795fc77d74d8e8b80846e1fb8292fc0b5060cd8131d522974b751",
+ "sha256:da469dc041701583e34de852d8634703550348d5822e66a0c827d39b05365b12",
+ "sha256:daab68faadb847063d0c56f361a289c4f268706b598afbf9ad113cbe5c38b6b2",
+ "sha256:e05ab82ea7753354bb054b92e2f288afb750e6b439ff6ca78af52939ebbc476d",
+ "sha256:e09bb6252b6476d8d56100e8147b803befa9a12cea144bbe629dd508800d1ad0",
+ "sha256:e29f0cf06974c899b2c188ef7f783607dbef36da4c242eb6c82dcd8b512855e3",
+ "sha256:e59fdc271772f6686e01e1b3b74537259800f57e24280be3f29c8a0deb1904dd",
+ "sha256:e7360eae90809efd19b886e59a09dad07da4ca9ba096752e61a2e03c8aca188e",
+ "sha256:e96594a5537722fdfb79951672a2a63aec5ebfb823e7560586f7484819f2a08f",
+ "sha256:ea9d54cc3d8064260114a0bbf3479fc4a98b21dffc89b3459edd506b69262f6e",
+ "sha256:ec996f12524f88e151c339688c3897194821d7f03081ab35d31d1e12ec975e94",
+ "sha256:f27662e4f7dbf9f9c12391cb37b4c4c3cb90ffbd3b1fb9284dadbbb8935fa708",
+ "sha256:f373da2c1757bb7f1acaf09369cdc1d51d84131e50d5fa9863982fd626466313",
+ "sha256:f5aeea11ded7320a84dcdd62a3d95b5186834224a9e55b92ccae35d21a8b63d4",
+ "sha256:f604efd28f239cc21b3adb53eb061e2a205dc164be408e553b41ba2ffe0ca15c",
+ "sha256:f67e8f1a324a900e75b5e28ffb152bcac9fbed1cc7b43f99cd90f395c4375344",
+ "sha256:fd7a5004eb1980d3cefe26b2685bcb0b17989901a70a1040d1ac86f1d898c551",
+ "sha256:ffef5a74088f1e09947aecf91011136665152e0b4b359c42be3373897fb39b01"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==0.25.0"
}
},
"develop": {
"astroid": {
"hashes": [
- "sha256:7d5895c9825e18079c5aeac0572bc2e4c83205c95d416e0b4fee8bc361d2d9ca",
- "sha256:86b0bb7d7da0be1a7c4aedb7974e391b32d4ed89e33de6ed6902b4b15c97577e"
+ "sha256:4148645659b08b70d72460ed1921158027a9e53ae8b7234149b1400eddacbb93",
+ "sha256:92fcf218b89f449cdf9f7b39a269f8d5d617b27be68434912e11e79203963a17"
],
"markers": "python_full_version >= '3.8.0'",
- "version": "==3.0.1"
+ "version": "==3.0.3"
},
"bandit": {
"hashes": [
- "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549",
- "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e"
+ "sha256:32410415cd93bf9c8b91972159d5cf1e7f063a9146d70345641cd3877de348ce",
+ "sha256:bda8d68610fc33a6e10b7a8f1d61d92c8f6c004051d5e946406be1fb1b16a868"
],
"index": "pypi",
- "markers": "python_version >= '3.7'",
- "version": "==1.7.5"
+ "markers": "python_version >= '3.10'",
+ "version": "==1.9.2"
},
"black": {
"hashes": [
@@ -1159,51 +1735,44 @@
},
"click": {
"hashes": [
- "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
- "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"
+ "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a",
+ "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"
],
- "markers": "python_version >= '3.7'",
- "version": "==8.1.7"
+ "markers": "python_version >= '3.10'",
+ "version": "==8.3.1"
},
- "dill": {
- "hashes": [
- "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e",
- "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"
- ],
- "markers": "python_version < '3.11'",
- "version": "==0.3.7"
- },
- "gitdb": {
+ "colorama": {
"hashes": [
- "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4",
- "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"
+ "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44",
+ "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"
],
- "markers": "python_version >= '3.7'",
- "version": "==4.0.11"
+ "index": "pypi",
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'",
+ "version": "==0.4.6"
},
- "gitpython": {
+ "dill": {
"hashes": [
- "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4",
- "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a"
+ "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0",
+ "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049"
],
- "markers": "python_version >= '3.7'",
- "version": "==3.1.40"
+ "markers": "python_version >= '3.8'",
+ "version": "==0.4.0"
},
"isort": {
"hashes": [
- "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504",
- "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"
+ "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109",
+ "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"
],
"markers": "python_full_version >= '3.8.0'",
- "version": "==5.12.0"
+ "version": "==5.13.2"
},
"markdown-it-py": {
"hashes": [
- "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1",
- "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"
+ "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147",
+ "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3"
],
- "markers": "python_version >= '3.8'",
- "version": "==3.0.0"
+ "markers": "python_version >= '3.10'",
+ "version": "==4.0.0"
},
"mccabe": {
"hashes": [
@@ -1223,11 +1792,11 @@
},
"mypy-extensions": {
"hashes": [
- "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d",
- "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"
+ "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505",
+ "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"
],
- "markers": "python_version >= '3.5'",
- "version": "==1.0.0"
+ "markers": "python_version >= '3.8'",
+ "version": "==1.1.0"
},
"packaging": {
"hashes": [
@@ -1240,35 +1809,27 @@
},
"pathspec": {
"hashes": [
- "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20",
- "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"
+ "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08",
+ "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"
],
- "markers": "python_version >= '3.7'",
- "version": "==0.11.2"
- },
- "pbr": {
- "hashes": [
- "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda",
- "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9"
- ],
- "markers": "python_version >= '2.6'",
- "version": "==6.0.0"
+ "markers": "python_version >= '3.8'",
+ "version": "==0.12.1"
},
"platformdirs": {
"hashes": [
- "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b",
- "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"
+ "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312",
+ "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3"
],
- "markers": "python_version >= '3.7'",
- "version": "==4.0.0"
+ "markers": "python_version >= '3.10'",
+ "version": "==4.5.0"
},
"pygments": {
"hashes": [
- "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c",
- "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"
+ "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887",
+ "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"
],
- "markers": "python_version >= '3.7'",
- "version": "==2.17.2"
+ "markers": "python_version >= '3.8'",
+ "version": "==2.19.2"
},
"pylint": {
"hashes": [
@@ -1281,108 +1842,154 @@
},
"pyyaml": {
"hashes": [
- "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5",
- "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc",
- "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df",
- "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741",
- "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206",
- "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27",
- "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595",
- "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62",
- "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98",
- "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696",
- "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290",
- "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9",
- "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d",
- "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6",
- "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867",
- "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47",
- "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486",
- "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6",
- "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3",
- "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007",
- "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938",
- "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0",
- "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c",
- "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735",
- "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d",
- "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28",
- "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4",
- "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba",
- "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8",
- "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5",
- "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd",
- "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3",
- "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0",
- "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515",
- "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c",
- "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c",
- "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924",
- "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34",
- "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43",
- "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859",
- "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673",
- "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54",
- "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a",
- "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b",
- "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab",
- "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa",
- "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c",
- "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585",
- "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d",
- "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"
+ "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c",
+ "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a",
+ "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3",
+ "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956",
+ "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6",
+ "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c",
+ "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65",
+ "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a",
+ "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0",
+ "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b",
+ "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1",
+ "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6",
+ "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7",
+ "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e",
+ "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007",
+ "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310",
+ "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4",
+ "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9",
+ "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295",
+ "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea",
+ "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0",
+ "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e",
+ "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac",
+ "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9",
+ "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7",
+ "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35",
+ "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb",
+ "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b",
+ "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69",
+ "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5",
+ "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b",
+ "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c",
+ "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369",
+ "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd",
+ "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824",
+ "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198",
+ "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065",
+ "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c",
+ "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c",
+ "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764",
+ "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196",
+ "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b",
+ "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00",
+ "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac",
+ "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8",
+ "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e",
+ "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28",
+ "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3",
+ "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5",
+ "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4",
+ "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b",
+ "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf",
+ "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5",
+ "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702",
+ "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8",
+ "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788",
+ "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da",
+ "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d",
+ "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc",
+ "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c",
+ "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba",
+ "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f",
+ "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917",
+ "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5",
+ "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26",
+ "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f",
+ "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b",
+ "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be",
+ "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c",
+ "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3",
+ "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6",
+ "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926",
+ "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0"
],
- "markers": "python_version >= '3.6'",
- "version": "==6.0.1"
+ "markers": "python_version >= '3.8'",
+ "version": "==6.0.3"
},
"rich": {
"hashes": [
- "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa",
- "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"
+ "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4",
+ "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd"
],
- "markers": "python_full_version >= '3.7.0'",
- "version": "==13.7.0"
- },
- "smmap": {
- "hashes": [
- "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62",
- "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==5.0.1"
+ "markers": "python_full_version >= '3.8.0'",
+ "version": "==14.2.0"
},
"stevedore": {
"hashes": [
- "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d",
- "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"
+ "sha256:4a36dccefd7aeea0c70135526cecb7766c4c84c473b1af68db23d541b6dc1820",
+ "sha256:f22d15c6ead40c5bbfa9ca54aa7e7b4a07d59b36ae03ed12ced1a54cf0b51945"
],
- "markers": "python_version >= '3.8'",
- "version": "==5.1.0"
+ "markers": "python_version >= '3.10'",
+ "version": "==5.6.0"
},
"tomli": {
"hashes": [
- "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
- "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
+ "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6",
+ "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd",
+ "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c",
+ "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b",
+ "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8",
+ "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6",
+ "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77",
+ "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff",
+ "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea",
+ "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192",
+ "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249",
+ "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee",
+ "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4",
+ "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98",
+ "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8",
+ "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4",
+ "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281",
+ "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744",
+ "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69",
+ "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13",
+ "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140",
+ "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e",
+ "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e",
+ "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc",
+ "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff",
+ "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec",
+ "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2",
+ "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222",
+ "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106",
+ "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272",
+ "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a",
+ "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"
],
- "markers": "python_version < '3.11'",
- "version": "==2.0.1"
+ "index": "pypi",
+ "markers": "python_version >= '3.8'",
+ "version": "==2.2.1"
},
"tomlkit": {
"hashes": [
- "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4",
- "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"
+ "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1",
+ "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0"
],
- "markers": "python_version >= '3.7'",
- "version": "==0.12.3"
+ "markers": "python_version >= '3.8'",
+ "version": "==0.13.3"
},
"typing-extensions": {
"hashes": [
- "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0",
- "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"
+ "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466",
+ "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"
],
"index": "pypi",
- "markers": "python_version >= '3.8'",
- "version": "==4.8.0"
+ "markers": "python_version >= '3.9'",
+ "version": "==4.15.0"
}
}
}
diff --git a/README.md b/README.md
index 2e3d32e344..58243cab61 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
-
+
@@ -23,8 +23,8 @@
-
-
+
+
@@ -48,7 +48,7 @@
Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way.
-This bot is free for everyone and always will be. If you like this project and would like to show your appreciation, you can support us on **[Patreon](https://www.patreon.com/kyber)**, cool benefits included!
+This bot is free for everyone and always will be. If you like this project and would like to show your appreciation, you can support us on **[Buy Me A Coffee](https://buymeacoffee.com/modmaildev)**, cool benefits included!
For up-to-date setup instructions, please visit our [**documentation**](https://docs.modmail.dev/installation) page.
@@ -72,7 +72,7 @@ Our Logviewer will save the threads so you can view previous threads through the
* When you close a thread, Modmail will generate a log link and post it to your log channel.
* Native Discord dark-mode feel.
* Markdown/formatting support.
- * Login via Discord to protect your logs ([premium Patreon feature](https://patreon.com/kyber)).
+ * Login via Discord to protect your logs ([premium feature](https://buymeacoffee.com/modmaildev/membership)).
* See past logs of a user with `?logs`.
* Searchable by text queries using `?logs search`.
@@ -90,15 +90,15 @@ There are a number of options for hosting your very own dedicated Modmail bot.
Visit our [**documentation**](https://docs.modmail.dev/installation) page for detailed guidance on how to deploy your Modmail bot.
-### Patreon Hosting
+### Paid Hosting
-If you don't want the trouble of renting and configuring your server to host Modmail, we got a solution for you! We offer hosting and maintenance of your own, private Modmail bot (including a Logviewer) through [**Patreon**](https://patreon.com/kyber).
+If you don't want the trouble of renting and configuring your server to host Modmail, we got a solution for you! We offer hosting and maintenance of your own, private Modmail bot (including a Logviewer) through [**Buy Me A Coffee**](https://buymeacoffee.com/modmaildev/membership).
## FAQ
**Q: Where can I find the Modmail bot invite link?**
-**A:** Unfortunately, due to how this bot functions, it cannot be invited. The lack of an invite link is to ensure an individuality to your server and grant you full control over your bot and data. Nonetheless, you can quickly obtain a free copy of Modmail for your server by following our [**documentation**](https://docs.modmail.dev/installation) steps or subscribe to [**Patreon**](https://patreon.com/kyber).
+**A:** Unfortunately, due to how this bot functions, it cannot be invited. The lack of an invite link is to ensure an individuality to your server and grant you full control over your bot and data. Nonetheless, you can quickly obtain a free copy of Modmail for your server by following our [**documentation**](https://docs.modmail.dev/installation) steps or subscribe to [**Buy Me A Coffee**](https://buymeacoffee.com/modmaildev/membership).
**Q: Where can I find out more info about Modmail?**
@@ -147,13 +147,6 @@ Advertise Your Server:
-Help Us • Help Other's:
-
-
-
-
-
-
Discord Advice Center:
@@ -161,20 +154,19 @@ Discord Advice Center:
-Blacklight Promotions:
+Kistó Bakery:
-
-
+
+
-
-Become a sponsor on [Patreon](https://patreon.com/kyber).
+Become a sponsor on [Buy Me A Coffee](https://buymeacoffee.com/modmaildev/membership).
## Contributing
Contributions to Modmail are always welcome, whether it be improvements to the documentation or new functionality, please feel free to make the change. Check out our [contributing guidelines](https://github.com/modmail-dev/modmail/blob/master/.github/CONTRIBUTING.md) before you get started.
-If you like this project and would like to show your appreciation, support us on **[Patreon](https://www.patreon.com/kyber)**!
+If you like this project and would like to show your appreciation, support us on **[Buy Me A Coffee](https://buymeacoffee.com/modmaildev)**!
## Beta Testing
diff --git a/SPONSORS.json b/SPONSORS.json
index b6212b8ed7..955b839fd7 100644
--- a/SPONSORS.json
+++ b/SPONSORS.json
@@ -112,33 +112,6 @@
"title": "uncommon community"
}
},
- {
- "embed": {
- "author": {
- "name": "Help us • Help Others"
- },
- "title": "Join Today",
- "url": "https://discord.gg/5yQCFzY6HU",
- "description": "At Help Us • Help Others, we accept as true with inside the transformative electricity of cooperation and kindness. Each one people has the capability to make a meaningful impact by means of helping and caring for others. Whether you want assistance or want to offer it, this is the right region for you!",
- "fields": [
- {
- "name": "What we offer:",
- "value": "`🎬` - Active community\n`👮` - Active staff around the globe! \n`🛜` - 40+ Advertising channels to grow your socials!\n`💎` - Boosting Perks\n`🎉` - Event's monthly especially bank holiday roles!!\n`🔢` - Unique levelling systems\n`📞` - Multiple voice channels including gaming!\n`🎁` - Exclusive giveaways!"
- },
- {
- "name": "We Are Hiring",
- "value": "`🔵` - Moderators\n`🔵` - Human Resources\n`🔵` - Community Team\n`🔵` - Partnership Manager\n`🔵` - Growth Manager\n`🚀` Much more to come!\n\n\nJoin Today!"
- }
- ],
- "image": {
- "url": "https://cdn.discordapp.com/attachments/1218338794416246874/1243635366326567002/AD_animated.gif"
- },
- "color": 45300,
- "footer": {
- "text": "Help Us • Help Others"
- }
- }
- },
{
"embed": {
"description": "> Be apart of our community as we start to grow! and embark on a long journey.\n——————————————————-\n**What we offer?**\n\n➺〚🖌️〛Custom Liveries \n➺〚❤️〛Friendly and Growing community.\n➺〚🤝〛Partnerships.\n➺〚🎮〛Daily SSUs. \n➺〚🚨〛Great roleplays.\n➺〚💬〛Kind and Professional staff\n➺〚🎉〛Giveaways!!! \n——————————————————-\n**Emergency Services**\n\n➺〚🚔〛NY Police Force\n➺〚🚒〛Fire & Emergency NY\n➺〚🚧〛NY department of transportation \n\n——————————————————-\n**Whitelisted**\nComing soon!\n——————————————————-\n**What are we looking for!**\n\n➺〚💬〛More members\n➺〚⭐〛Staff Members - **WE'RE HIRING!**\n➺〚🤝〛Partnerships\n➺〚💎〛Boosters\n——————————————————\n\n**[Join now](https://discord.com/invite/qt62qSnKVa)**",
@@ -158,5 +131,21 @@
"description": "*Your Retail Journey*\n*\"Better choice and better value in food, fashion & homewares.\"*\n\n\n**------------------------------------------**\n*__About us__*\nSupermarket, CityStore PLC! Attend a training to become staff!\n\nThis game is currently in V3\n\nWe have a training Centre and applications center!\n\n**------------------------------------------**\n\n> *❤️ Don't hesitate! Dive into the excitement today by joining our vibrant community on Discord. Experience our unique perspective and become an integral part of our group. Your **journey** with us promises to be unforgettable no regrets, only great memories await! ❤️*\n\n*We hope to see you. *\n\n*Signed,*\n**CityStore PLC**\n> Discord: https://discord.gg/yjFQb5mrSk\n> Roblox Group: https://www.roblox.com/groups/32819373/CityStore-PLC#!/about\n\nJoin us now and become apart of Citystore PLC community! 🎉",
"color": 15523550
}
+ },
+ {
+ "embed": {
+ "description": "✨ *\"Let's bake it!\"* ✨ \n\nKistó is a very successful and well-known **Bakery Group** on the platform. Its goal is to give every guest the **ultimate bakery experience**. \n\nWe have a wide variety of hand-made treats, from our rich **drinks** to our freshly baked **pastries**. Every item is made with care by our **skilled and passionate team**, redefining what it means to be a modern bakery. \n\n💖 Come visit us today and taste the *sweet side of perfection* at **Kistó Bakery.** \n\n**Roblox Group:** [Click here!](https://www.roblox.com/communities/9318596/Kist#!/about) \n**Discord Server:** [Click here!](https://discord.gg/aGt8Wv3gP9)",
+ "color": 16736255,
+ "author": {
+ "name": "Kistó Bakery",
+ "icon_url": "https://cdn.discordapp.com/attachments/1413609998797242522/1436882475883298887/noFilter_10_1.png"
+ },
+ "footer": {
+ "text": "Proudly serving since 2021"
+ },
+ "image": {
+ "url": "https://cdn.discordapp.com/attachments/1413609998797242522/1436882475543429260/0904.png"
+ }
+ }
}
]
diff --git a/bot.py b/bot.py
index 3f13ef7ced..a022e99dcf 100644
--- a/bot.py
+++ b/bot.py
@@ -1,10 +1,9 @@
-__version__ = "4.1.2"
+__version__ = "4.2.1"
import asyncio
import copy
import hashlib
-import logging
import os
import re
import string
@@ -12,7 +11,7 @@
import sys
import platform
import typing
-from datetime import datetime, timezone, timedelta
+from datetime import datetime, timezone
from subprocess import PIPE
from types import SimpleNamespace
@@ -48,7 +47,15 @@
)
from core.thread import ThreadManager
from core.time import human_timedelta
-from core.utils import extract_block_timestamp, normalize_alias, parse_alias, truncate, tryint, human_join
+from core.utils import (
+ extract_block_timestamp,
+ normalize_alias,
+ parse_alias,
+ truncate,
+ tryint,
+ human_join,
+ extract_forwarded_content,
+)
logger = getLogger(__name__)
@@ -76,12 +83,18 @@ def __init__(self):
self.session = None
self._api = None
self.formatter = SafeFormatter()
- self.loaded_cogs = ["cogs.modmail", "cogs.plugins", "cogs.utility"]
+ self.loaded_cogs = [
+ "cogs.modmail",
+ "cogs.plugins",
+ "cogs.utility",
+ "cogs.threadmenu",
+ ]
self._connected = None
self.start_time = discord.utils.utcnow()
self._started = False
self.threads = ThreadManager(self)
+ self._message_queues = {} # User ID -> asyncio.Queue for message ordering
log_dir = os.path.join(temp_dir, "logs")
if not os.path.exists(log_dir):
@@ -93,7 +106,10 @@ def __init__(self):
self.startup()
def get_guild_icon(
- self, guild: typing.Optional[discord.Guild], *, size: typing.Optional[int] = None
+ self,
+ guild: typing.Optional[discord.Guild],
+ *,
+ size: typing.Optional[int] = None,
) -> str:
if guild is None:
guild = self.guild
@@ -308,7 +324,10 @@ def log_channel(self) -> typing.Optional[discord.TextChannel]:
try:
channel = self.main_category.channels[0]
self.config["log_channel_id"] = channel.id
- logger.warning("No log channel set, setting #%s to be the log channel.", channel.name)
+ logger.warning(
+ "No log channel set, setting #%s to be the log channel.",
+ channel.name,
+ )
return channel
except IndexError:
pass
@@ -561,7 +580,11 @@ async def on_ready(self):
logger.debug("Closing thread for recipient %s.", recipient_id)
after = 0
else:
- logger.debug("Thread for recipient %s will be closed after %s seconds.", recipient_id, after)
+ logger.debug(
+ "Thread for recipient %s will be closed after %s seconds.",
+ recipient_id,
+ after,
+ )
thread = await self.threads.find(recipient_id=int(recipient_id))
@@ -582,7 +605,7 @@ async def on_ready(self):
)
for log in await self.api.get_open_logs():
- if self.get_channel(int(log["channel_id"])) is None:
+ if log.get("channel_id") is None or self.get_channel(int(log["channel_id"])) is None:
logger.debug("Unable to resolve thread with channel %s.", log["channel_id"])
log_data = await self.api.post_log(
log["channel_id"],
@@ -603,7 +626,10 @@ async def on_ready(self):
if log_data:
logger.debug("Successfully closed thread with channel %s.", log["channel_id"])
else:
- logger.debug("Failed to close thread with channel %s, skipping.", log["channel_id"])
+ logger.debug(
+ "Failed to close thread with channel %s, skipping.",
+ log["channel_id"],
+ )
other_guilds = [guild for guild in self.guilds if guild not in {self.guild, self.modmail_guild}]
if any(other_guilds):
@@ -768,6 +794,33 @@ def check_manual_blocked(self, author: discord.Member) -> bool:
logger.debug("User blocked, user %s.", author.name)
return False
+ def check_local_git(self) -> bool:
+ """
+ Checks if the bot is installed via git.
+ """
+ valid_local_git = False
+ git_folder_path = os.path.join(".git")
+
+ # Check if the .git folder exists and is a directory
+ if os.path.exists(git_folder_path) and os.path.isdir(git_folder_path):
+ required_files = ["config", "HEAD"]
+ required_dirs = ["refs", "objects"]
+
+ # Verify required files exist
+ for file in required_files:
+ if not os.path.isfile(os.path.join(git_folder_path, file)):
+ return valid_local_git
+
+ # Verify required directories exist
+ for directory in required_dirs:
+ if not os.path.isdir(os.path.join(git_folder_path, directory)):
+ return valid_local_git
+
+ # If all checks pass, set valid_local_git to True
+ valid_local_git = True
+
+ return valid_local_git
+
async def _process_blocked(self, message):
_, blocked_emoji = await self.retrieve_emoji()
if await self.is_blocked(message.author, channel=message.channel, send_message=True):
@@ -862,7 +915,8 @@ async def get_thread_cooldown(self, author: discord.Member):
@staticmethod
async def add_reaction(
- msg, reaction: typing.Union[discord.Emoji, discord.Reaction, discord.PartialEmoji, str]
+ msg,
+ reaction: typing.Union[discord.Emoji, discord.Reaction, discord.PartialEmoji, str],
) -> bool:
if reaction != "disable":
try:
@@ -872,6 +926,36 @@ async def add_reaction(
return False
return True
+ async def _queue_dm_message(self, message: discord.Message) -> None:
+ """Queue DM messages to ensure they're processed in order per user."""
+ user_id = message.author.id
+
+ if user_id not in self._message_queues:
+ self._message_queues[user_id] = asyncio.Queue()
+ # Start processing task for this user
+ self.loop.create_task(self._process_user_messages(user_id))
+
+ await self._message_queues[user_id].put(message)
+
+ async def _process_user_messages(self, user_id: int) -> None:
+ """Process messages for a specific user in order."""
+ queue = self._message_queues[user_id]
+
+ while True:
+ try:
+ # Wait for a message with timeout to clean up inactive queues
+ message = await asyncio.wait_for(queue.get(), timeout=300) # 5 minutes
+ await self.process_dm_modmail(message)
+ queue.task_done()
+ except asyncio.TimeoutError:
+ # Clean up inactive queue
+ if queue.empty():
+ self._message_queues.pop(user_id, None)
+ break
+ except Exception as e:
+ logger.error(f"Error processing message for user {user_id}: {e}", exc_info=True)
+ queue.task_done()
+
async def process_dm_modmail(self, message: discord.Message) -> None:
"""Processes messages sent to the bot."""
blocked = await self._process_blocked(message)
@@ -879,10 +963,202 @@ async def process_dm_modmail(self, message: discord.Message) -> None:
return
sent_emoji, blocked_emoji = await self.retrieve_emoji()
+ # Handle forwarded messages (Discord forwards)
+ # See: https://discord.com/developers/docs/resources/message#message-reference-content-attribution-forwards
+ # 1. Multi-forward (message_snapshots)
+ if hasattr(message, "flags") and getattr(message.flags, "has_snapshot", False):
+ if hasattr(message, "message_snapshots") and message.message_snapshots:
+ thread = await self.threads.find(recipient=message.author)
+ if thread is None:
+ delta = await self.get_thread_cooldown(message.author)
+ if delta:
+ await message.channel.send(
+ embed=discord.Embed(
+ title=self.config["cooldown_thread_title"],
+ description=self.config["cooldown_thread_response"].format(delta=delta),
+ color=self.error_color,
+ )
+ )
+ return
+ if self.config["dm_disabled"] in (DMDisabled.NEW_THREADS, DMDisabled.ALL_THREADS):
+ embed = discord.Embed(
+ title=self.config["disabled_new_thread_title"],
+ color=self.error_color,
+ description=self.config["disabled_new_thread_response"],
+ )
+ embed.set_footer(
+ text=self.config["disabled_new_thread_footer"],
+ icon_url=self.get_guild_icon(guild=message.guild, size=128),
+ )
+ logger.info(
+ "A new thread was blocked from %s due to disabled Modmail.", message.author
+ )
+ await self.add_reaction(message, blocked_emoji)
+ return await message.channel.send(embed=embed)
+ thread = await self.threads.create(message.author, message=message)
+ else:
+ if self.config["dm_disabled"] == DMDisabled.ALL_THREADS:
+ embed = discord.Embed(
+ title=self.config["disabled_current_thread_title"],
+ color=self.error_color,
+ description=self.config["disabled_current_thread_response"],
+ )
+ embed.set_footer(
+ text=self.config["disabled_current_thread_footer"],
+ icon_url=self.get_guild_icon(guild=message.guild, size=128),
+ )
+ logger.info("A message was blocked from %s due to disabled Modmail.", message.author)
+ await self.add_reaction(message, blocked_emoji)
+ return await message.channel.send(embed=embed)
+ # Extract forwarded content using utility function
+ combined_content = extract_forwarded_content(message) or "[Forwarded message with no content]"
+
+ class ForwardedMessage:
+ def __init__(self, original_message, forwarded_content):
+ self.author = original_message.author
+ self.content = forwarded_content
+ self.attachments = []
+ self.stickers = []
+ self.created_at = original_message.created_at
+ self.embeds = []
+ self.id = original_message.id
+ self.flags = original_message.flags
+ self.message_snapshots = original_message.message_snapshots
+ self.type = getattr(original_message, "type", None)
+
+ forwarded_msg = ForwardedMessage(message, combined_content)
+ await thread.send(forwarded_msg)
+ await self.add_reaction(message, sent_emoji)
+ self.dispatch("thread_reply", thread, False, message, False, False)
+ return
+ else:
+ message.content = "[Forwarded message with no content]"
+ # 2. Single-message forward (MessageType.forward)
+ elif getattr(message, "type", None) == getattr(discord.MessageType, "forward", None):
+ # Check for message.reference and its type
+ ref = getattr(message, "reference", None)
+ if ref and getattr(ref, "type", None) == getattr(discord, "MessageReferenceType", None).forward:
+ # Try to fetch the referenced message
+ ref_msg = None
+ try:
+ if ref.resolved:
+ ref_msg = ref.resolved
+ elif ref.message_id and ref.channel_id:
+ channel = self.get_channel(ref.channel_id) or (
+ await self.fetch_channel(ref.channel_id)
+ )
+ ref_msg = await channel.fetch_message(ref.message_id)
+ except Exception:
+ ref_msg = None
+ if ref_msg:
+ # Forward the referenced message as if it was sent
+ thread = await self.threads.find(recipient=message.author)
+ if thread is None:
+ delta = await self.get_thread_cooldown(message.author)
+ if delta:
+ await message.channel.send(
+ embed=discord.Embed(
+ title=self.config["cooldown_thread_title"],
+ description=self.config["cooldown_thread_response"].format(delta=delta),
+ color=self.error_color,
+ )
+ )
+ return
+ if self.config["dm_disabled"] in (DMDisabled.NEW_THREADS, DMDisabled.ALL_THREADS):
+ embed = discord.Embed(
+ title=self.config["disabled_new_thread_title"],
+ color=self.error_color,
+ description=self.config["disabled_new_thread_response"],
+ )
+ embed.set_footer(
+ text=self.config["disabled_new_thread_footer"],
+ icon_url=self.get_guild_icon(guild=message.guild, size=128),
+ )
+ logger.info(
+ "A new thread was blocked from %s due to disabled Modmail.", message.author
+ )
+ await self.add_reaction(message, blocked_emoji)
+ return await message.channel.send(embed=embed)
+ thread = await self.threads.create(message.author, message=message)
+ else:
+ if self.config["dm_disabled"] == DMDisabled.ALL_THREADS:
+ embed = discord.Embed(
+ title=self.config["disabled_current_thread_title"],
+ color=self.error_color,
+ description=self.config["disabled_current_thread_response"],
+ )
+ embed.set_footer(
+ text=self.config["disabled_current_thread_footer"],
+ icon_url=self.get_guild_icon(guild=message.guild, size=128),
+ )
+ logger.info(
+ "A message was blocked from %s due to disabled Modmail.", message.author
+ )
+ await self.add_reaction(message, blocked_emoji)
+ return await message.channel.send(embed=embed)
+
+ # Create a forwarded message wrapper to preserve forward info
+ class ForwardedMessage:
+ def __init__(self, original_message, ref_message):
+ self.author = original_message.author
+ # Use the utility function to extract content or fallback to ref message content
+ extracted_content = extract_forwarded_content(original_message)
+ self.content = (
+ extracted_content
+ or ref_message.content
+ or "[Forwarded message with no text content]"
+ )
+ self.attachments = getattr(ref_message, "attachments", [])
+ self.stickers = getattr(ref_message, "stickers", [])
+ self.created_at = original_message.created_at
+ self.embeds = getattr(ref_message, "embeds", [])
+ self.id = original_message.id
+ self.type = getattr(original_message, "type", None)
+ self.reference = original_message.reference
+
+ forwarded_msg = ForwardedMessage(message, ref_msg)
+ await thread.send(forwarded_msg)
+ await self.add_reaction(message, sent_emoji)
+ self.dispatch("thread_reply", thread, False, message, False, False)
+ return
+ else:
+ message.content = "[Forwarded message with no content]"
+
if message.type not in [discord.MessageType.default, discord.MessageType.reply]:
return
thread = await self.threads.find(recipient=message.author)
+ if thread and thread.snoozed:
+ await thread.restore_from_snooze()
+ self.threads.cache[thread.id] = thread
+ # No need to re-fetch the thread - it's already restored and cached properly
+
+ # If the previous thread was closed with delete_channel=True the channel object
+ # stored on the thread will now be invalid (deleted). In some rare race cases
+ # the thread can still be returned from the cache (or reconstructed) while the
+ # channel lookup returns None, causing downstream relay attempts to raise
+ # discord.NotFound ("Channel not found when trying to send message."). Treat
+ # this situation as "no active thread" so the user's new DM starts a fresh
+ # thread instead of silently failing.
+ try:
+ if (
+ thread
+ and thread.channel
+ and isinstance(thread.channel, discord.TextChannel)
+ and self.get_channel(getattr(thread.channel, "id", None)) is None
+ ):
+ logger.info(
+ "Stale thread detected for %s (channel deleted). Purging cache entry and creating new thread.",
+ message.author,
+ )
+ # Best-effort removal; ignore if already gone.
+ self.threads.cache.pop(thread.id, None)
+ thread = None
+ except Exception:
+ # If any attribute access fails, fall back to treating it as closed.
+ self.threads.cache.pop(getattr(thread, "id", None), None)
+ thread = None
+
if thread is None:
delta = await self.get_thread_cooldown(message.author)
if delta:
@@ -895,7 +1171,10 @@ async def process_dm_modmail(self, message: discord.Message) -> None:
)
return
- if self.config["dm_disabled"] in (DMDisabled.NEW_THREADS, DMDisabled.ALL_THREADS):
+ if self.config["dm_disabled"] in (
+ DMDisabled.NEW_THREADS,
+ DMDisabled.ALL_THREADS,
+ ):
embed = discord.Embed(
title=self.config["disabled_new_thread_title"],
color=self.error_color,
@@ -905,11 +1184,17 @@ async def process_dm_modmail(self, message: discord.Message) -> None:
text=self.config["disabled_new_thread_footer"],
icon_url=self.get_guild_icon(guild=message.guild, size=128),
)
- logger.info("A new thread was blocked from %s due to disabled Modmail.", message.author)
+ logger.info(
+ "A new thread was blocked from %s due to disabled Modmail.",
+ message.author,
+ )
await self.add_reaction(message, blocked_emoji)
return await message.channel.send(embed=embed)
thread = await self.threads.create(message.author, message=message)
+ # If thread menu is enabled, thread creation is deferred until user selects an option.
+ if getattr(thread, "_pending_menu", False):
+ return
else:
if self.config["dm_disabled"] == DMDisabled.ALL_THREADS:
embed = discord.Embed(
@@ -921,7 +1206,10 @@ async def process_dm_modmail(self, message: discord.Message) -> None:
text=self.config["disabled_current_thread_footer"],
icon_url=self.get_guild_icon(guild=message.guild, size=128),
)
- logger.info("A message was blocked from %s due to disabled Modmail.", message.author)
+ logger.info(
+ "A message was blocked from %s due to disabled Modmail.",
+ message.author,
+ )
await self.add_reaction(message, blocked_emoji)
return await message.channel.send(embed=embed)
@@ -931,6 +1219,49 @@ async def process_dm_modmail(self, message: discord.Message) -> None:
except Exception:
logger.error("Failed to send message:", exc_info=True)
await self.add_reaction(message, blocked_emoji)
+
+ try:
+ # Re-check channel existence
+ if thread and thread.channel and isinstance(thread.channel, discord.TextChannel):
+ if self.get_channel(thread.channel.id) is None:
+ logger.info(
+ "Relay failed due to deleted channel for %s; creating new thread.",
+ message.author,
+ )
+ self.threads.cache.pop(thread.id, None)
+ new_thread = await self.threads.create(message.author, message=message)
+ if not getattr(new_thread, "_pending_menu", False) and not new_thread.cancelled:
+ try:
+ await new_thread.send(message)
+ except Exception:
+ logger.error(
+ "Failed to relay message after creating new thread:",
+ exc_info=True,
+ )
+ else:
+ for user in new_thread.recipients:
+ if user != message.author:
+ try:
+ await new_thread.send(message, user)
+ except Exception:
+ logger.error(
+ "Failed to send message to additional recipient:",
+ exc_info=True,
+ )
+ await self.add_reaction(message, sent_emoji)
+ self.dispatch(
+ "thread_reply",
+ new_thread,
+ False,
+ message,
+ False,
+ False,
+ )
+ except Exception:
+ logger.warning(
+ "Unexpected failure in DM relay/new-thread follow-up block.",
+ exc_info=True,
+ )
else:
for user in thread.recipients:
# send to all other recipients
@@ -1043,7 +1374,12 @@ async def trigger_auto_triggers(self, message, channel, *, cls=commands.Context)
if trigger:
invoker = re.search(trigger, message.content).group(0)
else:
- trigger = next(filter(lambda x: x.lower() in message.content.lower(), self.auto_triggers.keys()))
+ trigger = next(
+ filter(
+ lambda x: x.lower() in message.content.lower(),
+ self.auto_triggers.keys(),
+ )
+ )
if trigger:
invoker = trigger.lower()
@@ -1156,6 +1492,19 @@ async def on_message(self, message):
content = ""
await self.mention_channel.send(content=content, embed=em)
+ # --- MODERATOR-ONLY MESSAGE LOGGING ---
+ # If a moderator sends a message directly in a thread channel (not via modmail command), log it
+ if not message.author.bot and not isinstance(message.channel, discord.DMChannel):
+ thread = await self.threads.find(channel=message.channel)
+ if thread is not None:
+ ctxs = await self.get_contexts(message)
+ is_command = any(ctx.command for ctx in ctxs)
+ if not is_command:
+ # Only log if not a command
+ perms = message.channel.permissions_for(message.author)
+ if perms.manage_messages or perms.administrator:
+ await self.api.append_log(message, type_="internal")
+
await self.process_commands(message)
async def process_commands(self, message):
@@ -1163,7 +1512,7 @@ async def process_commands(self, message):
return
if isinstance(message.channel, discord.DMChannel):
- return await self.process_dm_modmail(message)
+ return await self._queue_dm_message(message)
ctxs = await self.get_contexts(message)
for ctx in ctxs:
@@ -1175,11 +1524,44 @@ async def process_commands(self, message):
)
checks.has_permissions(PermissionLevel.INVALID)(ctx.command)
+ # Check if thread is unsnoozing and queue command if so
+ thread = await self.threads.find(channel=ctx.channel)
+ if thread and thread._unsnoozing:
+ queued = await thread.queue_command(ctx, ctx.command)
+ if queued:
+ # Send a brief acknowledgment that command is queued
+ try:
+ await ctx.message.add_reaction("⏳")
+ except Exception as e:
+ logger.warning("Failed to add queued-reaction: %s", e)
+ continue
+
await self.invoke(ctx)
continue
thread = await self.threads.find(channel=ctx.channel)
if thread is not None:
+ # If thread is snoozed (moved), auto-unsnooze when a mod sends a message directly in channel
+ behavior = (self.config.get("snooze_behavior") or "delete").lower()
+ if thread.snoozed and behavior == "move":
+ if not thread.snooze_data:
+ try:
+ log_entry = await self.api.logs.find_one(
+ {"recipient.id": str(thread.id), "snoozed": True}
+ )
+ if log_entry:
+ thread.snooze_data = log_entry.get("snooze_data")
+ except Exception:
+ logger.debug(
+ "Failed to add queued command reaction (⏳).",
+ exc_info=True,
+ )
+ try:
+ await thread.restore_from_snooze()
+ # refresh local cache
+ self.threads.cache[thread.id] = thread
+ except Exception as e:
+ logger.warning("Auto-unsnooze on direct message failed: %s", e)
anonymous = False
plain = False
if self.config.get("anon_reply_without_command"):
@@ -1192,9 +1574,9 @@ async def process_commands(self, message):
or self.config.get("anon_reply_without_command")
or self.config.get("plain_reply_without_command")
):
- await thread.reply(message, anonymous=anonymous, plain=plain)
- else:
- await self.api.append_log(message, type_="internal")
+ # When replying without a command in a thread channel, use the raw content
+ # from the sent message as reply text while still preserving attachments.
+ await thread.reply(message, message.content, anonymous=anonymous, plain=plain)
elif ctx.invoked_with:
exc = commands.CommandNotFound('Command "{}" is not found'.format(ctx.invoked_with))
self.dispatch("command_error", ctx, exc)
@@ -1212,7 +1594,13 @@ async def on_typing(self, channel, user, _):
thread = await self.threads.find(recipient=user)
if thread:
- await thread.channel.typing()
+ try:
+ await thread.channel.typing()
+ except Exception:
+ logger.debug(
+ "Failed to trigger typing indicator in recipient DM.",
+ exc_info=True,
+ )
else:
if not self.config.get("mod_typing"):
return
@@ -1222,7 +1610,14 @@ async def on_typing(self, channel, user, _):
for user in thread.recipients:
if await self.is_blocked(user):
continue
- await user.typing()
+ try:
+ await user.typing()
+ except Exception:
+ logger.debug(
+ "Failed to trigger typing for recipient %s.",
+ getattr(user, "id", "?"),
+ exc_info=True,
+ )
async def handle_reaction_events(self, payload):
user = self.get_user(payload.user_id)
@@ -1295,7 +1690,7 @@ async def handle_reaction_events(self, payload):
logger.warning("Failed to find linked message for reactions: %s", e)
return
- if self.config["transfer_reactions"] and linked_messages is not [None]:
+ if self.config["transfer_reactions"] and linked_messages != [None]:
if payload.event_type == "REACTION_ADD":
for msg in linked_messages:
await self.add_reaction(msg, reaction)
@@ -1328,7 +1723,10 @@ async def handle_react_to_contact(self, payload):
await message.remove_reaction(payload.emoji, member)
await message.add_reaction(emoji_fmt) # bot adds as well
- if self.config["dm_disabled"] in (DMDisabled.NEW_THREADS, DMDisabled.ALL_THREADS):
+ if self.config["dm_disabled"] in (
+ DMDisabled.NEW_THREADS,
+ DMDisabled.ALL_THREADS,
+ ):
embed = discord.Embed(
title=self.config["disabled_new_thread_title"],
color=self.error_color,
@@ -1344,6 +1742,19 @@ async def handle_react_to_contact(self, payload):
)
return await member.send(embed=embed)
+ # Check if user has a snoozed thread
+ existing_thread = await self.threads.find(recipient=member)
+ if existing_thread and existing_thread.snoozed:
+ # Unsnooze the thread
+ await existing_thread.restore_from_snooze()
+ self.threads.cache[existing_thread.id] = existing_thread
+ # Send notification to the thread channel
+ if existing_thread.channel:
+ await existing_thread.channel.send(
+ f"ℹ️ {member.mention} reacted to contact and their snoozed thread has been unsnoozed."
+ )
+ return
+
ctx = await self.get_context(message)
await ctx.invoke(self.get_command("contact"), users=[member], manual_trigger=False)
@@ -1377,12 +1788,30 @@ async def on_guild_channel_delete(self, channel):
await self.config.update()
return
- audit_logs = self.modmail_guild.audit_logs(limit=10, action=discord.AuditLogAction.channel_delete)
- found_entry = False
- async for entry in audit_logs:
- if int(entry.target.id) == channel.id:
- found_entry = True
- break
+ # Attempt to attribute channel deletion to a moderator via audit logs.
+ # This requires the "View Audit Log" permission; if missing, skip silently.
+ if not self.modmail_guild.me.guild_permissions.view_audit_log:
+ logger.debug(
+ "Skipping audit log lookup for deleted channel %d: missing view_audit_log permission.",
+ channel.id,
+ )
+ return
+
+ try:
+ audit_logs = self.modmail_guild.audit_logs(limit=10, action=discord.AuditLogAction.channel_delete)
+ found_entry = False
+ async for entry in audit_logs:
+ if int(entry.target.id) == channel.id:
+ found_entry = True
+ break
+ except discord.Forbidden:
+ logger.debug(
+ "Forbidden when fetching audit logs for deleted channel %d (missing permission).", channel.id
+ )
+ return
+ except discord.HTTPException as e:
+ logger.debug("HTTPException when fetching audit logs for deleted channel %d: %s", channel.id, e)
+ return
if not found_entry:
logger.debug("Cannot find the audit log entry for channel delete of %d.", channel.id)
@@ -1479,7 +1908,14 @@ async def on_message_delete(self, message):
await thread.delete_message(message, note=False)
embed = discord.Embed(description="Successfully deleted message.", color=self.main_color)
except ValueError as e:
- if str(e) not in {"DM message not found.", "Malformed thread message."}:
+ # Treat common non-fatal cases as benign: relay counterpart not present, note embeds, etc.
+ if str(e) not in {
+ "DM message not found.",
+ "Malformed thread message.",
+ "Thread message not found.",
+ "Linked DM message not found.",
+ "Thread message is an internal message, not a note.",
+ }:
logger.debug("Failed to find linked message to delete: %s", e)
embed = discord.Embed(description="Failed to delete message.", color=self.error_color)
else:
@@ -1518,7 +1954,11 @@ async def on_error(self, event_method, *args, **kwargs):
logger.error("Unexpected exception:", exc_info=sys.exc_info())
async def on_command_error(
- self, context: commands.Context, exception: Exception, *, unhandled_by_cog: bool = False
+ self,
+ context: commands.Context,
+ exception: Exception,
+ *,
+ unhandled_by_cog: bool = False,
) -> None:
if not unhandled_by_cog:
command = context.command
@@ -1529,7 +1969,13 @@ async def on_command_error(
return
if isinstance(exception, (commands.BadArgument, commands.BadUnionArgument)):
- await context.typing()
+ try:
+ await context.typing()
+ except Exception:
+ logger.debug(
+ "Failed to start typing context for command error feedback.",
+ exc_info=True,
+ )
await context.send(embed=discord.Embed(color=self.error_color, description=str(exception)))
elif isinstance(exception, commands.CommandNotFound):
logger.warning("CommandNotFound: %s", exception)
@@ -1560,7 +2006,10 @@ async def on_command_error(
)
logger.warning("CheckFailure: %s", exception)
elif isinstance(exception, commands.DisabledCommand):
- logger.info("DisabledCommand: %s is trying to run eval but it's disabled", context.author.name)
+ logger.info(
+ "DisabledCommand: %s is trying to run eval but it's disabled",
+ context.author.name,
+ )
else:
logger.error("Unexpected exception:", exc_info=exception)
@@ -1592,7 +2041,13 @@ async def post_metadata(self):
}
)
else:
- data.update({"owner_name": info.owner.name, "owner_id": info.owner.id, "team": False})
+ data.update(
+ {
+ "owner_name": info.owner.name,
+ "owner_id": info.owner.id,
+ "team": False,
+ }
+ )
async with self.session.post("https://api.modmail.dev/metadata", json=data):
logger.debug("Uploading metadata to Modmail server.")
@@ -1645,7 +2100,7 @@ async def autoupdate(self):
user = data["user"]
embed.add_field(
name="Merge Commit",
- value=f"[`{short_sha}`]({html_url}) " f"{message} - {user['username']}",
+ value=f"[`{short_sha}`]({html_url}) {message} - {user['username']}",
)
embed.set_author(
name=user["username"] + " - Updating Bot",
@@ -1692,7 +2147,10 @@ async def autoupdate(self):
logger.info("Bot has been updated.")
channel = self.update_channel
- if self.hosting_method in (HostingMethod.PM2, HostingMethod.SYSTEMD):
+ if self.hosting_method in (
+ HostingMethod.PM2,
+ HostingMethod.SYSTEMD,
+ ):
embed = discord.Embed(title="Bot has been updated", color=self.main_color)
embed.set_footer(
text=f"Updating Modmail v{self.version} " f"-> v{latest.version} {message}"
@@ -1731,6 +2189,12 @@ async def before_autoupdate(self):
self.autoupdate.cancel()
return
+ if not self.check_local_git():
+ logger.warning("Bot not installed via git.")
+ logger.warning("Autoupdates disabled.")
+ self.autoupdate.cancel()
+ return
+
@tasks.loop(hours=1, reconnect=False)
async def log_expiry(self):
log_expire_after = self.config.get("log_expiration")
@@ -1820,7 +2284,7 @@ def main():
sys.exit(0)
# check discord version
- discord_version = "2.3.2"
+ discord_version = "2.6.3"
if discord.__version__ != discord_version:
logger.error(
"Dependencies are not updated, run pipenv install. discord.py version expected %s, received %s",
diff --git a/cogs/modmail.py b/cogs/modmail.py
index e2a0039384..cbab46bcb0 100644
--- a/cogs/modmail.py
+++ b/cogs/modmail.py
@@ -1,11 +1,13 @@
import asyncio
import re
-from datetime import datetime, timezone
+from datetime import datetime, timezone, timedelta
from itertools import zip_longest
from typing import Optional, Union, List, Tuple, Literal
+import logging
import discord
from discord.ext import commands
+from discord.ext import tasks
from discord.ext.commands.view import StringView
from discord.ext.commands.cooldowns import BucketType
from discord.role import Role
@@ -28,6 +30,87 @@ class Modmail(commands.Cog):
def __init__(self, bot):
self.bot = bot
+ self._snoozed_cache = []
+ self._auto_unsnooze_task = self.bot.loop.create_task(self.auto_unsnooze_task())
+
+ async def auto_unsnooze_task(self):
+ await self.bot.wait_until_ready()
+ last_db_query = 0
+ while not self.bot.is_closed():
+ now = datetime.now(timezone.utc)
+ try:
+ # Query DB every 2 minutes
+ if (now.timestamp() - last_db_query) > 120:
+ snoozed_threads = await self.bot.api.logs.find(
+ {"snooze_until": {"$gte": now.isoformat()}}
+ ).to_list(None)
+ self._snoozed_cache = snoozed_threads or []
+ last_db_query = now.timestamp()
+ # Check cache every 10 seconds
+ to_unsnooze = []
+ for thread_data in list(self._snoozed_cache):
+ snooze_until = thread_data.get("snooze_until")
+ recipient = thread_data.get("recipient")
+ if not recipient or not recipient.get("id"):
+ continue
+ thread_id = int(recipient.get("id"))
+ if snooze_until:
+ try:
+ dt = parser.isoparse(snooze_until)
+ except Exception:
+ continue
+ if now >= dt:
+ to_unsnooze.append(thread_data)
+ for thread_data in to_unsnooze:
+ recipient = thread_data.get("recipient")
+ if not recipient or not recipient.get("id"):
+ continue
+ thread_id = int(recipient.get("id"))
+ thread = self.bot.threads.cache.get(thread_id) or await self.bot.threads.find(
+ id=thread_id
+ )
+ if thread and thread.snoozed:
+ await thread.restore_from_snooze()
+ logging.info(f"[AUTO-UNSNOOZE] Thread {thread_id} auto-unsnoozed.")
+ try:
+ channel = thread.channel
+ if channel:
+ await channel.send("⏰ This thread has been automatically unsnoozed.")
+ except Exception as e:
+ logger.info(
+ "Failed to notify channel after auto-unsnooze: %s",
+ e,
+ )
+ self._snoozed_cache.remove(thread_data)
+ except Exception as e:
+ logging.error(f"Error in auto_unsnooze_task: {e}")
+ await asyncio.sleep(10)
+
+ def _resolve_user(self, user_str):
+ """Helper to resolve a user from mention, ID, or username."""
+ import re
+
+ if not user_str:
+ return None
+ if user_str.isdigit():
+ return int(user_str)
+ match = re.match(r"<@!?(\d+)>", user_str)
+ if match:
+ return int(match.group(1))
+ return None
+
+ def _resolve_user(self, user_str):
+ """Helper to resolve a user from mention, ID, or username."""
+ import re
+
+ if not user_str:
+ return None
+ if user_str.isdigit():
+ return int(user_str)
+ match = re.match(r"<@!?(\d+)>", user_str)
+ if match:
+ return int(match.group(1))
+ return None
@commands.command()
@trigger_typing
@@ -94,7 +177,7 @@ async def setup(self, ctx):
name="Thanks for using our bot!",
value="If you like what you see, consider giving the "
"[repo a star](https://github.com/modmail-dev/modmail) :star: and if you are "
- "feeling extra generous, buy us coffee on [Patreon](https://patreon.com/kyber) :heart:!",
+ "feeling extra generous, buy us coffee on [Buy Me A Coffee](https://buymeacoffee.com/modmaildev) :heart:!",
)
embed.set_footer(text=f'Type "{self.bot.prefix}help" for a complete list of commands.')
@@ -143,6 +226,21 @@ async def snippet(self, ctx, *, name: str.lower = None):
"""
if name is not None:
+ if name == "compact":
+ embeds = []
+
+ for i, names in enumerate(zip_longest(*(iter(sorted(self.bot.snippets)),) * 15)):
+ description = format_description(i, names)
+ embed = discord.Embed(color=self.bot.main_color, description=description)
+ embed.set_author(
+ name="Snippets", icon_url=self.bot.get_guild_icon(guild=ctx.guild, size=128)
+ )
+ embeds.append(embed)
+
+ session = EmbedPaginatorSession(ctx, *embeds)
+ await session.run()
+ return
+
snippet_name = self.bot._resolve_snippet(name)
if snippet_name is None:
@@ -150,25 +248,32 @@ async def snippet(self, ctx, *, name: str.lower = None):
else:
val = self.bot.snippets[snippet_name]
embed = discord.Embed(
- title=f'Snippet - "{snippet_name}":', description=val, color=self.bot.main_color
+ title=f'Snippet - "{snippet_name}":',
+ description=val,
+ color=self.bot.main_color,
)
return await ctx.send(embed=embed)
if not self.bot.snippets:
embed = discord.Embed(
- color=self.bot.error_color, description="You dont have any snippets at the moment."
+ color=self.bot.error_color,
+ description="You dont have any snippets at the moment.",
)
embed.set_footer(text=f'Check "{self.bot.prefix}help snippet add" to add a snippet.')
- embed.set_author(name="Snippets", icon_url=self.bot.get_guild_icon(guild=ctx.guild, size=128))
+ embed.set_author(
+ name="Snippets",
+ icon_url=self.bot.get_guild_icon(guild=ctx.guild, size=128),
+ )
return await ctx.send(embed=embed)
- embeds = []
-
- for i, names in enumerate(zip_longest(*(iter(sorted(self.bot.snippets)),) * 15)):
- description = format_description(i, names)
- embed = discord.Embed(color=self.bot.main_color, description=description)
+ embeds = [discord.Embed(color=self.bot.main_color) for _ in range((len(self.bot.snippets) // 10) + 1)]
+ for embed in embeds:
embed.set_author(name="Snippets", icon_url=self.bot.get_guild_icon(guild=ctx.guild, size=128))
- embeds.append(embed)
+
+ for i, snippet in enumerate(sorted(self.bot.snippets.items())):
+ embeds[i // 10].add_field(
+ name=snippet[0], value=return_or_truncate(snippet[1], 350), inline=False
+ )
session = EmbedPaginatorSession(ctx, *embeds)
await session.run()
@@ -375,6 +480,61 @@ async def snippet_edit(self, ctx, name: str.lower, *, value):
embed = create_not_found_embed(name, self.bot.snippets.keys(), "Snippet")
await ctx.send(embed=embed)
+ @snippet.command(name="rename")
+ @checks.has_permissions(PermissionLevel.SUPPORTER)
+ async def snippet_rename(self, ctx, name: str.lower, *, value):
+ """
+ Rename a snippet.
+
+ To rename a multi-word snippet name, use quotes: ```
+ {prefix}snippet rename "two word" this is a new two word snippet.
+ ```
+ """
+ if name in self.bot.snippets:
+ if self.bot.get_command(value):
+ embed = discord.Embed(
+ title="Error",
+ color=self.bot.error_color,
+ description=f"A command with the same name already exists: `{value}`.",
+ )
+ return await ctx.send(embed=embed)
+ elif value in self.bot.snippets:
+ embed = discord.Embed(
+ title="Error",
+ color=self.bot.error_color,
+ description=f"Snippet `{value}` already exists.",
+ )
+ return await ctx.send(embed=embed)
+
+ if value in self.bot.aliases:
+ embed = discord.Embed(
+ title="Error",
+ color=self.bot.error_color,
+ description=f"An alias that shares the same name exists: `{value}`.",
+ )
+ return await ctx.send(embed=embed)
+
+ if len(value) > 120:
+ embed = discord.Embed(
+ title="Error",
+ color=self.bot.error_color,
+ description="Snippet names cannot be longer than 120 characters.",
+ )
+ return await ctx.send(embed=embed)
+ old_snippet_value = self.bot.snippets[name]
+ self.bot.snippets.pop(name)
+ self.bot.snippets[value] = old_snippet_value
+ await self.bot.config.update()
+
+ embed = discord.Embed(
+ title="Renamed snippet",
+ color=self.bot.main_color,
+ description=f'`{name}` has been renamed to "{value}".',
+ )
+ else:
+ embed = create_not_found_embed(name, self.bot.snippets.keys(), "Snippet")
+ await ctx.send(embed=embed)
+
@commands.command(usage=" [options]")
@checks.has_permissions(PermissionLevel.MODERATOR)
@checks.thread_only()
@@ -418,7 +578,10 @@ async def move(self, ctx, *, arguments):
silent = any(word in silent_words for word in options.split())
await thread.channel.move(
- category=category, end=True, sync_permissions=True, reason=f"{ctx.author} moved this thread."
+ category=category,
+ end=True,
+ sync_permissions=True,
+ reason=f"{ctx.author} moved this thread.",
)
if self.bot.config["thread_move_notify"] and not silent:
@@ -441,21 +604,24 @@ async def move(self, ctx, *, arguments):
await self.bot.add_reaction(ctx.message, sent_emoji)
async def send_scheduled_close_message(self, ctx, after, silent=False):
- human_delta = human_timedelta(after.dt)
+ """Send a scheduled close notice only to the staff thread channel.
+ Uses Discord relative timestamp formatting for better UX.
+ """
+ ts = int((after.dt if after.dt.tzinfo else after.dt.replace(tzinfo=timezone.utc)).timestamp())
embed = discord.Embed(
title="Scheduled close",
- description=f"This thread will{' silently' if silent else ''} close in {human_delta}.",
+ description=f"This thread will{' silently' if silent else ''} close .",
color=self.bot.error_color,
)
-
if after.arg and not silent:
embed.add_field(name="Message", value=after.arg)
-
embed.set_footer(text="Closing will be cancelled if a thread message is sent.")
embed.timestamp = after.dt
- await ctx.send(embed=embed)
+ thread = getattr(ctx, "thread", None)
+ if thread and ctx.channel == thread.channel:
+ await thread.channel.send(embed=embed)
@commands.command(usage="[after] [close message]")
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -496,7 +662,8 @@ async def close(
if thread.close_task is not None or thread.auto_close_task is not None:
await thread.cancel_closure(all=True)
embed = discord.Embed(
- color=self.bot.error_color, description="Scheduled close has been cancelled."
+ color=self.bot.error_color,
+ description="Scheduled close has been cancelled.",
)
else:
embed = discord.Embed(
@@ -595,7 +762,8 @@ async def unnotify(self, ctx, *, user_or_role: Union[discord.Role, User, str.low
mentions.remove(mention)
await self.bot.config.update()
embed = discord.Embed(
- color=self.bot.main_color, description=f"{mention} will no longer be notified."
+ color=self.bot.main_color,
+ description=f"{mention} will no longer be notified.",
)
return await ctx.send(embed=embed)
@@ -706,7 +874,8 @@ async def msglink(self, ctx, message_id: int):
continue
if not found:
embed = discord.Embed(
- color=self.bot.error_color, description="Message not found or no longer exists."
+ color=self.bot.error_color,
+ description="Message not found or no longer exists.",
)
else:
embed = discord.Embed(color=self.bot.main_color, description=message.jump_url)
@@ -849,7 +1018,10 @@ async def adduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, str
)
if self.bot.config["show_timestamp"]:
em.timestamp = discord.utils.utcnow()
- em.set_footer(text=str(ctx.author), icon_url=ctx.author.display_avatar.url)
+ em.set_footer(
+ text=str(ctx.author),
+ icon_url=ctx.author.display_avatar.url if ctx.author.display_avatar else None,
+ )
for u in users:
to_exec.append(u.send(embed=em))
@@ -865,7 +1037,9 @@ async def adduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, str
)
if self.bot.config["show_timestamp"]:
em.timestamp = discord.utils.utcnow()
- em.set_footer(text=f"{users[0]}", icon_url=users[0].display_avatar.url)
+ em.set_footer(
+ text=f"{users[0]}", icon_url=users[0].display_avatar.url if users[0].display_avatar else None
+ )
for i in ctx.thread.recipients:
if i not in users:
@@ -933,7 +1107,8 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role,
to_exec = []
if not silent:
description = self.bot.formatter.format(
- self.bot.config["private_removed_from_group_response"], moderator=ctx.author
+ self.bot.config["private_removed_from_group_response"],
+ moderator=ctx.author,
)
em = discord.Embed(
title=self.bot.config["private_removed_from_group_title"],
@@ -942,7 +1117,10 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role,
)
if self.bot.config["show_timestamp"]:
em.timestamp = discord.utils.utcnow()
- em.set_footer(text=str(ctx.author), icon_url=ctx.author.display_avatar.url)
+ em.set_footer(
+ text=str(ctx.author),
+ icon_url=ctx.author.display_avatar.url if ctx.author.display_avatar else None,
+ )
for u in users:
to_exec.append(u.send(embed=em))
@@ -958,7 +1136,9 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role,
)
if self.bot.config["show_timestamp"]:
em.timestamp = discord.utils.utcnow()
- em.set_footer(text=f"{users[0]}", icon_url=users[0].display_avatar.url)
+ em.set_footer(
+ text=f"{users[0]}", icon_url=users[0].display_avatar.url if users[0].display_avatar else None
+ )
for i in ctx.thread.recipients:
if i not in users:
@@ -1032,11 +1212,11 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role,
tag = str(get_top_role(ctx.author, self.bot.config["use_hoisted_top_role"]))
name = self.bot.config["anon_username"]
if name is None:
- name = tag
+ name = "Anonymous"
avatar_url = self.bot.config["anon_avatar_url"]
if avatar_url is None:
avatar_url = self.bot.get_guild_icon(guild=ctx.guild, size=128)
- em.set_footer(text=name, icon_url=avatar_url)
+ em.set_footer(text=name, icon_url=avatar_url if avatar_url else None)
for u in users:
to_exec.append(u.send(embed=em))
@@ -1052,7 +1232,9 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role,
)
if self.bot.config["show_timestamp"]:
em.timestamp = discord.utils.utcnow()
- em.set_footer(text=f"{users[0]}", icon_url=users[0].display_avatar.url)
+ em.set_footer(
+ text=f"{users[0]}", icon_url=users[0].display_avatar.url if users[0].display_avatar else None
+ )
for i in ctx.thread.recipients:
if i not in users:
@@ -1121,11 +1303,11 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro
tag = str(get_top_role(ctx.author, self.bot.config["use_hoisted_top_role"]))
name = self.bot.config["anon_username"]
if name is None:
- name = tag
+ name = "Anonymous"
avatar_url = self.bot.config["anon_avatar_url"]
if avatar_url is None:
avatar_url = self.bot.get_guild_icon(guild=ctx.guild, size=128)
- em.set_footer(text=name, icon_url=avatar_url)
+ em.set_footer(text=name, icon_url=avatar_url if avatar_url else None)
for u in users:
to_exec.append(u.send(embed=em))
@@ -1141,7 +1323,9 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro
)
if self.bot.config["show_timestamp"]:
em.timestamp = discord.utils.utcnow()
- em.set_footer(text=f"{users[0]}", icon_url=users[0].display_avatar.url)
+ em.set_footer(
+ text=f"{users[0]}", icon_url=users[0].display_avatar.url if users[0].display_avatar else None
+ )
for i in ctx.thread.recipients:
if i not in users:
@@ -1165,7 +1349,8 @@ async def logs(self, ctx, *, user: User = None):
`user` may be a user ID, mention, or name.
"""
- await ctx.typing()
+ async with safe_typing(ctx):
+ pass
if not user:
thread = ctx.thread
@@ -1297,7 +1482,8 @@ async def logs_search(self, ctx, limit: Optional[int] = None, *, query):
Provide a `limit` to specify the maximum number of logs the bot should find.
"""
- await ctx.typing()
+ async with safe_typing(ctx):
+ pass
entries = await self.bot.api.search_by_text(query, limit)
@@ -1324,10 +1510,10 @@ async def reply(self, ctx, *, msg: str = ""):
automatically embedding image URLs.
"""
+ # Ensure logs record only the reply text, not the command.
ctx.message.content = msg
-
- async with ctx.typing():
- await ctx.thread.reply(ctx.message)
+ async with safe_typing(ctx):
+ await ctx.thread.reply(ctx.message, msg)
@commands.command(aliases=["formatreply"])
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -1345,11 +1531,15 @@ async def freply(self, ctx, *, msg: str = ""):
automatically embedding image URLs.
"""
msg = self.bot.formatter.format(
- msg, channel=ctx.channel, recipient=ctx.thread.recipient, author=ctx.message.author
+ msg,
+ channel=ctx.channel,
+ recipient=ctx.thread.recipient,
+ author=ctx.message.author,
)
+ # Ensure logs record only the reply text, not the command.
ctx.message.content = msg
- async with ctx.typing():
- await ctx.thread.reply(ctx.message)
+ async with safe_typing(ctx):
+ await ctx.thread.reply(ctx.message, msg)
@commands.command(aliases=["formatanonreply"])
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -1367,11 +1557,15 @@ async def fareply(self, ctx, *, msg: str = ""):
automatically embedding image URLs.
"""
msg = self.bot.formatter.format(
- msg, channel=ctx.channel, recipient=ctx.thread.recipient, author=ctx.message.author
+ msg,
+ channel=ctx.channel,
+ recipient=ctx.thread.recipient,
+ author=ctx.message.author,
)
+ # Ensure logs record only the reply text, not the command.
ctx.message.content = msg
- async with ctx.typing():
- await ctx.thread.reply(ctx.message, anonymous=True)
+ async with safe_typing(ctx):
+ await ctx.thread.reply(ctx.message, msg, anonymous=True)
@commands.command(aliases=["formatplainreply"])
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -1389,11 +1583,15 @@ async def fpreply(self, ctx, *, msg: str = ""):
automatically embedding image URLs.
"""
msg = self.bot.formatter.format(
- msg, channel=ctx.channel, recipient=ctx.thread.recipient, author=ctx.message.author
+ msg,
+ channel=ctx.channel,
+ recipient=ctx.thread.recipient,
+ author=ctx.message.author,
)
+ # Ensure logs record only the reply text, not the command.
ctx.message.content = msg
- async with ctx.typing():
- await ctx.thread.reply(ctx.message, plain=True)
+ async with safe_typing(ctx):
+ await ctx.thread.reply(ctx.message, msg, plain=True)
@commands.command(aliases=["formatplainanonreply"])
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -1411,11 +1609,15 @@ async def fpareply(self, ctx, *, msg: str = ""):
automatically embedding image URLs.
"""
msg = self.bot.formatter.format(
- msg, channel=ctx.channel, recipient=ctx.thread.recipient, author=ctx.message.author
+ msg,
+ channel=ctx.channel,
+ recipient=ctx.thread.recipient,
+ author=ctx.message.author,
)
+ # Ensure logs record only the reply text, not the command.
ctx.message.content = msg
- async with ctx.typing():
- await ctx.thread.reply(ctx.message, anonymous=True, plain=True)
+ async with safe_typing(ctx):
+ await ctx.thread.reply(ctx.message, msg, anonymous=True, plain=True)
@commands.command(aliases=["anonreply", "anonymousreply"])
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -1430,9 +1632,10 @@ async def areply(self, ctx, *, msg: str = ""):
Edit the `anon_username`, `anon_avatar_url`
and `anon_tag` config variables to do so.
"""
+ # Ensure logs record only the reply text, not the command.
ctx.message.content = msg
- async with ctx.typing():
- await ctx.thread.reply(ctx.message, anonymous=True)
+ async with safe_typing(ctx):
+ await ctx.thread.reply(ctx.message, msg, anonymous=True)
@commands.command(aliases=["plainreply"])
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -1444,9 +1647,10 @@ async def preply(self, ctx, *, msg: str = ""):
Supports attachments and images as well as
automatically embedding image URLs.
"""
+ # Ensure logs record only the reply text, not the command.
ctx.message.content = msg
- async with ctx.typing():
- await ctx.thread.reply(ctx.message, plain=True)
+ async with safe_typing(ctx):
+ await ctx.thread.reply(ctx.message, msg, plain=True)
@commands.command(aliases=["plainanonreply", "plainanonymousreply"])
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -1458,9 +1662,10 @@ async def pareply(self, ctx, *, msg: str = ""):
Supports attachments and images as well as
automatically embedding image URLs.
"""
+ # Ensure logs record only the reply text, not the command.
ctx.message.content = msg
- async with ctx.typing():
- await ctx.thread.reply(ctx.message, anonymous=True, plain=True)
+ async with safe_typing(ctx):
+ await ctx.thread.reply(ctx.message, msg, anonymous=True, plain=True)
@commands.group(invoke_without_command=True)
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -1472,9 +1677,16 @@ async def note(self, ctx, *, msg: str = ""):
Useful for noting context.
"""
ctx.message.content = msg
- async with ctx.typing():
+ async with safe_typing(ctx):
msg = await ctx.thread.note(ctx.message)
await msg.pin()
+ # Acknowledge and clean up the invoking command message
+ sent_emoji, _ = await self.bot.retrieve_emoji()
+ await self.bot.add_reaction(ctx.message, sent_emoji)
+ try:
+ await ctx.message.delete(delay=3)
+ except (discord.Forbidden, discord.NotFound):
+ pass
@note.command(name="persistent", aliases=["persist"])
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -1484,10 +1696,17 @@ async def note_persistent(self, ctx, *, msg: str = ""):
Take a persistent note about the current user.
"""
ctx.message.content = msg
- async with ctx.typing():
+ async with safe_typing(ctx):
msg = await ctx.thread.note(ctx.message, persistent=True)
await msg.pin()
await self.bot.api.create_note(recipient=ctx.thread.recipient, message=ctx.message, message_id=msg.id)
+ # Acknowledge and clean up the invoking command message
+ sent_emoji, _ = await self.bot.retrieve_emoji()
+ await self.bot.add_reaction(ctx.message, sent_emoji)
+ try:
+ await ctx.message.delete(delay=3)
+ except (discord.Forbidden, discord.NotFound) as e:
+ logger.debug(f"Failed to delete note command message: {e}")
@commands.command()
@checks.has_permissions(PermissionLevel.SUPPORTER)
@@ -1505,11 +1724,11 @@ async def edit(self, ctx, message_id: Optional[int] = None, *, message: str):
try:
await thread.edit_message(message_id, message)
- except ValueError:
+ except ValueError as e:
return await ctx.send(
embed=discord.Embed(
title="Failed",
- description="Cannot find a message to edit. Plain messages are not supported.",
+ description=str(e),
color=self.bot.error_color,
)
)
@@ -1521,6 +1740,29 @@ async def edit(self, ctx, message_id: Optional[int] = None, *, message: str):
@checks.has_permissions(PermissionLevel.REGULAR)
async def selfcontact(self, ctx):
"""Creates a thread with yourself"""
+ # Check if user already has a thread
+ existing_thread = await self.bot.threads.find(recipient=ctx.author)
+ if existing_thread:
+ if existing_thread.snoozed:
+ # Unsnooze the thread
+ msg = await ctx.send("ℹ️ You had a snoozed thread. Unsnoozing now...")
+ await existing_thread.restore_from_snooze()
+ self.bot.threads.cache[existing_thread.id] = existing_thread
+ try:
+ await msg.delete(delay=10)
+ except (discord.Forbidden, discord.NotFound):
+ pass
+ return
+ else:
+ # Thread already exists and is active
+ embed = discord.Embed(
+ title="Thread not created",
+ description=f"A thread for you already exists in {existing_thread.channel.mention}.",
+ color=self.bot.error_color,
+ )
+ await ctx.send(embed=embed, delete_after=10)
+ return
+
await ctx.invoke(self.contact, users=[ctx.author])
@commands.command(usage=" [category] [options]")
@@ -1529,7 +1771,12 @@ async def contact(
self,
ctx,
users: commands.Greedy[
- Union[Literal["silent", "silently"], discord.Member, discord.User, discord.Role]
+ Union[
+ Literal["silent", "silently"],
+ discord.Member,
+ discord.User,
+ discord.Role,
+ ]
],
*,
category: SimilarCategoryConverter = None,
@@ -1579,9 +1826,14 @@ async def contact(
users += u.members
users.remove(u)
+ snoozed_users = []
for u in list(users):
exists = await self.bot.threads.find(recipient=u)
if exists:
+ # Check if thread is snoozed
+ if exists.snoozed:
+ snoozed_users.append(u)
+ continue
errors.append(f"A thread for {u} already exists.")
if exists.channel:
errors[-1] += f" in {exists.channel.mention}"
@@ -1595,6 +1847,23 @@ async def contact(
errors.append(f"{ref} currently blocked from contacting {self.bot.user.name}.")
users.remove(u)
+ # Handle snoozed users - unsnooze them and return early
+ if snoozed_users:
+ for u in snoozed_users:
+ thread = await self.bot.threads.find(recipient=u)
+ if thread and thread.snoozed:
+ msg = await ctx.send(f"ℹ️ {u.mention} had a snoozed thread. Unsnoozing now...")
+ await thread.restore_from_snooze()
+ self.bot.threads.cache[thread.id] = thread
+ try:
+ await msg.delete(delay=10)
+ except (discord.Forbidden, discord.NotFound) as e:
+ logger.debug(
+ f"Failed to delete message (likely already deleted or lacking permissions): {e}"
+ )
+ # Don't try to create a new thread - we just unsnoozed existing ones
+ return
+
if len(users) > 5:
errors.append("Group conversations only support 5 users.")
users = []
@@ -1607,11 +1876,14 @@ async def contact(
title = None
if manual_trigger: # not react to contact
- embed = discord.Embed(title=title, color=self.bot.error_color, description="\n".join(errors))
+ embed = discord.Embed(
+ title=title,
+ color=self.bot.error_color,
+ description="\n".join(errors),
+ )
await ctx.send(embed=embed, delete_after=10)
if not users:
- # end
return
creator = ctx.author if manual_trigger else users[0]
@@ -1621,12 +1893,16 @@ async def contact(
creator=creator,
category=category,
manual_trigger=manual_trigger,
+ # The minimum character check is enforced in ThreadManager.create
)
if thread.cancelled:
return
- if self.bot.config["dm_disabled"] in (DMDisabled.NEW_THREADS, DMDisabled.ALL_THREADS):
+ if self.bot.config["dm_disabled"] in (
+ DMDisabled.NEW_THREADS,
+ DMDisabled.ALL_THREADS,
+ ):
logger.info("Contacting user %s when Modmail DM is disabled.", users[0])
if not silent and not self.bot.config.get("thread_contact_silently"):
@@ -1644,7 +1920,9 @@ async def contact(
)
if self.bot.config["show_timestamp"]:
em.timestamp = discord.utils.utcnow()
- em.set_footer(text=f"{creator}", icon_url=creator.display_avatar.url)
+ em.set_footer(
+ text=f"{creator}", icon_url=creator.display_avatar.url if creator.display_avatar else None
+ )
for u in users:
await u.send(embed=em)
@@ -1664,8 +1942,10 @@ async def contact(
if manual_trigger:
sent_emoji, _ = await self.bot.retrieve_emoji()
await self.bot.add_reaction(ctx.message, sent_emoji)
- await asyncio.sleep(5)
- await ctx.message.delete()
+ try:
+ await ctx.message.delete(delay=5)
+ except (discord.Forbidden, discord.NotFound):
+ pass
@commands.group(invoke_without_command=True)
@checks.has_permissions(PermissionLevel.MODERATOR)
@@ -1966,7 +2246,9 @@ async def unblock(self, ctx, *, user_or_role: Union[User, Role] = None):
)
else:
embed = discord.Embed(
- title="Error", description=f"{mention} is not blocked.", color=self.bot.error_color
+ title="Error",
+ description=f"{mention} is not blocked.",
+ color=self.bot.error_color,
)
return await ctx.send(embed=embed)
@@ -1992,7 +2274,7 @@ async def delete(self, ctx, message_id: int = None):
return await ctx.send(
embed=discord.Embed(
title="Failed",
- description="Cannot find a message to delete. Plain messages are not supported.",
+ description=str(e),
color=self.bot.error_color,
)
)
@@ -2106,7 +2388,9 @@ async def repair(self, ctx):
thread.ready = True
logger.info("Setting current channel's topic to User ID and created new thread.")
await ctx.channel.edit(
- reason="Fix broken Modmail thread", name=name, topic=f"User ID: {user.id}"
+ reason="Fix broken Modmail thread",
+ name=name,
+ topic=f"User ID: {user.id}",
)
return await self.bot.add_reaction(ctx.message, sent_emoji)
@@ -2213,6 +2497,344 @@ async def isenable(self, ctx):
return await ctx.send(embed=embed)
+ @commands.command(usage="[duration]")
+ @checks.has_permissions(PermissionLevel.SUPPORTER)
+ @checks.thread_only()
+ async def snooze(self, ctx, *, duration: UserFriendlyTime = None):
+ """
+ Snooze this thread. Behavior depends on config:
+ - delete (default): deletes the channel and restores it later
+ - move: moves the channel to the configured snoozed category
+ Optionally specify a duration, e.g. 'snooze 2d' for 2 days.
+ Uses config: snooze_default_duration, snooze_title, snooze_text
+ """
+ thread = ctx.thread
+ if thread.snoozed:
+ await ctx.send("This thread is already snoozed.")
+ logging.info(f"[SNOOZE] Thread for {getattr(thread.recipient, 'id', None)} already snoozed.")
+ return
+ # Default snooze duration with safe fallback
+ try:
+ default_snooze = int(self.bot.config.get("snooze_default_duration", 604800))
+ except (ValueError, TypeError):
+ default_snooze = 604800
+ if duration:
+ snooze_for = int((duration.dt - duration.now).total_seconds())
+ snooze_for = min(snooze_for, default_snooze)
+ else:
+ snooze_for = default_snooze
+
+ # Capacity pre-check: if behavior is move, ensure snoozed category has room (<49 channels)
+ behavior = (self.bot.config.get("snooze_behavior") or "delete").lower()
+ if behavior == "move":
+ snoozed_cat_id = self.bot.config.get("snoozed_category_id")
+ target_category = None
+ if snoozed_cat_id:
+ try:
+ target_category = self.bot.modmail_guild.get_channel(int(snoozed_cat_id))
+ except Exception:
+ target_category = None
+ # Auto-create snoozed category if missing
+ if not isinstance(target_category, discord.CategoryChannel):
+ try:
+ logging.info("Auto-creating snoozed category for move-based snoozing.")
+ # Hide category by default; only bot can view/manage
+ overwrites = {
+ self.bot.modmail_guild.default_role: discord.PermissionOverwrite(view_channel=False)
+ }
+ bot_member = self.bot.modmail_guild.me
+ if bot_member is not None:
+ overwrites[bot_member] = discord.PermissionOverwrite(
+ view_channel=True,
+ send_messages=True,
+ read_message_history=True,
+ manage_channels=True,
+ manage_messages=True,
+ attach_files=True,
+ embed_links=True,
+ add_reactions=True,
+ )
+ target_category = await self.bot.modmail_guild.create_category(
+ name="Snoozed Threads",
+ overwrites=overwrites,
+ reason="Auto-created snoozed category for move-based snoozing",
+ )
+ try:
+ await self.bot.config.set("snoozed_category_id", target_category.id)
+ await self.bot.config.update()
+ except Exception as e:
+ logging.warning("Failed to persist snoozed_category_id: %s", e)
+ try:
+ await ctx.send(
+ "⚠️ Created snoozed category but failed to save it to config. Please set `snoozed_category_id` manually."
+ )
+ except Exception as e:
+ logging.info(
+ "Failed to notify about snoozed category persistence issue: %s",
+ e,
+ )
+ await ctx.send(
+ embed=discord.Embed(
+ title="Snoozed category created",
+ description=(
+ f"Created category {target_category.mention if hasattr(target_category, 'mention') else target_category.name} "
+ "and set it as `snoozed_category_id`."
+ ),
+ color=self.bot.main_color,
+ )
+ )
+ except Exception as e:
+ await ctx.send(
+ embed=discord.Embed(
+ title="Could not create snoozed category",
+ description=(
+ "I couldn't create a category automatically. Please ensure I have Manage Channels "
+ "permission, or set `snoozed_category_id` manually."
+ ),
+ color=self.bot.error_color,
+ )
+ )
+ logging.warning("Failed to auto-create snoozed category: %s", e)
+ # Capacity check after ensuring category exists
+ if isinstance(target_category, discord.CategoryChannel):
+ try:
+ if len(target_category.channels) >= 49:
+ await ctx.send(
+ embed=discord.Embed(
+ title="Snooze unavailable",
+ description=(
+ "The configured snoozed category is full (49 channels). "
+ "Unsnooze or move some channels out before snoozing more."
+ ),
+ color=self.bot.error_color,
+ )
+ )
+ return
+ except Exception as e:
+ logging.debug("Failed to check snoozed category channel count: %s", e)
+
+ # Store snooze_until timestamp for reliable auto-unsnooze
+ now = datetime.now(timezone.utc)
+ snooze_until = now + timedelta(seconds=snooze_for)
+ await self.bot.api.logs.update_one(
+ {"recipient.id": str(thread.id)},
+ {
+ "$set": {
+ "snooze_start": now.isoformat(),
+ "snooze_for": snooze_for,
+ "snooze_until": snooze_until.isoformat(),
+ }
+ },
+ )
+ embed = discord.Embed(
+ title=self.bot.config.get("snooze_title") or "Thread Snoozed",
+ description=self.bot.config.get("snooze_text") or "This thread has been snoozed.",
+ color=self.bot.error_color,
+ )
+ await ctx.send(embed=embed)
+ ok = await thread.snooze(moderator=ctx.author, snooze_for=snooze_for)
+ if ok:
+ logging.info(
+ f"[SNOOZE] Thread for {getattr(thread.recipient, 'id', None)} snoozed for {snooze_for}s."
+ )
+ self.bot.threads.cache[thread.id] = thread
+ else:
+ await ctx.send("Failed to snooze this thread.")
+ logging.error(f"[SNOOZE] Failed to snooze thread for {getattr(thread.recipient, 'id', None)}.")
+
+ @commands.command()
+ @checks.has_permissions(PermissionLevel.SUPPORTER)
+ async def unsnooze(self, ctx, *, user: str = None):
+ """
+ Unsnooze a thread: restores the channel and replays messages.
+ You can specify a user by mention or ID, or run in a thread channel to unsnooze that thread.
+ Uses config: unsnooze_text
+ """
+ import discord
+
+ thread = None
+ user_obj = None
+ if user is not None:
+ user_id = self._resolve_user(user)
+ if user_id:
+ try:
+ user_obj = await self.bot.get_or_fetch_user(user_id)
+ except Exception:
+ logger.debug(
+ "Failed fetching user during unsnooze; falling back to partial object (%s).",
+ user_id,
+ exc_info=True,
+ )
+ user_obj = discord.Object(user_id)
+ if user_obj:
+ thread = await self.bot.threads.find(recipient=user_obj)
+ if not thread:
+ await ctx.send(f"[DEBUG] No thread found for user {user} (obj: {user_obj}).")
+ logging.warning(f"[UNSNOOZE] No thread found for user {user} (obj: {user_obj})")
+ return
+ elif hasattr(ctx, "thread"):
+ thread = ctx.thread
+ else:
+ await ctx.send("This is not a Modmail thread.")
+ logging.warning("[UNSNOOZE] Not a Modmail thread context.")
+ return
+ if not thread.snoozed:
+ await ctx.send("This thread is not snoozed.")
+ logging.info(f"[UNSNOOZE] Thread for {getattr(thread.recipient, 'id', None)} is not snoozed.")
+ return
+
+ # Manually fetch snooze_data if the thread object doesn't have it
+ if not thread.snooze_data:
+ log_entry = await self.bot.api.logs.find_one({"recipient.id": str(thread.id), "snoozed": True})
+ if log_entry:
+ thread.snooze_data = log_entry.get("snooze_data")
+
+ ok = await thread.restore_from_snooze()
+ if ok:
+ self.bot.threads.cache[thread.id] = thread
+ await ctx.send(
+ self.bot.config.get("unsnooze_text") or "This thread has been unsnoozed and restored."
+ )
+ logging.info(f"[UNSNOOZE] Thread for {getattr(thread.recipient, 'id', None)} unsnoozed.")
+ else:
+ await ctx.send("Failed to unsnooze this thread.")
+ logging.error(
+ f"[UNSNOOZE] Failed to unsnooze thread for {getattr(thread.recipient, 'id', None)}."
+ )
+
+ @commands.command()
+ @checks.has_permissions(PermissionLevel.SUPPORTER)
+ async def snoozed(self, ctx):
+ """
+ List all currently snoozed threads/users.
+ """
+ snoozed_threads = [thread for thread in self.bot.threads.cache.values() if thread.snoozed]
+ if not snoozed_threads:
+ await ctx.send("No threads are currently snoozed.")
+ return
+
+ lines = []
+ now = datetime.now(timezone.utc)
+ for thread in snoozed_threads:
+ user = thread.recipient.name if thread.recipient else "Unknown"
+ user_id = thread.id
+
+ since_str = "?"
+ until_str = "?"
+
+ if thread.snooze_data:
+ since = thread.snooze_data.get("snooze_start")
+ duration = thread.snooze_data.get("snooze_for")
+
+ if since:
+ try:
+ since_dt = datetime.fromisoformat(since)
+ since_str = f"" # Discord relative timestamp
+ except (ValueError, TypeError) as e:
+ logging.warning(f"[SNOOZED] Invalid snooze_start for {user_id}: {since} ({e})")
+ else:
+ logging.warning(f"[SNOOZED] Missing snooze_start for {user_id}")
+
+ if duration and since_str != "?":
+ try:
+ until_dt = datetime.fromisoformat(since) + timedelta(seconds=int(duration))
+ until_str = f""
+ except (ValueError, TypeError) as e:
+ logging.warning(
+ f"[SNOOZED] Invalid until time for {user_id}: {since} + {duration} ({e})"
+ )
+
+ lines.append(f"- {user} (`{user_id}`) since {since_str}, until {until_str}")
+
+ await ctx.send("Snoozed threads:\n" + "\n".join(lines))
+
+ async def cog_load(self):
+ self.snooze_auto_unsnooze.start()
+
+ @tasks.loop(seconds=10)
+ async def snooze_auto_unsnooze(self):
+ now = datetime.now(timezone.utc)
+ snoozed = await self.bot.api.logs.find({"snoozed": True}).to_list(None)
+ for entry in snoozed:
+ snooze_until = entry.get("snooze_until")
+ if snooze_until:
+ try:
+ until_dt = datetime.fromisoformat(snooze_until)
+ if now >= until_dt:
+ thread = await self.bot.threads.find(recipient_id=int(entry["recipient"]["id"]))
+ if thread and thread.snoozed:
+ await thread.restore_from_snooze()
+ except (ValueError, TypeError) as e:
+ logger.debug(
+ "Failed parsing snooze_until timestamp for auto-unsnooze loop: %s",
+ e,
+ )
+
+ @snooze_auto_unsnooze.before_loop
+ async def _snooze_auto_unsnooze_before(self):
+ await self.bot.wait_until_ready()
+
+ async def process_dm_modmail(self, message: discord.Message) -> None:
+ # ... existing code ...
+ # Before processing, check if thread is snoozed and auto-unsnooze
+ thread = await self.threads.find(recipient=message.author)
+ if thread and thread.snoozed:
+ await thread.restore_from_snooze()
+ # Ensure the thread object in the cache is updated with the new channel
+ self.threads.cache[thread.id] = thread
+ # ... rest of the method unchanged ...
+
+ @commands.command()
+ @checks.has_permissions(PermissionLevel.OWNER)
+ async def clearsnoozed(self, ctx):
+ """
+ List all snoozed threads and ask for confirmation before clearing (unsnoozing) all of them.
+ Only proceed if the user confirms.
+ """
+ snoozed = await self.bot.api.logs.find({"snoozed": True}).to_list(None)
+ if not snoozed:
+ await ctx.send("No threads are currently snoozed.")
+ return
+ lines = []
+ for entry in snoozed:
+ user = entry.get("recipient", {}).get("name", "Unknown")
+ user_id = entry.get("recipient", {}).get("id", "?")
+ lines.append(f"- {user} (`{user_id}`)")
+ msg = await ctx.send(
+ "The following threads are currently snoozed and will be unsnoozed if you confirm:\n"
+ + "\n".join(lines)
+ + "\n\nType `yes` to confirm, or anything else to cancel."
+ )
+
+ def check(m):
+ return m.author == ctx.author and m.channel == ctx.channel
+
+ try:
+ reply = await self.bot.wait_for("message", check=check, timeout=30)
+ except asyncio.TimeoutError:
+ await ctx.send("Timed out. No threads were unsnoozed.")
+ return
+ if reply.content.strip().lower() != "yes":
+ await ctx.send("Cancelled. No threads were unsnoozed.")
+ return
+ count = 0
+ for entry in snoozed:
+ user_id = entry.get("recipient", {}).get("id")
+ if not user_id:
+ continue
+ user_obj = None
+ try:
+ user_obj = await self.bot.get_or_fetch_user(int(user_id))
+ except Exception:
+ user_obj = discord.Object(int(user_id))
+ thread = await self.bot.threads.find(recipient=user_obj)
+ if thread and thread.snoozed:
+ ok = await thread.restore_from_snooze()
+ if ok:
+ self.bot.threads.cache[thread.id] = thread
+ count += 1
+ await ctx.send(f"Unsnoozed {count} threads.")
+
async def setup(bot):
await bot.add_cog(Modmail(bot))
diff --git a/cogs/plugins.py b/cogs/plugins.py
index 78bc0aa544..a5cece7ab6 100644
--- a/cogs/plugins.py
+++ b/cogs/plugins.py
@@ -20,7 +20,7 @@
from core import checks
from core.models import PermissionLevel, getLogger
from core.paginator import EmbedPaginatorSession
-from core.utils import trigger_typing, truncate
+from core.utils import trigger_typing, truncate, safe_typing
logger = getLogger(__name__)
@@ -113,7 +113,7 @@ class Plugins(commands.Cog):
These addons could have a range of features from moderation to simply
making your life as a moderator easier!
Learn how to create a plugin yourself here:
- https://github.com/modmail-dev/modmail/wiki/Plugins
+ https://docs.modmail.dev/usage-guide/plugins
"""
def __init__(self, bot):
@@ -251,7 +251,11 @@ async def load_plugin(self, plugin):
if stderr:
logger.debug("[stderr]\n%s.", stderr.decode())
- logger.error("Failed to download requirements for %s.", plugin.ext_string, exc_info=True)
+ logger.error(
+ "Failed to download requirements for %s.",
+ plugin.ext_string,
+ exc_info=True,
+ )
raise InvalidPluginError(f"Unable to download requirements: ```\n{stderr.decode()}\n```")
if os.path.exists(USER_SITE):
@@ -328,7 +332,7 @@ async def parse_user_input(self, ctx, plugin_name, check_version=False):
embed = discord.Embed(
description="Invalid plugin name, double check the plugin name "
"or use one of the following formats: "
- "username/repo/plugin-name, username/repo/plugin-name@branch, local/plugin-name.",
+ "username/repo/plugin-name, username/repo/plugin-name@branch, @local/plugin-name.",
color=self.bot.error_color,
)
await ctx.send(embed=embed)
@@ -353,7 +357,7 @@ async def plugins_add(self, ctx, *, plugin_name: str):
`plugin_name` can be the name of the plugin found in `{prefix}plugin registry`,
or a direct reference to a GitHub hosted plugin (in the format `user/repo/name[@branch]`)
- or `local/name` for local plugins.
+ or `@local/name` for local plugins.
"""
plugin = await self.parse_user_input(ctx, plugin_name, check_version=True)
@@ -361,7 +365,10 @@ async def plugins_add(self, ctx, *, plugin_name: str):
return
if str(plugin) in self.bot.config["plugins"]:
- embed = discord.Embed(description="This plugin is already installed.", color=self.bot.error_color)
+ embed = discord.Embed(
+ description="This plugin is already installed.",
+ color=self.bot.error_color,
+ )
return await ctx.send(embed=embed)
if plugin.name in self.bot.cogs:
@@ -437,7 +444,7 @@ async def plugins_remove(self, ctx, *, plugin_name: str):
Remove an installed plugin of the bot.
`plugin_name` can be the name of the plugin found in `{prefix}plugin registry`, or a direct reference
- to a GitHub hosted plugin (in the format `user/repo/name[@branch]`) or `local/name` for local plugins.
+ to a GitHub hosted plugin (in the format `user/repo/name[@branch]`) or `@local/name` for local plugins.
"""
plugin = await self.parse_user_input(ctx, plugin_name)
if plugin is None:
@@ -470,7 +477,8 @@ async def plugins_remove(self, ctx, *, plugin_name: str):
pass # dir not empty
embed = discord.Embed(
- description="The plugin is successfully uninstalled.", color=self.bot.main_color
+ description="The plugin is successfully uninstalled.",
+ color=self.bot.main_color,
)
await ctx.send(embed=embed)
@@ -484,9 +492,10 @@ async def update_plugin(self, ctx, plugin_name):
embed = discord.Embed(description="Plugin is not installed.", color=self.bot.error_color)
return await ctx.send(embed=embed)
- async with ctx.typing():
+ async with safe_typing(ctx):
embed = discord.Embed(
- description=f"Successfully updated {plugin.name}.", color=self.bot.main_color
+ description=f"Successfully updated {plugin.name}.",
+ color=self.bot.main_color,
)
await self.download_plugin(plugin, force=True)
if self.bot.config.get("enable_plugins"):
@@ -517,7 +526,7 @@ async def plugins_update(self, ctx, *, plugin_name: str = None):
Update a plugin for the bot.
`plugin_name` can be the name of the plugin found in `{prefix}plugin registry`, or a direct reference
- to a GitHub hosted plugin (in the format `user/repo/name[@branch]`) or `local/name` for local plugins.
+ to a GitHub hosted plugin (in the format `user/repo/name[@branch]`) or `@local/name` for local plugins.
To update all plugins, do `{prefix}plugins update`.
"""
@@ -570,7 +579,8 @@ async def plugins_reset(self, ctx):
logger.warning("Removing %s.", entry.name)
embed = discord.Embed(
- description="Successfully purged all plugins from the bot.", color=self.bot.main_color
+ description="Successfully purged all plugins from the bot.",
+ color=self.bot.main_color,
)
return await ctx.send(embed=embed)
@@ -598,7 +608,8 @@ async def plugins_loaded(self, ctx):
if not self.loaded_plugins:
embed = discord.Embed(
- description="There are no plugins currently loaded.", color=self.bot.error_color
+ description="There are no plugins currently loaded.",
+ color=self.bot.error_color,
)
return await ctx.send(embed=embed)
@@ -666,7 +677,10 @@ async def plugins_registry(self, ctx, *, plugin_name: typing.Union[int, str] = N
matches = get_close_matches(plugin_name, self.registry.keys())
if matches:
- embed.add_field(name="Perhaps you meant:", value="\n".join(f"`{m}`" for m in matches))
+ embed.add_field(
+ name="Perhaps you meant:",
+ value="\n".join(f"`{m}`" for m in matches),
+ )
return await ctx.send(embed=embed)
@@ -759,7 +773,10 @@ async def plugins_registry_compact(self, ctx):
for page in pages:
embed = discord.Embed(color=self.bot.main_color, description=page)
- embed.set_author(name="Plugin Registry", icon_url=self.bot.user.display_avatar.url)
+ embed.set_author(
+ name="Plugin Registry",
+ icon_url=self.bot.user.display_avatar.url if self.bot.user.display_avatar else None,
+ )
embeds.append(embed)
paginator = EmbedPaginatorSession(ctx, *embeds)
diff --git a/cogs/threadmenu.py b/cogs/threadmenu.py
new file mode 100644
index 0000000000..4f4f1985ae
--- /dev/null
+++ b/cogs/threadmenu.py
@@ -0,0 +1,846 @@
+import json
+import asyncio
+from copy import copy as _copy
+
+import discord
+from discord.ext import commands
+
+from core import checks
+from core.models import PermissionLevel
+
+
+class ThreadCreationMenuCore(commands.Cog):
+ """Core-integrated thread menu configuration and management.
+
+ This Cog exposes the same commands as the legacy plugin to manage menu options,
+ but stores settings in core config (no plugin DB).
+ """
+
+ def __init__(self, bot):
+ self.bot = bot
+
+ # ----- helpers -----
+ def _get_conf(self) -> dict:
+ return {
+ "enabled": bool(self.bot.config.get("thread_creation_menu_enabled")),
+ "options": self.bot.config.get("thread_creation_menu_options") or {},
+ "submenus": self.bot.config.get("thread_creation_menu_submenus") or {},
+ "timeout": int(self.bot.config.get("thread_creation_menu_timeout") or 20),
+ "close_on_timeout": bool(self.bot.config.get("thread_creation_menu_close_on_timeout")),
+ "anonymous_menu": bool(self.bot.config.get("thread_creation_menu_anonymous_menu")),
+ "embed_text": self.bot.config.get("thread_creation_menu_embed_text")
+ or "Please select an option.",
+ "dropdown_placeholder": self.bot.config.get("thread_creation_menu_dropdown_placeholder")
+ or "Select an option to contact the staff team.",
+ "embed_title": self.bot.config.get("thread_creation_menu_embed_title"),
+ "embed_footer": self.bot.config.get("thread_creation_menu_embed_footer"),
+ "embed_thumbnail_url": self.bot.config.get("thread_creation_menu_embed_thumbnail_url"),
+ "embed_footer_icon_url": self.bot.config.get("thread_creation_menu_embed_footer_icon_url"),
+ "embed_color": self.bot.config.get("thread_creation_menu_embed_color"),
+ }
+
+ async def _save_conf(self, conf: dict):
+ await self.bot.config.set("thread_creation_menu_enabled", conf.get("enabled", False))
+ await self.bot.config.set("thread_creation_menu_options", conf.get("options", {}), convert=False)
+ await self.bot.config.set("thread_creation_menu_submenus", conf.get("submenus", {}), convert=False)
+ await self.bot.config.set("thread_creation_menu_timeout", conf.get("timeout", 20))
+ await self.bot.config.set(
+ "thread_creation_menu_close_on_timeout", conf.get("close_on_timeout", False)
+ )
+ await self.bot.config.set("thread_creation_menu_anonymous_menu", conf.get("anonymous_menu", False))
+ await self.bot.config.set(
+ "thread_creation_menu_embed_text", conf.get("embed_text", "Please select an option.")
+ )
+ await self.bot.config.set(
+ "thread_creation_menu_dropdown_placeholder",
+ conf.get("dropdown_placeholder", "Select an option to contact the staff team."),
+ )
+ await self.bot.config.set("thread_creation_menu_embed_title", conf.get("embed_title"))
+ await self.bot.config.set("thread_creation_menu_embed_footer", conf.get("embed_footer"))
+ await self.bot.config.set("thread_creation_menu_embed_thumbnail_url", conf.get("embed_thumbnail_url"))
+ await self.bot.config.set(
+ "thread_creation_menu_embed_footer_icon_url", conf.get("embed_footer_icon_url")
+ )
+ if conf.get("embed_color"):
+ try:
+ await self.bot.config.set("thread_creation_menu_embed_color", conf.get("embed_color"))
+ except Exception:
+ pass
+ await self.bot.config.update()
+
+ # ----- commands -----
+ @checks.has_permissions(PermissionLevel.ADMINISTRATOR)
+ @commands.group(invoke_without_command=True)
+ async def threadmenu(self, ctx):
+ """Thread-creation menu settings (core)."""
+ await ctx.send_help(ctx.command)
+
+ @checks.has_permissions(PermissionLevel.ADMINISTRATOR)
+ @threadmenu.command(name="toggle")
+ async def threadmenu_toggle(self, ctx):
+ """Enable or disable the thread-creation menu.
+
+ Toggles the global on/off state. When disabled, users won't see
+ or be able to use the interactive thread creation select menu.
+ """
+ conf = self._get_conf()
+ conf["enabled"] = not conf["enabled"]
+ await self._save_conf(conf)
+ await ctx.send(f"Thread-creation menu is now {'enabled' if conf['enabled'] else 'disabled'}.")
+ advancedmenu_plugin = self.bot.get_cog("AdvancedMenu")
+ if (
+ advancedmenu_plugin
+ and hasattr(advancedmenu_plugin, "config")
+ and advancedmenu_plugin.config.get("enabled")
+ and advancedmenu_plugin.config["enabled"] is True
+ and conf["enabled"]
+ ):
+ await ctx.send(
+ "**Warning:** You are using both the core threadmenu feature and the advancedmenu plugin.\n"
+ "It is recommended to disable/uninstall the advancedmenu plugin to avoid interruption.\n"
+ "Migration guide can be found at: "
+ )
+
+ @checks.has_permissions(PermissionLevel.ADMINISTRATOR)
+ @threadmenu.command(name="show")
+ async def threadmenu_show(self, ctx):
+ """Show all current main-menu options.
+
+ Lists every option (label + description) configured in the root
+ (non-submenu) select menu so you can review what users will see.
+ """
+ conf = self._get_conf()
+ if not conf["options"]:
+ return await ctx.send("There are no options in the main menu.")
+ embed = discord.Embed(title="Main menu", color=discord.Color.blurple())
+ for v in conf["options"].values():
+ embed.add_field(name=v["label"], value=v["description"], inline=False)
+ await ctx.send(embed=embed)
+
+ # ----- options -----
+ @checks.has_permissions(PermissionLevel.ADMINISTRATOR)
+ @threadmenu.group(name="option", invoke_without_command=True)
+ async def threadmenu_option(self, ctx):
+ """Manage main-menu options (add/remove/edit/show).
+
+ Use subcommands:
+ - add: interactive wizard to create an option
+ - remove