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/CHANGELOG.md b/CHANGELOG.md index 4ec54e0f8a..83c4f1bdd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,39 @@ 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.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..8fe5bd40c8 100644 --- a/Pipfile +++ b/Pipfile @@ -8,11 +8,12 @@ bandit = ">=1.7.5" black = "==23.11.0" pylint = "==3.0.2" typing-extensions = "==4.8.0" +tomli = "==2.2.1" # Needed for black on Python < 3.11 [packages] aiohttp = "==3.9.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" diff --git a/Pipfile.lock b/Pipfile.lock index 5f07c7b131..ae2da5ae76 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "7fee393ea9ea4c0b923033f0da0fdc590ba3f75c6072812062cdc458b84bf9ae" + "sha256": "93bdedec9b82ac210253d3424e48f3af9e79dca6c44b5b941ec446709de27409" }, "pipfile-spec": 6, "requires": {}, @@ -16,10 +16,11 @@ "default": { "aiodns": { "hashes": [ - "sha256:1073eac48185f7a4150cad7f96a5192d6911f12b4fb894de80a088508c9b3a99", - "sha256:a387b63da4ced6aad35b1dda2d09620ad608a1c7c0fb71efa07ebb4cd511928d" + "sha256:11264edbab51896ecf546c18eb0dd56dff0428c6aa6d2cd87e643e07300eb310", + "sha256:6d0404f7d5215849233f6ee44854f2bb2481adf71b336b2279016ea5990ca5c5" ], - "version": "==3.1.1" + "markers": "python_version >= '3.9'", + "version": "==3.5.0" }, "aiohttp": { "hashes": [ @@ -106,33 +107,81 @@ }, "aiosignal": { "hashes": [ - "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", - "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17" + "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", + "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7" ], - "markers": "python_version >= '3.7'", - "version": "==1.3.1" - }, - "async-timeout": { - "hashes": [ - "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", - "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028" - ], - "markers": "python_version < '3.11'", - "version": "==4.0.3" + "markers": "python_version >= '3.9'", + "version": "==1.4.0" }, "attrs": { "hashes": [ - "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", - "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015" + "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", + "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b" ], - "markers": "python_version >= '3.7'", - "version": "==23.1.0" + "markers": "python_version >= '3.8'", + "version": "==25.3.0" + }, + "audioop-lts": { + "hashes": [ + "sha256:0337d658f9b81f4cd0fdb1f47635070cc084871a3d4646d9de74fdf4e7c3d24a", + "sha256:03f061a1915538fd96272bac9551841859dbb2e3bf73ebe4a23ef043766f5449", + "sha256:068aa17a38b4e0e7de771c62c60bbca2455924b67a8814f3b0dee92b5820c0b3", + "sha256:088327f00488cdeed296edd9215ca159f3a5a5034741465789cad403fcf4bec0", + "sha256:0d9385e96f9f6da847f4d571ce3cb15b5091140edf3db97276872647ce37efd7", + "sha256:106753a83a25ee4d6f473f2be6b0966fc1c9af7e0017192f5531a3e7463dce58", + "sha256:143fad0311e8209ece30a8dbddab3b65ab419cbe8c0dde6e8828da25999be911", + "sha256:15ab25dd3e620790f40e9ead897f91e79c0d3ce65fe193c8ed6c26cffdd24be7", + "sha256:167d3b62586faef8b6b2275c3218796b12621a60e43f7e9d5845d627b9c9b80e", + "sha256:2b267b70747d82125f1a021506565bdc5609a2b24bcb4773c16d79d2bb260bbd", + "sha256:3bcddaaf6cc5935a300a8387c99f7a7fbbe212a11568ec6cf6e4bc458c048636", + "sha256:3fc38008969796f0f689f1453722a0f463da1b8a6fbee11987830bfbb664f623", + "sha256:47eba38322370347b1c47024defbd36374a211e8dd5b0dcbce7b34fdb6f8847b", + "sha256:48159d96962674eccdca9a3df280e864e8ac75e40a577cc97c5c42667ffabfc5", + "sha256:49ee1a41738a23e98d98b937a0638357a2477bc99e61b0f768a8f654f45d9b7a", + "sha256:4a53aa7c16a60a6857e6b0b165261436396ef7293f8b5c9c828a3a203147ed4a", + "sha256:4b4cd51a57b698b2d06cb9993b7ac8dfe89a3b2878e96bc7948e9f19ff51dba6", + "sha256:51c916108c56aa6e426ce611946f901badac950ee2ddaf302b7ed35d9958970d", + "sha256:550c114a8df0aafe9a05442a1162dfc8fec37e9af1d625ae6060fed6e756f303", + "sha256:58cf54380c3884fb49fdd37dfb7a772632b6701d28edd3e2904743c5e1773602", + "sha256:5b00be98ccd0fc123dcfad31d50030d25fcf31488cde9e61692029cd7394733b", + "sha256:5f93a5db13927a37d2d09637ccca4b2b6b48c19cd9eda7b17a2e9f77edee6a6f", + "sha256:64d0c62d88e67b98a1a5e71987b7aa7b5bcffc7dcee65b635823dbdd0a8dbbd0", + "sha256:73f80bf4cd5d2ca7814da30a120de1f9408ee0619cc75da87d0641273d202a09", + "sha256:752d76472d9804ac60f0078c79cdae8b956f293177acd2316cd1e15149aee132", + "sha256:83c381767e2cc10e93e40281a04852facc4cd9334550e0f392f72d1c0a9c5753", + "sha256:8fefe5868cd082db1186f2837d64cfbfa78b548ea0d0543e9b28935ccce81ce9", + "sha256:9191d68659eda01e448188f60364c7763a7ca6653ed3f87ebb165822153a8547", + "sha256:96f19de485a2925314f5020e85911fb447ff5fbef56e8c7c6927851b95533a1c", + "sha256:9a13dc409f2564de15dd68be65b462ba0dde01b19663720c68c1140c782d1d75", + "sha256:a2c2a947fae7d1062ef08c4e369e0ba2086049a5e598fda41122535557012e9e", + "sha256:a2d4f1513d63c795e82948e1305f31a6d530626e5f9f2605408b300ae6095093", + "sha256:a5bf613e96f49712073de86f20dbdd4014ca18efd4d34ed18c75bd808337851b", + "sha256:a6d2e0f9f7a69403e388894d4ca5ada5c47230716a03f2847cfc7bd1ecb589d6", + "sha256:b492c3b040153e68b9fdaff5913305aaaba5bb433d8a7f73d5cf6a64ed3cc1dd", + "sha256:ba7c3a7e5f23e215cb271516197030c32aef2e754252c4c70a50aaff7031a2c8", + "sha256:c0022283e9556e0f3643b7c3c03f05063ca72b3063291834cca43234f20c60bb", + "sha256:c174e322bb5783c099aaf87faeb240c8d210686b04bd61dfd05a8e5a83d88969", + "sha256:c9c8e68d8b4a56fda8c025e538e639f8c5953f5073886b596c93ec9b620055e7", + "sha256:cfcac6aa6f42397471e4943e0feb2244549db5c5d01efcd02725b96af417f3fe", + "sha256:d5e73fa573e273e4f2e5ff96f9043858a5e9311e94ffefd88a3186a910c70917", + "sha256:def246fe9e180626731b26e89816e79aae2276f825420a07b4a647abaa84becc", + "sha256:dfbbc74ec68a0fd08cfec1f4b5e8cca3d3cd7de5501b01c4b5d209995033cde9", + "sha256:e160bf9df356d841bb6c180eeeea1834085464626dc1b68fa4e1d59070affdc3", + "sha256:e541c3ef484852ef36545f66209444c48b28661e864ccadb29daddb6a4b8e5f5", + "sha256:f9b0b8a03ef474f56d1a842af1a2e01398b8f7654009823c6d9e0ecff4d5cfbf", + "sha256:f9ee9b52f5f857fbaf9d605a360884f034c92c1c23021fb90b2e39b8e64bede6", + "sha256:fbdd522624141e40948ab3e8cdae6e04c748d78710e9f0f8d4dae2750831de19", + "sha256:fd3d4602dc64914d462924a08c1a9816435a2155d74f325853c1f1ac3b2d9800" + ], + "markers": "python_version >= '3.13'", + "version": "==0.2.2" }, "brotli": { "hashes": [ "sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208", "sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48", "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354", + "sha256:0737ddb3068957cf1b054899b0883830bb1fec522ec76b1098f9b6e0f02d9419", "sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a", "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128", "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c", @@ -140,43 +189,67 @@ "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9", "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a", "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3", + "sha256:1b2c248cd517c222d89e74669a4adfa5577e06ab68771a529060cf5a156e9757", + "sha256:1e9a65b5736232e7a7f91ff3d02277f11d339bf34099a56cdab6a8b3410a02b2", "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438", "sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578", "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b", "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b", "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68", + "sha256:2a24c50840d89ded6c9a8fdc7b6ed3692ed4e86f1c4a4a938e1e92def92933e0", "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d", + "sha256:2feb1d960f760a575dbc5ab3b1c00504b24caaf6986e2dc2b01c09c87866a943", "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd", "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", + "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28", "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da", "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50", + "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f", "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0", + "sha256:3ee8a80d67a4334482d9712b8e83ca6b1d9bc7e351931252ebef5d8f7335a547", "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", + "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0", "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d", + "sha256:4410f84b33374409552ac9b6903507cdb31cd30d2501fc5ca13d18f73548444a", + "sha256:494994f807ba0b92092a163a0a283961369a65f6cbe01e8891132b7a320e61eb", "sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112", "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc", + "sha256:4f3607b129417e111e30637af1b56f24f7a49e64763253bbc275c75fa887d4b2", "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265", "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327", "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95", + "sha256:58d4b711689366d4a03ac7957ab8c28890415e267f9b6589969e74b6e42225ec", "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd", + "sha256:5dab0844f2cf82be357a0eb11a9087f70c5430b2c241493fc122bb6f2bb0917c", + "sha256:5e55da2c8724191e5b557f8e18943b1b4839b8efc3ef60d65985bcf6f587dd38", "sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914", "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a", "sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7", + "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368", + "sha256:6974f52a02321b36847cd19d1b8e381bf39939c21efd6ee2fc13a28b0d99348c", "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0", + "sha256:6c6e0c425f22c1c719c42670d561ad682f7bfeeef918edea971a79ac5252437f", "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", "sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f", + "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8", "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e", "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", + "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c", "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91", "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724", + "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7", "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", + "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9", "sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97", "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d", + "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5", "sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf", "sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac", + "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b", "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74", + "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648", "sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60", "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c", "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1", @@ -187,27 +260,44 @@ "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460", "sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751", "sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9", + "sha256:a7e53012d2853a07a4a79c00643832161a910674a893d296c9f1259859a289d2", + "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0", "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1", "sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474", + "sha256:aea440a510e14e818e67bfc4027880e2fb500c2ccb20ab21c7a7c8b5b4703d75", + "sha256:af6fa6817889314555aede9a919612b23739395ce767fe7fcbea9a80bf140fe5", + "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f", "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2", + "sha256:c247dd99d39e0338a604f8c2b3bc7061d5c2e9e2ac7ba9cc1be5a69cb6cd832f", + "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb", "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6", "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9", + "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111", "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", + "sha256:cb1dac1770878ade83f2ccdf7d25e494f05c9165f5246b46a621cc849341dc01", "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467", "sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619", "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf", "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408", "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579", "sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84", + "sha256:d2b35ca2c7f81d173d2fadc2f4f31e88cc5f7a39ae5b6db5513cf3383b0e0ec7", + "sha256:d342778ef319e1026af243ed0a07c97acf3bad33b9f29e7ae6a1f68fd083e90c", + "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284", + "sha256:d7702622a8b40c49bffb46e1e3ba2e81268d5c04a34f460978c6b5517a34dd52", "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b", "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59", "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752", + "sha256:e4fe605b917c70283db7dfe5ada75e04561479075761a0b3866c081d035b01c1", "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80", + "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839", "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0", "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2", "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3", "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64", + "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089", "sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643", + "sha256:f31859074d57b4639318523d6ffdca586ace54271a73ad23ad021acd807eb14b", "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e", "sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985", "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596", @@ -218,181 +308,202 @@ }, "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:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", + "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43" ], - "markers": "python_version >= '3.6'", - "version": "==2023.11.17" + "markers": "python_version >= '3.7'", + "version": "==2025.10.5" }, "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:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91", + "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0", + "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", + "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601", + "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", + "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07", + "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c", + "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64", + "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", + "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", + "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432", + "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", + "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", + "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", + "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae", + "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19", + "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", + "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e", + "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4", + "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7", + "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312", + "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", + "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", + "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c", + "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", + "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99", + "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b", + "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", + "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", + "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", + "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", + "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", + "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0", + "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc", + "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", + "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f", + "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a", + "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40", + "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", + "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849", + "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", + "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", + "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05", + "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", + "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c", + "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a", + "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", + "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34", + "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9", + "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", + "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14", + "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30", + "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b", + "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b", + "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942", + "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", + "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", + "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b", + "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", + "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669", + "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0", + "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", + "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", + "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe", + "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", + "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", + "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", + "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2", + "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca", + "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", + "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f", + "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb", + "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", + "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557", + "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", + "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7", + "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72", + "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c", + "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9" + ], + "markers": "python_version >= '3.7'", + "version": "==3.4.3" }, "colorama": { "hashes": [ @@ -405,11 +516,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 +535,19 @@ "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" + "markers": "python_version >= '3.10'", + "version": "==2.8.0" }, "emoji": { "hashes": [ @@ -449,78 +560,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:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", + "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" ], - "markers": "python_version >= '3.5'", - "version": "==3.4" + "markers": "python_version >= '3.6'", + "version": "==3.10" }, "isodate": { "hashes": [ @@ -551,83 +731,119 @@ }, "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:01368e3c94032ba6ca0b78e7ccb099643466cf24f8dc8eefcfdc0571d56e58f9", + "sha256:01d0959807a451fe9fdd4da3e139cb5b77f7328baf2140feeaf233e1d777b729", + "sha256:024ce601f92d780ca1617ad4be5ac15b501cc2414970ffa2bb2bbc2bd5a68fa5", + "sha256:047d9425860a8c9544fed1b9584f0c8bcd31bcde9568b047c5e567a1025ecd6e", + "sha256:0a2088c126b6f72db6c9212ad827d0ba088c01d951cee25e758c450da732c138", + "sha256:0af5f9dee472371e36d6ae38bde009bd8ce65ac7335f55dcc240379d7bed1495", + "sha256:0b2e886624be5773e69cf32bcb8534aecdeb38943520b240fed3d5596a430f2f", + "sha256:0c5cbac6b55ad69cb6aa17ee9343dfbba903118fd530348c330211dc7aa756d1", + "sha256:0e0558693063c75f3d952abf645c78f3c5dfdd825a41d8c4d8156fc0b0da6e7e", + "sha256:0f37bed7319b848097085d7d48116f545985db988e2256b2e6f00563a3416ee6", + "sha256:0ffb87be160942d56d7b87b0fdf098e81ed565add09eaa1294268c7f3caac4c8", + "sha256:105245cc6b76f51e408451a844a54e6823bbd5a490ebfe5bdfc79798511ceded", + "sha256:10a68a9191f284fe9d501fef4efe93226e74df92ce7a24e301371293bd4918ae", + "sha256:14616a30fe6d0a48d0a48d1a633ab3b8bec4cf293aac65f32ed116f620adfd69", + "sha256:14754eb72feaa1e8ae528468f24250dd997b8e2188c3d2f593f9eba259e4b364", + "sha256:163c7ea522ea9365a8a57832dea7618e6cbdc3cd75f8c627663587459a4e328f", + "sha256:17d2cbbfa6ff20821396b25890f155f40c986f9cfbce5667759696d83504954f", + "sha256:190766dac95aab54cae5b152a56520fd99298f32a1266d66d27fdd1b5ac00f4e", + "sha256:1a0ccbfe93ca114c5d65a2471d52d8829e56d467c97b0e341cf5ee45410033b3", + "sha256:21f216669109e02ef3e2415ede07f4f8987f00de8cdfa0cc0b3440d42534f9f0", + "sha256:22e38b2bc176c5eb9c0a0e379f9d188ae4cd8b28c0f53b52bce7ab0a9e534657", + "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", + "sha256:2a4c6875c37aae9794308ec43e3530e4aa0d36579ce38d89979bbf89582002bb", + "sha256:34d8f2a5ffdceab9dcd97c7a016deb2308531d5f0fced2bb0c9e1df45b3363d7", + "sha256:350f6b0fe1ced61e778037fdc7613f4051c8baf64b1ee19371b42a3acdb016a0", + "sha256:37b7187197da6af3ee0b044dbc9625afd0c885f2800815b228a0e70f9a7f473d", + "sha256:38a0956dd92d918ad5feff3db8fcb4a5eb7dba114da917e1a88475619781b57b", + "sha256:3ba5aaf600edaf2a868a391779f7a85d93bed147854925f34edd24cc70a3e141", + "sha256:3bb0eae408fa1996d87247ca0d6a57b7fc1dcf83e8a5c47ab82c558c250d4adf", + "sha256:3f8e2384cb83ebd23fd07e9eada8ba64afc4c759cd94817433ab8c81ee4b403f", + "sha256:40cd05eaeb39e2bc8939451f033e57feaa2ac99e07dbca8afe2be450a4a3b6cf", + "sha256:43868297a5759a845fa3a483fb4392973a95fb1de891605a3728130c52b8f40f", + "sha256:452ff5da78d4720d7516a3a2abd804957532dd69296cb77319c193e3ffb87e24", + "sha256:467fe64138cfac771f0e949b938c2e1ada2b5af22f39692aa9258715e9ea613a", + "sha256:49517449b58d043023720aa58e62b2f74ce9b28f740a0b5d33971149553d72aa", + "sha256:497a2954adc25c08daff36f795077f63ad33e13f19bfff7736e72c785391534f", + "sha256:4a1fb393a2c9d202cb766c76208bd7945bc194eba8ac920ce98c6e458f0b524b", + "sha256:4bb7627fd7a968f41905a4d6343b0d63244a0623f006e9ed989fa2b78f4438a0", + "sha256:4d09384e75788861e046330308e7af54dd306aaf20eb760eb1d0de26b2bea2cb", + "sha256:4fefd4a815e362d4f011919d97d7b4a1e566f1dde83dc4ad8cfb5b41de1df68d", + "sha256:52e3c8d43cdfff587ceedce9deb25e6ae77daba560b626e97a56ddcad3756879", + "sha256:55624b3f321d84c403cb7d8e6e982f41ae233d85f85db54ba6286f7295dc8a9c", + "sha256:56c6b3652f945c9bc3ac6c8178cd93132b8d82dd581fcbc3a00676c51302bc1a", + "sha256:580b643b7fd2c295d83cad90d78419081f53fd532d1f1eb67ceb7060f61cff0d", + "sha256:59e8d40ab1f5a8597abcef00d04845155a5693b5da00d2c93dbe88f2050f2812", + "sha256:5df8afd26f162da59e218ac0eefaa01b01b2e6cd606cffa46608f699539246da", + "sha256:630f70c32b8066ddfd920350bc236225814ad94dfa493fe1910ee17fe4365cbb", + "sha256:66247d72ed62d5dd29752ffc1d3b88f135c6a8de8b5f63b7c14e973ef5bda19e", + "sha256:6865f6d3b7900ae020b495d599fcf3765653bc927951c1abb959017f81ae8287", + "sha256:6bf2f10f70acc7a2446965ffbc726e5fc0b272c97a90b485857e5c70022213eb", + "sha256:6c84378acd4f37d1b507dfa0d459b449e2321b3ba5f2338f9b085cf7a7ba95eb", + "sha256:6d46a180acdf6e87cc41dc15d8f5c2986e1e8739dc25dbb7dac826731ef381a4", + "sha256:756989334015e3335d087a27331659820d53ba432befdef6a718398b0a8493ad", + "sha256:75aa52fba2d96bf972e85451b99d8e19cc37ce26fd016f6d4aa60da9ab2b005f", + "sha256:7dd57515bebffd8ebd714d101d4c434063322e4fe24042e90ced41f18b6d3395", + "sha256:7f683a551e92bdb7fac545b9c6f9fa2aebdeefa61d607510b3533286fcab67f5", + "sha256:87a32d20759dc52a9e850fe1061b6e41ab28e2998d44168a8a341b99ded1dba0", + "sha256:8c2fcb12136530ed19572bbba61b407f655e3953ba669b96a35036a11a485793", + "sha256:8c91cdb30809a96d9ecf442ec9bc45e8cfaa0f7f8bdf534e082c2443a196727e", + "sha256:8c9854df0eaa610a23494c32a6f44a3a550fb398b6b51a56e8c6b9b3689578db", + "sha256:8e42332cf8276bb7645d310cdecca93a16920256a5b01bebf747365f86a1675b", + "sha256:8fe323540c255db0bffee79ad7f048c909f2ab0edb87a597e1c17da6a54e493c", + "sha256:967af5f238ebc2eb1da4e77af5492219fbd9b4b812347da39a7b5f5c72c0fa45", + "sha256:9a950b7cf54099c1209f455ac5970b1ea81410f2af60ed9eb3c3f14f0bfcf987", + "sha256:a1b20a9d56b2d81e2ff52ecc0670d583eaabaa55f402e8d16dd062373dbbe796", + "sha256:a506a77ddee1efcca81ecbeae27ade3e09cdf21a8ae854d766c2bb4f14053f92", + "sha256:a59c63061f1a07b861c004e53869eb1211ffd1a4acbca330e3322efa6dd02978", + "sha256:a650629970fa21ac1fb06ba25dabfc5b8a2054fcbf6ae97c758aa956b8dba802", + "sha256:a693fc5ed9bdd1c9e898013e0da4dcc640de7963a371c0bd458e50e046bf6438", + "sha256:aaea28ba20a9026dfa77f4b80369e51cb767c61e33a2d4043399c67bd95fb7c6", + "sha256:ad8850921d3a8d8ff6fbef790e773cecfc260bbfa0566998980d3fa8f520bc4a", + "sha256:ad887a8250eb47d3ab083d2f98db7f48098d13d42eb7a3b67d8a5c795f224ace", + "sha256:ae9408439537c5afdca05edd128a63f56a62680f4b3c234301055d7a2000220f", + "sha256:af7618b591bae552b40dbb6f93f5518328a949dac626ee75927bba1ecdeea9f4", + "sha256:b6819f83aef06f560cb15482d619d0e623ce9bf155115150a85ab11b8342a665", + "sha256:b8aa6f0bd8125ddd04a6593437bad6a7e70f300ff4180a531654aa2ab3f6d58f", + "sha256:b8eb3025f17b0a4c3cd08cda49acf312a19ad6e8a4edd9dbd591e6506d999402", + "sha256:b95494daf857602eccf4c18ca33337dd2be705bccdb6dddbfc9d513e6addb9d9", + "sha256:b9e5853bbd7264baca42ffc53391b490d65fe62849bf2c690fa3f6273dbcd0cb", + "sha256:bbc14f0365534d35a06970d6a83478b249752e922d662dc24d489af1aa0d1be7", + "sha256:be5bf4b3224948032a845d12ab0f69f208293742df96dc14c4ff9b09e508fc17", + "sha256:c5c97aa666cf70e667dfa5af945424ba1329af5dd988a437efeb3a09430389fb", + "sha256:c7a0e9b561e6460484318a7612e725df1145d46b0ef57c6b9866441bf6e27e0c", + "sha256:caebafea30ed049c57c673d0b36238b1748683be2593965614d7b0e99125c877", + "sha256:cbbc54e58b34c3bae389ef00046be0961f30fef7cb0dd9c7756aee376a4f7683", + "sha256:cc356250cffd6e78416cf5b40dc6a74f1edf3be8e834cf8862d9ed5265cf9b0e", + "sha256:ce9a40fbe52e57e7edf20113a4eaddfacac0561a0879734e636aa6d4bb5e3fb0", + "sha256:d191de6cbab2aff5de6c5723101705fd044b3e4c7cfd587a1929b5028b9714b3", + "sha256:d24f351e4d759f5054b641c81e8291e5d122af0fca5c72454ff77f7cbe492de8", + "sha256:d2d4e4787672911b48350df02ed3fa3fffdc2f2e8ca06dd6afdf34189b76a9dd", + "sha256:d8c112f7a90d8ca5d20213aa41eac690bb50a76da153e3afb3886418e61cb22e", + "sha256:d9890d68c45d1aeac5178ded1d1cccf3bc8d7accf1f976f79bf63099fb16e4bd", + "sha256:dadf95aa862714ea468a49ad1e09fe00fcc9ec67d122f6596a8d40caf6cec7d0", + "sha256:db6a3810eec08280a172a6cd541ff4a5f6a97b161d93ec94e6c4018917deb6b7", + "sha256:db9801fe021f59a5b375ab778973127ca0ac52429a26e2fd86aa9508f4d26eb7", + "sha256:e167bf899c3d724f9662ef00b4f7fef87a19c22b2fead198a6f68b263618df52", + "sha256:e1b93790ed0bc26feb72e2f08299691ceb6da5e9e14a0d13cc74f1869af327a0", + "sha256:e5b1413361cef15340ab9dc61523e653d25723e82d488ef7d60a12878227ed50", + "sha256:ecab51ad2462197a4c000b6d5701fc8585b80eecb90583635d7e327b7b6923eb", + "sha256:ed3b94c5e362a8a84d69642dbeac615452e8af9b8eb825b7bc9f31a53a1051e2", + "sha256:ed8358ae7d94ffb7c397cecb62cbac9578a83ecefc1eba27b9090ee910e2efb6", + "sha256:edfdcae97cdc5d1a89477c436b61f472c4d40971774ac4729c613b4b133163cb", + "sha256:ee25f82f53262f9ac93bd7e58e47ea1bdcc3393cef815847e397cba17e284210", + "sha256:f3be27440f7644ab9a13a6fc86f09cdd90b347c3c5e30c6d6d860de822d7cb53", + "sha256:f46a6e8597f9bd71b31cc708195d42b634c8527fecbcf93febf1052cacc1f16e", + "sha256:f6eb37d511bfae9e13e82cb4d1af36b91150466f24d9b2b8a9785816deb16605", + "sha256:f8d4916a81697faec6cb724a273bd5457e4c6c43d82b29f9dc02c5542fd21fc9", + "sha256:f93b2b2279883d1d0a9e1bd01f312d6fc315c5e4c1f09e112e4736e2f650bc4e", + "sha256:f9867e55590e0855bcec60d4f9a092b69476db64573c9fe17e92b0c50614c16a", + "sha256:f996b87b420995a9174b2a7c1a8daf7db4750be6848b03eb5e639674f7963773" + ], + "markers": "python_version >= '3.9'", + "version": "==6.6.4" }, "natural": { "hashes": [ @@ -638,58 +854,92 @@ }, "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:00f1a271e56d511d1569937c0447d7dce5a99a33ea0dec76673706360a051904", + "sha256:0c212cfdd90512fe722fa9bd620de4d46cda691415be86b2e02243242ae81873", + "sha256:0c6d7328c200c349e3a4c6d8c83e0a5ad029bdc2d417f234152bf34842d0fc8d", + "sha256:0e92a4e83341ef79d835ca21b8bd13e27c859e4e9e4d7b63defc6e58462a3710", + "sha256:11c6d71478e2cbea0a709e8a06365fa63da81da6498a53e4c4f065881d21ae8f", + "sha256:124d5ba71fee9c9902c4a7baa9425e663f7f0aecf73d31d54fe3dd357d62c1a7", + "sha256:18bd1435cb1f2857ceb59cfb7de6f92593ef7b831ccd1b9bfb28ca530e539dce", + "sha256:1c0603b1d2ffcd43a411d64797a19556ef76958aef1c182f22dc30860152a98a", + "sha256:2030c01cbf77bc67bee7eef1e7e31ecf28649353987775e3583062c752da0077", + "sha256:2039b7847ba3eec1f5886e75e6763a16e18c68a63efc4b029ddf994821e2e66b", + "sha256:212e67806525d2561efbfe9e799633b17eb668b8964abed6b5319b2f1cfbae1f", + "sha256:215c595c792a87d4407cb72dd5e0f6ee8e694ceeb7f9102b533c5a9bf2a916bb", + "sha256:22724d80ee5a815a44fc76274bb7ba2e7464f5564aacb6ecddaa9970a83e3225", + "sha256:29be5ac4164aa8bdcba5fa0700a3c9c316b411d8ed9d39ef8a882541bd452fae", + "sha256:29cb1f1b008d936803e2da3d7cba726fc47232c45df531b29edf0b232dd737e7", + "sha256:2b7b153ed90ababadbef5c3eb39549f9476890d339cf47af563aea7e07db2451", + "sha256:2d68bf97a771836687107abfca089743885fb664b90138d8761cce61d5625d55", + "sha256:317bbe2c069bbc757b1a2e4105b64aacd3bc78279b66a6b9e51e846e4809f804", + "sha256:3782d2c60b8116772aea8d9b7905221437fdf53e7277282e8d8b07c220f96cca", + "sha256:3d721fee37380a44f9d9ce6c701b3960239f4fb3d5ceea7f31cbd43882edaa2f", + "sha256:414f71e3bdd5573893bf5ecdf35c32b213ed20aa15536fe2f588f946c318824f", + "sha256:524b765ad888dc5518bbce12c77c2e83dee1ed6b0992c1790cc5fb49bb4b6667", + "sha256:56afaf1e9b02302ba636151cfc49929c1bb66b98794291afd0e5f20fecaf757c", + "sha256:58533f9e8266cb0ac298e259ed7b4d42ed3fa0b78ce76860626164de49e0d467", + "sha256:5ff835b5d3e67d9207343effb03760c00335f8b5285bfceefd4dc967b0e48f6a", + "sha256:61dcdad16da5bb486d7227a37a2e789c429397793a6955227cedbd7252eb5a27", + "sha256:6890ace0809627b0dff19cfad92d69d0fa3f089d3e359a2a532507bb6ba34efb", + "sha256:6be2f1b5d3dc99a5ce5ce162fc741c22ba9f3443d3dd586e6a1211b7bc87bc7b", + "sha256:6e8e0c3b85575a32f2ffa59de455f85ce002b8bdc0662d6b9c2ed6d80ab5d204", + "sha256:73b92a5b69f31b1a58c0c7e31080aeaec49c6e01b9522e71ff38d08f15aa56de", + "sha256:7909ae2460f5f494fecbcd10613beafe40381fd0316e35d6acb5f3a05bfda167", + "sha256:79b44319268af2eaa3e315b92298de9a0067ade6e6003ddaef72f8e0bedb94f1", + "sha256:828e3149ad8815dc14468f36ab2a4b819237c155ee1370341b91ea4c8672d2ee", + "sha256:84fd82870b97ae3cdcea9d8746e592b6d40e1e4d4527835fc520c588d2ded04f", + "sha256:88dcfc514cfd1b0de038443c7b3e6a9797ffb1b3674ef1fd14f701a13397f82d", + "sha256:8ab962931015f170b97a3dd7bd933399c1bae8ed8ad0fb2a7151a5654b6941c7", + "sha256:8b13974dc8ac6ba22feaa867fc19135a3e01a134b4f7c9c28162fed4d615008a", + "sha256:8c752089db84333e36d754c4baf19c0e1437012242048439c7e80eb0e6426e3b", + "sha256:8e531abd745f51f8035e207e75e049553a86823d189a51809c078412cefb399a", + "sha256:90368277087d4af32d38bd55f9da2ff466d25325bf6167c8f382d8ee40cb2bbc", + "sha256:913f629adef31d2d350d41c051ce7e33cf0fd06a5d1cb28d49b1899b23b903aa", + "sha256:976c6f1975032cc327161c65d4194c549f2589d88b105a5e3499429a54479770", + "sha256:97dceed87ed9139884a55db8722428e27bd8452817fbf1869c58b49fecab1120", + "sha256:9b8761b6cf04a856eb544acdd82fc594b978f12ac3602d6374a7edb9d86fd2c2", + "sha256:9d2ae0cc6aeb669633e0124531f342a17d8e97ea999e42f12a5ad4adaa304c5f", + "sha256:9d8787bdfbb65a85ea76d0e96a3b1bed7bf0fbcb16d40408dc1172ad784a49d2", + "sha256:9dba358d55aee552bd868de348f4736ca5a4086d9a62e2bfbbeeb5629fe8b0cc", + "sha256:9f1587f26c235894c09e8b5b7636a38091a9e6e7fe4531937534749c04face43", + "sha256:a0169ebd1cbd94b26c7a7ad282cf5c2744fce054133f959e02eb5265deae1872", + "sha256:ac9e05f25627ffc714c21f8dfe3a579445a5c392a9c8ae7ba1d0e9fb5333f56e", + "sha256:ae8b756575aaa2a855a75192f356bbda11a89169830e1439cfb1a3e1a6dde7be", + "sha256:af40c6612fd2a4b00de648aa26d18186cd1322330bd3a3cc52f87c699e995810", + "sha256:b67e71e47caa6680d1b6f075a396d04fa6ca8ca09aafb428731da9b3ea32a5a6", + "sha256:b822caf5b9752bc6f246eb08124c3d12bf2175b66ab74bac2ef3bbf9221ce1b2", + "sha256:ba21dbb2493e9c653eaffdc38819b004b7b1b246fb77bfc93dc016fe664eac91", + "sha256:bb93562146120bb51e6b154962d3dadc678ed0fce96513fa6bc06599bb6f6edc", + "sha256:bc779b4f4bba2847d0d2940081a7b6f7b5877e05408ffbb74fa1faf4a136c424", + "sha256:bc8bc85b81b6ac9fc4dae393a8c159b817f4c2c9dee5d12b773bddb3b95fc07e", + "sha256:bd4b909ce4c50faa2192da6bb684d9848d4510b736b0611b6ab4020ea6fd2d23", + "sha256:bfc27516ec46f4520b18ef645864cee168d2a027dbf32c5537cb1f3e3c22dac1", + "sha256:c5189a5dab8b0312eadaf9d58d3049b6a52c454256493a557405e77a3d67ab7f", + "sha256:c9416cc19a349c167ef76135b2fe40d03cea93680428efee8771f3e9fb66079d", + "sha256:cf4b81227ec86935568c7edd78352a92e97af8da7bd70bdfdaa0d2e0011a1ab4", + "sha256:d2489b241c19582b3f1430cc5d732caefc1aaf378d97e7fb95b9e56bed11725f", + "sha256:d61cd543d69715d5fc0a690c7c6f8dcc307bc23abef9738957981885f5f38229", + "sha256:d7d012ebddffcce8c85734a6d9e5f08180cd3857c5f5a3ac70185b43775d043d", + "sha256:d7d18dd34ea2e860553a579df02041845dee0af8985dff7f8661306f95504ddf", + "sha256:d8b11701bc43be92ea42bd454910437b355dfb63696c06fe953ffb40b5f763b4", + "sha256:dd759f75d6b8d1b62012b7f5ef9461d03c804f94d539a5515b454ba3a6588038", + "sha256:e0a23b41f8f98b4e61150a03f83e4f0d566880fe53519d445a962929a4d21045", + "sha256:e44fbe4000bd321d9f3b648ae46e0196d21577cf66ae684a96ff90b1f7c93633", + "sha256:e6fbaf48a744b94091a56c62897b27c31ee2da93d826aa5b207131a1e13d4064", + "sha256:e8f6a7a27d7b7bec81bd5924163e9af03d49bbb63013f107b48eb5d16db711bc", + "sha256:eabcf2e84f1d7105f84580e03012270c7e97ecb1fb1618bda395061b2a84a049", + "sha256:f5aa4682912a450c2db89cbd92d356fef47e115dffba07992555542f344d301b", + "sha256:f66b001332a017d7945e177e282a40b6997056394e3ed7ddb41fb1813b83e824", + "sha256:f83abab5bacb76d9c821fd5c07728ff224ed0e52d7a71b7b3de822f3df04e15c", + "sha256:f8d902867b699bcd09c176a280b1acdab57f924489033e53d0afe79817da37e6", + "sha256:f9d4a5e041ae435b815e568537755773d05dac031fee6a57b4ba70897a44d9d2", + "sha256:fafb1a99d740523d964b15c8db4eabbfc86ff29f84898262bf6e3e4c9e97e43e", + "sha256:fbecb9709111be913ae6879b07bafd4b0785b44c1eb5cac8ac76da048b3885a1", + "sha256:fd7ff459fb393358d3a155d25b275c60b07a2c83dcd7ea962b1923f5a1134569", + "sha256:ff94112e0098470b665cb0ed06efb187154b63649403b8d5e9aedeb482b4548c" + ], + "markers": "python_version >= '3.9'", + "version": "==3.11.3" }, "packaging": { "hashes": [ @@ -710,217 +960,429 @@ }, "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" + "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2", + "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214", + "sha256:040a5b691b0713e1f6cbe222e0f4f74cd233421e105850ae3b3c0ceda520f42e", + "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59", + "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50", + "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632", + "sha256:092c80c76635f5ecb10f3f83d76716165c96f5229addbd1ec2bdbbda7d496e06", + "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a", + "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51", + "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced", + "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f", + "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12", + "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8", + "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6", + "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580", + "sha256:19d2ff547c75b8e3ff46f4d9ef969a06c30ab2d4263a9e287733aa8b2429ce8f", + "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac", + "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860", + "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd", + "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722", + "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8", + "sha256:23cff760a9049c502721bdb743a7cb3e03365fafcdfc2ef9784610714166e5a4", + "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673", + "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788", + "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542", + "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e", + "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd", + "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8", + "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523", + "sha256:3cee80663f29e3843b68199b9d6f4f54bd1d4a6b59bdd91bceefc51238bcb967", + "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809", + "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477", + "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027", + "sha256:4445fa62e15936a028672fd48c4c11a66d641d2c05726c7ec1f8ba6a572036ae", + "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b", + "sha256:465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c", + "sha256:48d254f8a4c776de343051023eb61ffe818299eeac478da55227d96e241de53f", + "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e", + "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b", + "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7", + "sha256:527b37216b6ac3a12d7838dc3bd75208ec57c1c6d11ef01902266a5a0c14fc27", + "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361", + "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae", + "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d", + "sha256:6359a3bc43f57d5b375d1ad54a0074318a0844d11b76abccf478c37c986d3cfc", + "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58", + "sha256:65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad", + "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6", + "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024", + "sha256:6a418691000f2a418c9135a7cf0d797c1bb7d9a485e61fe8e7722845b95ef978", + "sha256:6abdbfd3aea42be05702a8dd98832329c167ee84400a1d1f61ab11437f1717eb", + "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d", + "sha256:7107195ddc914f656c7fc8e4a5e1c25f32e9236ea3ea860f257b0436011fddd0", + "sha256:71f511f6b3b91dd543282477be45a033e4845a40278fa8dcdbfdb07109bf18f9", + "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f", + "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874", + "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa", + "sha256:7aee118e30a4cf54fdd873bd3a29de51e29105ab11f9aad8c32123f58c8f8081", + "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149", + "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6", + "sha256:7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d", + "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd", + "sha256:819931d25e57b513242859ce1876c58c59dc31587847bf74cfe06b2e0cb22d2f", + "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c", + "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31", + "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e", + "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db", + "sha256:89bd777bc6624fe4115e9fac3352c79ed60f3bb18651420635f26e643e3dd1f6", + "sha256:8dc70ca24c110503e16918a658b869019126ecfe03109b754c402daff12b3d9f", + "sha256:91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494", + "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69", + "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94", + "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77", + "sha256:97afb3a00b65cc0804d1c7abddbf090a81eaac02768af58cbdcaaa0a931e0b6d", + "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7", + "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a", + "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438", + "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288", + "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b", + "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635", + "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3", + "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d", + "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe", + "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0", + "sha256:b5f56c3f344f2ccaf0dd875d3e180f631dc60a51b314295a3e681fe8cf851fbe", + "sha256:be5463ac478b623b9dd3937afd7fb7ab3d79dd290a28e2b6df292dc75063eb8a", + "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805", + "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8", + "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36", + "sha256:cadc9e0ea0a2431124cde7e1697106471fc4c1da01530e679b2391c37d3fbb3a", + "sha256:cc3e831b563b3114baac7ec2ee86819eb03caa1a2cef0b481a5675b59c4fe23b", + "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e", + "sha256:d000f46e2917c705e9fb93a3606ee4a819d1e3aa7a9b442f6444f07e77cf5e25", + "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12", + "sha256:e5c5858ad8ec655450a7c7df532e9842cf8df7cc349df7225c60d5d348c8aada", + "sha256:e67d793d180c9df62f1f40aee3accca4829d3794c95098887edc18af4b8b780c", + "sha256:ea944117a7974ae78059fcc1800e5d3295172bb97035c0c1d9345fca1419da71", + "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d", + "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c", + "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6", + "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1", + "sha256:f1f182ebd2303acf8c380a54f615ec883322593320a9b00438eb842c1f37ae50", + "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653", + "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c", + "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4", + "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3" + ], + "markers": "python_version >= '3.9'", + "version": "==11.3.0" + }, + "propcache": { + "hashes": [ + "sha256:009093c9b5dbae114a5958e6a649f8a5d94dd6866b0f82b60395eb92c58002d4", + "sha256:015b2ca2f98ea9e08ac06eecc409d5d988f78c5fd5821b2ad42bc9afcd6b1557", + "sha256:01c0ebc172ca28e9d62876832befbf7f36080eee6ed9c9e00243de2a8089ad57", + "sha256:02e071548b6a376e173b0102c3f55dc16e7d055b5307d487e844c320e38cacf2", + "sha256:0363a696a9f24b37a04ed5e34c2e07ccbe92798c998d37729551120a1bb744c4", + "sha256:0596d2ae99d74ca436553eb9ce11fe4163dc742fcf8724ebe07d7cb0db679bb1", + "sha256:075ca32384294434344760fdcb95f7833e1d7cf7c4e55f0e726358140179da35", + "sha256:077a32977399dc05299b16e793210341a0b511eb0a86d1796873e83ce47334cc", + "sha256:082a643479f49a6778dcd68a80262fc324b14fd8e9b1a5380331fe41adde1738", + "sha256:087e2d3d7613e1b59b2ffca0daabd500c1a032d189c65625ee05ea114afcad0b", + "sha256:0964c55c95625193defeb4fd85f8f28a9a754ed012cab71127d10e3dc66b1373", + "sha256:0b04ac2120c161416c866d0b6a4259e47e92231ff166b518cc0efb95777367c3", + "sha256:0b12df77eb19266efd146627a65b8ad414f9d15672d253699a50c8205661a820", + "sha256:0cd30341142c68377cf3c4e2d9f0581e6e528694b2d57c62c786be441053d2fc", + "sha256:0ea11fceb31fa95b0fa2007037f19e922e2caceb7dc6c6cac4cb56e2d291f1a2", + "sha256:184c779363740d6664982ad05699f378f7694220e2041996f12b7c2a4acdcad0", + "sha256:1927b78dd75fc31a7fdc76cc7039e39f3170cb1d0d9a271e60f0566ecb25211a", + "sha256:1cdabd60e109506462e6a7b37008e57979e737dc6e7dfbe1437adcfe354d1a0a", + "sha256:1e7fa29c71ffa8d6a37324258737d09475f84715a6e8c350f67f0bc8e5e44993", + "sha256:1e7fd82d4a5b7583588f103b0771e43948532f1292105f13ee6f3b300933c4ca", + "sha256:2015218812ee8f13bbaebc9f52b1e424cc130b68d4857bef018e65e3834e1c4d", + "sha256:213eb0d3bc695a70cffffe11a1c2e1c2698d89ffd8dba35a49bc44a035d45c93", + "sha256:2166466a666a5bebc332cd209cad77d996fad925ca7e8a2a6310ba9e851ae641", + "sha256:227892597953611fce2601d49f1d1f39786a6aebc2f253c2de775407f725a3f6", + "sha256:22f589652ee38de96aa58dd219335604e09666092bc250c1d9c26a55bcef9932", + "sha256:236c8da353ea7c22a8e963ab78cddb1126f700ae9538e2c4c6ef471e5545494b", + "sha256:24403152e41abf09488d3ae9c0c3bf7ff93e2fb12b435390718f21810353db28", + "sha256:26692850120241a99bb4a4eec675cd7b4fdc431144f0d15ef69f7f8599f6165f", + "sha256:2a4bf309d057327f1f227a22ac6baf34a66f9af75e08c613e47c4d775b06d6c7", + "sha256:2af6de831a26f42a3f94592964becd8d7f238551786d7525807f02e53defbd13", + "sha256:2c46d37955820dd883cf9156ceb7825b8903e910bdd869902e20a5ac4ecd2c8b", + "sha256:33ad7d37b9a386f97582f5d042cc7b8d4b3591bb384cf50866b749a17e4dba90", + "sha256:34000e31795bdcda9826e0e70e783847a42e3dcd0d6416c5d3cb717905ebaec0", + "sha256:381c84a445efb8c9168f1393a5a7c566de22edc42bfe207a142fff919b37f5d9", + "sha256:399c73201d88c856a994916200d7cba41d7687096f8eb5139eb68f02785dc3f7", + "sha256:39f0f6a3b56e82dc91d84c763b783c5c33720a33c70ee48a1c13ba800ac1fa69", + "sha256:4596c12aa7e3bb2abf158ea8f79eb0fb4851606695d04ab846b2bb386f5690a1", + "sha256:4a52c25a51d5894ba60c567b0dbcf73de2f3cd642cf5343679e07ca3a768b085", + "sha256:4bf95be277fbb51513895c2cecc81ab12a421cdbd8837f159828a919a0167f96", + "sha256:4c2735d3305e6cecab6e53546909edf407ad3da5b9eeaf483f4cf80142bb21be", + "sha256:4c491462e1dc80f9deb93f428aad8d83bb286de212837f58eb48e75606e7726c", + "sha256:515b610a364c8cdd2b72c734cc97dece85c416892ea8d5c305624ac8734e81db", + "sha256:545987971b2aded25ba4698135ea0ae128836e7deb6e18c29a581076aaef44aa", + "sha256:55a54de5266bc44aa274915cdf388584fa052db8748a869e5500ab5993bac3f4", + "sha256:566552ed9b003030745e5bc7b402b83cf3cecae1bade95262d78543741786db5", + "sha256:5710b1c01472542bb024366803812ca13e8774d21381bcfc1f7ae738eeb38acc", + "sha256:5a531d29d7b873b12730972237c48b1a4e5980b98cf21b3f09fa4710abd3a8c3", + "sha256:5b113feeda47f908562d9a6d0e05798ad2f83d4473c0777dafa2bc7756473218", + "sha256:5e0a5bc019014531308fb67d86066d235daa7551baf2e00e1ea7b00531f6ea85", + "sha256:626ec13592928b677f48ff5861040b604b635e93d8e2162fb638397ea83d07e8", + "sha256:659a0ea6d9017558ed7af00fb4028186f64d0ba9adfc70a4d2c85fcd3d026321", + "sha256:65ff56a31f25925ef030b494fe63289bf07ef0febe6da181b8219146c590e185", + "sha256:681a168d06284602d56e97f09978057aa88bcc4177352b875b3d781df4efd4cb", + "sha256:6a6a36b94c09711d6397d79006ca47901539fbc602c853d794c39abd6a326549", + "sha256:6d1f67dad8cc36e8abc2207a77f3f952ac80be7404177830a7af4635a34cbc16", + "sha256:6ebc6e2e65c31356310ddb6519420eaa6bb8c30fbd809d0919129c89dcd70f4c", + "sha256:71a400b2f0b079438cc24f9a27f02eff24d8ef78f2943f949abc518b844ade3d", + "sha256:71c45f02ffbb8a21040ae816ceff7f6cd749ffac29fc0f9daa42dc1a9652d577", + "sha256:728d98179e92d77096937fdfecd2c555a3d613abe56c9909165c24196a3b5012", + "sha256:72b51340047ac43b3cf388eebd362d052632260c9f73a50882edbb66e589fd44", + "sha256:779aaae64089e2f4992e993faea801925395d26bb5de4a47df7ef7f942c14f80", + "sha256:783e91595cf9b66c2deda17f2e8748ae8591aa9f7c65dcab038872bfe83c5bb1", + "sha256:790286d3d542c0ef9f6d0280d1049378e5e776dcba780d169298f664c39394db", + "sha256:7aa8cc5c94e682dce91cb4d12d7b81c01641f4ef5b3b3dc53325d43f0e3b9f2e", + "sha256:7d51f70f77950f8efafed4383865d3533eeee52d8a0dd1c35b65f24de41de4e0", + "sha256:7da5c4c72ae40fd3ce87213ab057db66df53e55600d0b9e72e2b7f5a470a2cc4", + "sha256:7dfa60953169d2531dd8ae306e9c27c5d4e5efe7a2ba77049e8afdaece062937", + "sha256:7ea86eb32e74f9902df57e8608e8ac66f1e1e1d24d1ed2ddeb849888413b924d", + "sha256:7f088e21d15b3abdb9047e4b7b7a0acd79bf166893ac2b34a72ab1062feb219e", + "sha256:83ae2f5343f6f06f4c91ae530d95f56b415f768f9c401a5ee2a10459cf74370b", + "sha256:84f847e64f4d1a232e50460eebc1196642ee9b4c983612f41cd2d44fd2fe7c71", + "sha256:858eaabd2191dd0da5272993ad08a748b5d3ae1aefabea8aee619b45c2af4a64", + "sha256:8659f995b19185179474b18de8755689e1f71e1334d05c14e1895caa4e409cf7", + "sha256:88d50d662c917ec2c9d3858920aa7b9d5bfb74ab9c51424b775ccbe683cb1b4e", + "sha256:892a072e5b19c3f324a4f8543c9f7e8fc2b0aa08579e46f69bdf0cfc1b440454", + "sha256:8d18d796ffecdc8253742fd53a94ceee2e77ad149eb9ed5960c2856b5f692f71", + "sha256:92bc43a1ab852310721ce856f40a3a352254aa6f5e26f0fad870b31be45bba2e", + "sha256:944de70384c62d16d4a00c686b422aa75efbc67c4addaebefbb56475d1c16034", + "sha256:94a278c45e6463031b5a8278e40a07edf2bcc3b5379510e22b6c1a6e6498c194", + "sha256:94b0f7407d18001dbdcbb239512e753b1b36725a6e08a4983be1c948f5435f79", + "sha256:96153e037ae065bb71cae889f23c933190d81ae183f3696a030b47352fd8655d", + "sha256:9ba68c57cde9c667f6b65b98bc342dfa7240b1272ffb2c24b32172ee61b6d281", + "sha256:a1d5e474d43c238035b74ecf997f655afa67f979bae591ac838bb3fbe3076392", + "sha256:a4efbaf10793fd574c76a5732c75452f19d93df6e0f758c67dd60552ebd8614b", + "sha256:a60634a9de41f363923c6adfb83105d39e49f7a3058511563ed3de6748661af6", + "sha256:a7f06f077fc4ef37e8a37ca6bbb491b29e29db9fb28e29cf3896aad10dbd4137", + "sha256:a8ef2ea819549ae2e8698d2ec229ae948d7272feea1cb2878289f767b6c585a4", + "sha256:a9725d96a81e17e48a0fe82d0c3de2f5e623d7163fec70a6c7df90753edd1bec", + "sha256:ab9c1bd95ebd1689f0e24f2946c495808777e9e8df7bb3c1dfe3e9eb7f47fe0d", + "sha256:abe04e7aa5ab2e4056fcf3255ebee2071e4a427681f76d4729519e292c46ecc1", + "sha256:ae3adf88a66f5863cf79394bc359da523bb27a2ed6ba9898525a6a02b723bfc5", + "sha256:b2f29697d1110e8cdf7a39cc630498df0082d7898b79b731c1c863f77c6e8cfc", + "sha256:b730048ae8b875e2c0af1a09ca31b303fc7b5ed27652beec03fa22b29545aec9", + "sha256:bcb5bfac5b9635e6fc520c8af6efc7a0a56f12a1fe9e9d3eb4328537e316dd6a", + "sha256:bd6c6dba1a3b8949e08c4280071c86e38cb602f02e0ed6659234108c7a7cd710", + "sha256:c0e1c218fff95a66ad9f2f83ad41a67cf4d0a3f527efe820f57bde5fda616de4", + "sha256:c1443fa4bb306461a3a8a52b7de0932a2515b100ecb0ebc630cc3f87d451e0a9", + "sha256:c1ad731253eb738f9cadd9fa1844e019576c70bca6a534252e97cf33a57da529", + "sha256:c20d796210720455086ef3f85adc413d1e41d374742f9b439354f122bbc3b528", + "sha256:c2e274f3d1cbb2ddcc7a55ce3739af0f8510edc68a7f37981b2258fa1eedc833", + "sha256:c3f4b125285d354a627eb37f3ea7c13b8842c7c0d47783581d0df0e272dbf5f0", + "sha256:c9b8119244d122241a9c4566bce49bb20408a6827044155856735cf14189a7da", + "sha256:cd6e22255ed73efeaaeb1765505a66a48a9ec9ebc919fce5ad490fe5e33b1555", + "sha256:cd8684f628fe285ea5c86f88e1c30716239dc9d6ac55e7851a4b7f555b628da3", + "sha256:cdb0cecafb528ab15ed89cdfed183074d15912d046d3e304955513b50a34b907", + "sha256:d74aa60b1ec076d4d5dcde27c9a535fc0ebb12613f599681c438ca3daa68acac", + "sha256:d7f008799682e8826ce98f25e8bc43532d2cd26c187a1462499fa8d123ae054f", + "sha256:d9a8d277dc218ddf04ec243a53ac309b1afcebe297c0526a8f82320139b56289", + "sha256:da47070e1340a1639aca6b1c18fe1f1f3d8d64d3a1f9ddc67b94475f44cd40f3", + "sha256:da584d917a1a17f690fc726617fd2c3f3006ea959dae5bb07a5630f7b16f9f5f", + "sha256:de536cf796abc5b58d11c0ad56580215d231d9554ea4bb6b8b1b3bed80aa3234", + "sha256:de8e310d24b5a61de08812dd70d5234da1458d41b059038ee7895a9e4c8cae79", + "sha256:df7107a91126a495880576610ae989f19106e1900dd5218d08498391fa43b31d", + "sha256:e0ce7f3d1faf7ad58652ed758cc9753049af5308b38f89948aa71793282419c5", + "sha256:e2d01fd53e89cb3d71d20b8c225a8c70d84660f2d223afc7ed7851a4086afe6d", + "sha256:e5227da556b2939da6125cda1d5eecf9e412e58bc97b41e2f192605c3ccbb7c2", + "sha256:e6229ad15366cd8b6d6b4185c55dd48debf9ca546f91416ba2e5921ad6e210a6", + "sha256:e878553543ece1f8006d0ba4d096b40290580db173bfb18e16158045b9371335", + "sha256:eb77a85253174bf73e52c968b689d64be62d71e8ac33cabef4ca77b03fb4ef92", + "sha256:f114a3e1f8034e2957d34043b7a317a8a05d97dfe8fddb36d9a2252c0117dbbc", + "sha256:f495007ada16a4e16312b502636fafff42a9003adf1d4fb7541e0a0870bc056f", + "sha256:f5c82af8e329c3cdc3e717dd3c7b2ff1a218b6de611f6ce76ee34967570a9de9" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.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:00538826d2eaf4a0e4becb0753b0ac8d652334603c445c9566c9eb273657eb4c", + "sha256:066f3caa07c85e1a094aebd9e7a7bb3f3b2d97cff2276665693dd5c0cc81cf84", + "sha256:0aed0974eab3131d832e7e84a73ddb0dddbc57393cd8c0788d68a759a78c4a7b", + "sha256:1571a7055c03a95d5270c914034eac7f8bfa1b432fc1de53d871b821752191a4", + "sha256:1732db81e348bfce19c9bf9448ba660aea03042eeeea282824da1604a5bd4dcf", + "sha256:1dbbf0cfb39be63598b4cdc2522960627bf2f523e49c4349fb64b0499902ec7c", + "sha256:218619b912cef7c64a339ab0e231daea10c994a05699740714dff8c428b9694a", + "sha256:23d50a0842e8dbdddf870a7218a7ab5053b68892706b3a391ecb3d657424d266", + "sha256:29daa36548c04cdcd1a78ae187a4b7b003f0b357a2f4f1f98f9863373eedc759", + "sha256:2c296ab94d1974f8d2f76c499755a9ce31ffd4986e8898ef19b90e32525f7d84", + "sha256:2d5cac829da91ade70ce1af97dad448c6cd4778b48facbce1b015e16ced93642", + "sha256:30ceed06f3bf5eff865a34d21562c25a7f3dad0ed336b9dd415330e03a6c50c4", + "sha256:30d197180af626bb56f17e1fa54640838d7d12ed0f74665a3014f7155435b199", + "sha256:30feeab492ac609f38a0d30fab3dc1789bd19c48f725b2955bcaaef516e32a21", + "sha256:3139ec1f4450a4b253386035c5ecd2722582ae3320a456df5021ffe3f174260a", + "sha256:31b85ad00422b38f426e5733a71dfb7ee7eb65a99ea328c508d4f552b1760dc8", + "sha256:35ff1ec260372c97ed688efd5b3c6e5481f2274dea08f6c4ea864c195a9673c6", + "sha256:3784b80d797bcc2ff2bf3d4b27f46d8516fe1707ff3b82c2580dc977537387f9", + "sha256:386da2581db4ea2832629e275c061103b0be32f9391c5dfaea7f6040951950ad", + "sha256:3b44e54cad31d3c3be5e8149ac36bc1c163ec86e0664293402f6f846fb22ad00", + "sha256:3bd81ad69f607803f531ff5cfa1262391fa06e78488c13495cee0f70d02e0287", + "sha256:3d5300a598ad48bbf169fba1f2b2e4cf7ab229e7c1a48d8c1166f9ccf1755cb3", + "sha256:3db6b6439e378115572fa317053f3ee6eecb39097baafe9292320ff1a9df73e3", + "sha256:3ef1ab7abbd238bb2dbbe871c3ea39f5a7fc63547c015820c1e24d0d494a1689", + "sha256:45d3254a694459fdb0640ef08724ca9d4b4f6ff6d7161c9b526d7d2e2111379e", + "sha256:4b6f7581793d8bb3014028b8397f6f80b99db8842da58f4409839c29b16397ad", + "sha256:4da2e805ed8c789b9444ef4053f6ef8040cd13b0c1ca6d3c4fe6f9369c458cb4", + "sha256:5344d52efa37df74728505a81dd52c15df639adffd166f7ddca7a6318ecdb605", + "sha256:5d69e2034160e1219665decb8140e439afc7a7afcfd4adff08eb0f6142405c3e", + "sha256:5d70324ca1d82c6c4b00aa678347f7560d1ef2ce1d181978903459a97751543a", + "sha256:5e1ab899bb0763dea5d6569300aab3a205572e6e2d0ef1a33b8cf2b86d1312a4", + "sha256:6195208b16cce1a7b121727710a6f78e8403878c1017ab5a3f92158b048cec34", + "sha256:66c310773abe42479302abf064832f4a37c8d7f788f4d5ee0d43cbad35cf5ff4", + "sha256:6f74b1d944a50fa12c5006fd10b45e1a45da0c5d15570919ce48be88e428264c", + "sha256:6f751f5a0e4913b2787f237c2c69c11a53f599269012feaa9fb86d7cef3aec26", + "sha256:702d21823996f139874aba5aa9bb786d69e93bde6e3915b99832eb4e335d31ae", + "sha256:719f7ddff024fdacde97b926b4b26d0cc25901d5ef68bb994a581c420069936d", + "sha256:742fbaa44b418237dbd6bf8cdab205c98b3edb334436a972ad341b0ea296fb47", + "sha256:7570e0b50db619b2ee370461c462617225dc3a3f63f975c6f117e2f0c94f82ca", + "sha256:775d99966e28c8abd9910ddef2de0f1e173afc5a11cea9f184613c747373ab80", + "sha256:77bf82dc0beb81262bf1c7f546e1c1fde4992e5c8a2343b867ca201b85f9e1aa", + "sha256:7830709c23bbc43fbaefbb3dde57bdd295dc86732504b9d2e65044df8fd5e9fb", + "sha256:7aba9a312a620052133437f2363aae90ae4695ee61cb2ee07cbb9951d4c69ddd", + "sha256:80752133442dc7e6dd9410cec227c49f69283c038c316a8585cca05ec32c2766", + "sha256:836725754c32363d2c5d15b931b3ebd46b20185c02e850672cb6c5f0452c1e80", + "sha256:83a7401d7520fa14b00d85d68bcca47a0676c69996e8515d53733972286f9739", + "sha256:84b0b402dd333403fdce0e204aef1ef834d839c439c0c1aa143dc7d1237bb197", + "sha256:84fde689557361764f052850a2d68916050adbfd9321f6105aca1d8f1a9bd49b", + "sha256:87dab618fe116f1936f8461df5970fcf0befeba7531a36b0a86321332ff9c20b", + "sha256:8a75a406432ce39ce0ca41edff7486df6c970eb0fe5cfbe292f195a6b8654461", + "sha256:910ce19a549f493fb55cfd1d7d70960706a03de6bfc896c1429fc5d6216df77e", + "sha256:9518514e3e85646bac798d94d34bf5b8741ee0cb580512e8450ce884f526b7cf", + "sha256:95bc81f83fadb67f7f87914f216a0e141555ee17fd7f56e25aa0cc165e99e53b", + "sha256:96e07d5a8b733d753e37d1f7138e7321d2316bb3f0f663ab4e3d500fabc82807", + "sha256:97d971b3a88a803bb95ff8a40ea4d68da59319eb8b59e924e318e2560af8c16d", + "sha256:9a00408105901ede92e318eecb46d0e661d7d093d0a9b1224c71b5dd94f79e83", + "sha256:9d0c543bdeefa4794582ef48f3c59e5e7a43d672a4bfad9cbbd531e897911690", + "sha256:a4060d8556c908660512d42df1f4a874e4e91b81f79e3a9090afedc7690ea5ba", + "sha256:a98fac4a3d4f780817016b6f00a8a2c2f41df5d25dfa8e5b1aa0d783645a6566", + "sha256:aa160dc9e785212c49c12bb891e242c949758b99542946cc8e2098ef391f93b0", + "sha256:aca981fc00c8af8d5b9254ea5c2f276df8ece089b081af1ef4856fbcfc7c698a", + "sha256:afc6503adf8b35c21183b9387be64ca6810644ef54c9ef6c99d1d5635c01601b", + "sha256:b50ca218a3e2e23cbda395fd002d030385202fbb8182aa87e11bea0a568bd0b8", + "sha256:b93d624560ba52287873bacff70b42c99943821ecbc810b959b0953560f53c36", + "sha256:bac55842047567ddae177fb8189b89a60633ac956d5d37260f7f71b517fd8b87", + "sha256:c0eec184df42fc82e43197e073f9cc8f93b25ad2f11f230c64c2dc1c80dbc078", + "sha256:c2971af3a4094280f7c24293ff4d361689c175c1ebcbea6b3c1560eaff7cb240", + "sha256:c2af7a9d3afb63da31df1456d38b91555a6c147710a116d5cc70ab1e9f457a4f", + "sha256:c863d9003ca0ce7df26429007859afd2a621d3276ed9fef154a9123db9252557", + "sha256:c9d839b5700542b27c1a0d359cbfad6496341e7c819c7fea63db9588857065ed", + "sha256:cb711a66246561f1cae51244deef700eef75481a70d99611fd3c8ab5bd69ab49", + "sha256:cdac992206756b024b371760c55719eb5cd9d6b2cb25a8d5a04ae1b0ff426232", + "sha256:cf306f3951740d7bed36149a6d8d656a7d5432dd4bbc6af3bb6554361fc87401", + "sha256:d2a3526dbf6cb01b355e8867079c9356a8df48706b4b099ac0bf59d4656e610d", + "sha256:d552fb2cb513ce910d1dc22dbba6420758a991a356f3cd1b7ec73a9e31f94d01", + "sha256:d5fe089be67bc5927f0c0bd60c082c79f22cf299635ee3ddd370ae2a6e8b4ae0", + "sha256:dc54a21586c096df73f06f9bdf594e8d86d7be84e5d4266358ce81c04c3cc88c", + "sha256:dcd4a7761fdfb5aaac88adad0a734dd065c038f5982a8c4b0dd28efa0bd9cc7c", + "sha256:dde02314eefb85dce3cfdd747e8b44c69a94d442c0d7221b7de151ee4c93f0f5", + "sha256:df0a17f4e677d57bca3624752bbb515316522ad1ce0de07ed9d920e6c4ee5d35", + "sha256:e0fcd3a8bac57a0987d9b09953ba0f8703eb9dca7c77f7051d8c2ed001185be8", + "sha256:e2f8d9cfe0eb3a2997fde5df99b1aaea5a46dabfcfcac97b2d05f027c2cd5e28", + "sha256:ea785d1f232b42b325578f0c8a2fa348192e182cc84a1e862896076a4a2ba2a7", + "sha256:eddf5e520bb88b23b04ac1f28f5e9a7c77c718b8b4af3a4a7a2cc4a600f34502", + "sha256:ee1ea367835eb441d246164c09d1f9703197af4425fc6865cefcde9e2ca81f85", + "sha256:ee751409322ff10709ee867d5aea1dc8431eec7f34835f0f67afd016178da134", + "sha256:f199702740f3b766ed8c70efb885538be76cb48cd0cb596b948626f0b825e07a", + "sha256:f4695153333607e63068580f2979b377b641a03bc36e02813659ffbea2b76fe2", + "sha256:f6c602c5e3615abbf43dbdf3c6c64c65e76e5aa23cb74e18466b55d4a2095468", + "sha256:faa8321bc2a366189dcf87b3823e030edf5ac97a6b9a7fc99f1926c4bf8ef28e", + "sha256:ff3d25883b7865ea34c00084dd22a7be7c58fd3131db6b25c35eafae84398f9d", + "sha256:ffb22cee640bc12ee0e654eba74ecfb59e2e0aebc5bccc3cc7ef92f487008af7" + ], + "markers": "python_version >= '3.9'", + "version": "==4.11.0" }, "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" - ], - "markers": "python_version >= '3.7'", - "version": "==4.6.0" + "sha256:024e735127e7f39763eb3043c628a857cbf6cdfabd9bf5a1825f3597bab74352", + "sha256:03bd7284fd299c7df09cebeb53f3251e0b4850fba71bf63cbbff1ddf20cc569d", + "sha256:05b9eab3bc049f8fd150869375eff3a85ceab606531b6226b60f054daf7d1368", + "sha256:05e96219d1acca15643042478103241771e46a3f5331bae3e19d2ea2756968b1", + "sha256:0ad7ec297e8999b0f984c998e2c1c605f11e9b8c7682256bbbc53c24a195f76e", + "sha256:1393e7e9d2fc291e0d72f8583ef58e1999e84f7cd01d5a72db53b4ed1ae44686", + "sha256:18bc73e47d21cabfde719d0cc5aa6b556856993397c9433d934089c86732e3d3", + "sha256:1b5c61e32c6afbf35a9c6638db892f75dc53ebcd45a9a1bf992ffff0ec28aaaa", + "sha256:1db14e952ceb574cb8acacf063040e2a6e9570bd50671fa903fb47adb7cf49cc", + "sha256:1f2af4b98fc6d54489d187c0faa12bfbf0ef6c56c3e735eeb837ac8ff235b490", + "sha256:20ee2722ac45fba2c502edbc5281b6efcd8601d94ae1900a48c106459a1715d7", + "sha256:21b1d1d33bdbc87c1a082b747aa9ab40a30638c4e58e799d8fe9f5cb15feb38f", + "sha256:22ad78ac0222b8c5f5a28cdf6300cf19481fff193110506768c9915c8cd3396b", + "sha256:29645a9a8166f20b3fc6aa05095af6caf8ee9af9a4cf23cd857576084e29cc9c", + "sha256:2968cf01e2257f2f5193aba259116c1e9e56f739a16eceef36e85a55edc91604", + "sha256:2b6c8588b04e304bb4670e5409b3def2d9daedb8f719d47780a59de7227f1d3f", + "sha256:2c816a9e9d4aaaa0e4e9fb2534b72957666d262f3ce874a0408f8b925cfd4d99", + "sha256:2daa9434828a5e5638b9d78f0031c9e19b5bc84ce9f5e69cf6083f58aa3e3901", + "sha256:2fad596a092ab9cd821c98d75b48dd6a9c3fc52df8b1453d2f10d8219676269a", + "sha256:338b29d89f92c665a1038d53c7cc68869e2a04e171dd4fb2d416d7ad263dc50a", + "sha256:38785ba507a019edb742e333c6bf2fa3644043f1ce79ef4d20a4f7bb2180ee74", + "sha256:3ab5ba56b868c56a38cfeb3202ee78dcdd4152bc364d24b71aaf1ee3994c7f96", + "sha256:3dc0ec9d78d4f28a24bd965e06c0a77459086522005aa199a8e4fc652ed1ce8e", + "sha256:3fafe5ef96943ab9b837f89b6abe779951102bee44d21c743259d43cfc1d9f6e", + "sha256:42acd45f7030743eed3d5e66a03dd3e9c12c7869301d123bffa1f71dc0e3f882", + "sha256:45103766c3f1bf1f5fc2da43a48dbe03a343389a334eb1d02ef39024957cdc91", + "sha256:475a97d48be850140f2455ed4a2a9920f70538b0824c53ffa5deeb940f49fdb3", + "sha256:50307e2403f0cfdf4fd0f5c6c9a45edbb4c5fa63196e1671b7fed5bbcd884109", + "sha256:50325282876a263ece78371319e78518dd034e434c11e3ab12402547292b8fd5", + "sha256:557611de3fa33bd5b8e5d38a7056b15d5c38361af50378ff5cf8b9cbf371913b", + "sha256:587202db4a64d5c091bc39695095af461a6a08b2a52ddd881a6e5cb34244d672", + "sha256:597dce90bc607b3180735a6692abcf75c111d7f6169b2b1cca1db85086ee980c", + "sha256:5b72de1a2f8cc52561c65a5062ade72e06da76e0899d4f11ae1c1bced1534ff8", + "sha256:5fa558bc6320e1183965db06e069973c9642b971a37729a8ae23c37f1c13ce21", + "sha256:6462763611c5fb97b56fcd3a62c325bc8111c686c7768f50668882d21b4f28f4", + "sha256:68fbc920409bd96e6a63b651254baa45e27473c4b73232a3fb5662279383a622", + "sha256:69515e1042a2fb4fadf6384918be34703aa2c792b9a8d3d406ad43e07cb095a2", + "sha256:6d797730d07bff953d05693e75d9575e7357739a5eb2747521987d2f99b9899f", + "sha256:7089a1f2d5883f5137f1c2766691db904741985bb7e7a400ed50c3b370507b17", + "sha256:7466840413fbd23605e9f95b702374b061525e85ea7f47dca6a88981455490ec", + "sha256:75f6f8363a57ba8a6bb1076114dc9aa29336f525c8b621cc1e4cfccae4ff546a", + "sha256:76c1c013bc577c7fb2c9a69d52ee335672eac1bdbfb9c37a432bb155bc69ffdc", + "sha256:780447f9112f0e57d821ced8d593657b45616f3821becb0740e6c0fc38b0e91e", + "sha256:82ba58edb6f6112aac543214ac22fc8e3d569372a7b3a180511cf4a70bd4c0ef", + "sha256:9fa833908d94b5869e6c9a53b778dc8235caca6fcda03aac8410b8f067cd8a6f", + "sha256:a15ad3f11556a30e5dd86344567e85eb46550b09e0ea8d3297476788f0c76d77", + "sha256:a244e27c034707f48f979fdcebe0df47ea000fd52ee1b2b2d2d2cb5b7b0e24dd", + "sha256:a33e118e14bd350bef6127a000c8d08e6bade8b9045bcd70d09a665434035705", + "sha256:a42ad84dfab44218f264e2d68b79e0e684c03c66fe8180a7961d6eb670eec4a3", + "sha256:a4a0d3cf68f9bf84a7ee737ba0b29265cfeeaf586a856c6d7773491c545e5230", + "sha256:a775371086ff63da1ae97f676bcb5556c86e4e281ccac998d49d6e24efa50ca1", + "sha256:a98f67df7aae325c0476aa453877475f9a1160f84b7e6e24e4804498ef99178e", + "sha256:a994b40542ba44748af9e382fd54e69428f40c1728ae06bc649c87a1135d1cfb", + "sha256:b5fe426128a03393d2e7f10169e1f10cf6a6355f40876f52b51a03721c12e6e5", + "sha256:bf646006bfce5e153cc838adaee319ff8a3d625978d491208cc290e89f9c2a21", + "sha256:c434219d66bf20f46011cc11b28e0dbfeb965f7a7cfd1e4b8e733a5f642ae1c2", + "sha256:c95a8d0ca11d16e325749fbd9f7d9aeb9a90241245e419007a941f446ff94dd6", + "sha256:cedfd1be19c8f7b41a1f5fbaea299303087b5d40605e956ffbcfe2adc76de0ec", + "sha256:d54b8139979e6e2ee6fec91b189e948ee2d83f125957793cf191c5e33be567e7", + "sha256:d9410537204bb9e83f1c5e43f6e5df2c0d3fe092dbd8d30bd883736818a6d786", + "sha256:ddf9face1dadf4cce4578dda29547ca2af6df09d44e7dd1bd6fe185f7c18dfc9", + "sha256:de0c88d7229a96a5bfe2827170578bcd871ee16843c47e5cb3290edf1aaf62ca", + "sha256:dece75a28450fa813040b13f7fbe80a614d02e04f7ff84255a2600c440bf227a", + "sha256:e6a22f0349142c92bb2ccbd35a8a0b7dc5a2eeac14217fb28cfa9956bcfee139", + "sha256:eb1423432631994d965e92ee63e448627d57793fd780c56c49570f12d4be1ff4", + "sha256:ebd6f6eed7c6c92af3d3fa375ecd0e730da628c59a95aca5b2445fbb3d1eb874", + "sha256:ee0ab602d309c6f903c002f8705b92459d885349f1f9561040f34a2a06c84891", + "sha256:f03716cfd4c86e3a8537ab8e1169cec26d532cc70fcd02e30027820ac587d28b", + "sha256:f5bfbde2ccc88b96d56cdc6bd104b856d9b039aa209b491311f8012e611d9f58", + "sha256:f736f1a6d85f3b1c182018ae0e6c387bb342935e3b97637c258b9b46e0509af2", + "sha256:f9d3bbb4741a6ab81dbcd73b0754725f304b118c4c738449639fd060ee8b5da9" + ], + "markers": "python_version >= '3.9'", + "version": "==4.15.2" }, "python-dateutil": { "hashes": [ @@ -928,7 +1390,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": { @@ -951,64 +1413,70 @@ }, "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:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", + "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289" ], - "markers": "python_version >= '3.7'", - "version": "==1.2.1" + "markers": "python_version >= '3.8'", + "version": "==1.4.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:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0", + "sha256:10d66943def5fcb6e7b37310eb6b5639fd2ccbc38df1177262b0640c3ca68c1f", + "sha256:10da8046cc4a8f12c91a1c39d1dd1585c41162a15caaef165c2174db9ef18bdc", + "sha256:17df489689befc72c39a08359efac29bbee8eee5209650d4b9f34df73d22e414", + "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", + "sha256:196274f2adb9689a289ad7d65700d37df0c0930fd8e4e743fa4834e850d7719d", + "sha256:221f4f2a1f46032b403bf3be628011caf75428ee3cc204a22addf96f586b19fd", + "sha256:2d1f581393673ce119355d56da84fe1dd9d2bb8b3d13ce792524e1607139feff", + "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", + "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", + "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d", + "sha256:460def4412e473896ef179a1671b40c039c7012184b627898eea5072ef6f017a", + "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", + "sha256:46923b0b5ee7fc0020bef24afe7836cb068f5050ca04caf6b487c513dc1a20b2", + "sha256:53e420a3afe22cdcf2a0f4846e377d16e718bc70103d7088a4f7623567ba5fb0", + "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", + "sha256:67dd654b8ca23aed0a8e99010b4c34aca62f4b7fce88f39d452ed7622c94845c", + "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", + "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", + "sha256:87c43e0f13022b998eb9b973b5e97200c8b90823454d4bc06ab33829e09fb9bb", + "sha256:88cb67cdbc0e483da00af0b2c3cdad4b7c61ceb1ee0f33fe00e09c81e3a6cb75", + "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb", + "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", + "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e", + "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6", + "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", + "sha256:bc09f0ff191e61c2d592a752423c767b4ebb2986daa9ed62908e2b1b9a9ae206", + "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", + "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", + "sha256:c097078b8031190c934ed0ebfee8cc5f9ba9642e6eb88322b9958b649750f72b", + "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8", + "sha256:e678ad6fe52af2c58d2ae3c73dc85524ba8abe637f134bf3564ed07f555c5e79", + "sha256:ec7e6b09a6fdded42403182ab6b832b71f4edaf7f37a9a0e371a01db5f0cb45f", + "sha256:f0ce1b49560b1d2d8a2977e3ba4afb2414fb46b86a1b64056bc4ab929efdafbe", + "sha256:f38b2e090258d051d68a5b14d1da7203a3c3677321cf32a95a6f4db4dd8b6f26", + "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", + "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2" ], "markers": "sys_platform != 'win32'", - "version": "==0.19.0" + "version": "==0.21.0" }, "webencodings": { "hashes": [ @@ -1019,118 +1487,255 @@ }, "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:019c2798df9d74fe8fb9cc916702966dad7e2e3eef66b4c19f8084ba5e0b6ecd", + "sha256:01ef0d7f1dd60d241529dc79a3fa647451056394f9a5ed05fbceeb5009de6122", + "sha256:028c59136b65fccfe5578520a3fb2a94e06601c545ca0125b7e07b3a39f238a5", + "sha256:0416fde6dc89866f4ff494a0ffcc4b2da984cf61aaa279c14a53495e8520c809", + "sha256:056fc431f10ae35aa2375c9de2b68176b34f54fb7de8bc2e830564e2a3d29efa", + "sha256:069cfc781f5d68389c8a4228f720cab453e1b6fa606bcd710a9cc01e38ffe2c1", + "sha256:06c71f698ac5b5bfdde1ce3d58d262235b3c1109f083286c96c01cee64ebf705", + "sha256:0a9454d4c513a3aa2fd87471126e0d32b01f1bf58d49309a84431521488b30c4", + "sha256:0a94664fe3c6dd44c36e875af0f338769dc9f80a1ccd58f53cf5f5b8341e8627", + "sha256:0aaa36261a1279b03fa0655a9bd879cc42e06406adaae0150fde25c778393fcb", + "sha256:0ab4e81b455dd8beb2537648be972eb63351bbe34fb55457054392fee759ac9c", + "sha256:0b16c889a7168ecf7242946dec013c9fb82ade70ab8e6b5d3290383390083a2b", + "sha256:0cc3eeea8f527119aac1b0c874bbb8092675da85fd6d9d91946cf7be7d59477b", + "sha256:0d37bf6f601c714b536159715d9ec6e69bf8a94dc593abe54c1b43ac339eb5e7", + "sha256:0e485c4f9f5b5b9fc10b4bb0ba5baf145ed0a702756da126c9f62f8a89b391a8", + "sha256:10580c7d9b50c883b93cc0ab5c91df5cc1e5b18713736471d622776b01c36810", + "sha256:1107b93c32cf7d7e2ece9bbb1b1820ecb923cfea24c8aa599a309434ed37d707", + "sha256:13c9b91e2e1224a8d33addc1bd58bb097396519c4c49524843947776b8dd45da", + "sha256:140402fef1f482840fcd4d2ee9bfd07f08bfb2c80dd215220bd47f6f3566b882", + "sha256:14872677213d96552268f927982d4c83f5d0674b0d54b623d8e909710460ab14", + "sha256:16957642c0594feba56a4bb430eea5f9132bb589ebb8b4740c0d47f022a5d976", + "sha256:1743d35529a8b9b2b6a9e5f00076c2c146726453051621b739b081dda382ee70", + "sha256:1754b3380ffef931b8eae3bbe6fc0b249db56294ffeb6e6124c2d031a82a3a92", + "sha256:178860382595f3b1fab2596b19570adc495c6211eee8b10a4112ce96342f6515", + "sha256:18e8272a4166d2bb68d51f86445f061aac21fcfc9c1d5b1187f9703f362d85dd", + "sha256:190356a39fed15109ab95600f8ff59c1a0665625f4cfe910388c82b965edaf87", + "sha256:19df967a905f2f9a09733dfb397baa6807772502931000f881943d7cfc6e9f47", + "sha256:1a0ba7cd4eabb7433e69737f33333d9e79d8ab6dbaa2f4d7313ad6611200cc65", + "sha256:1b5d29c1a86cc63e55f69253b8c817091884c4e1b79ee762a8643de834e70a64", + "sha256:1bff86850033508af0a7f9973ced23a16de7ba4ce30521080e2330475b8711b5", + "sha256:1e0b01fa225ec12e54c73be383326ae2a4a59a4a465a0e6cac679f314ed85d1f", + "sha256:20b2dca6588f65b5def8e8eae4a087d504eacf34b5b435c021cc233ce82f6c15", + "sha256:212a5c72d551f94b7799b5de1cc55ddcf3c69ac462f7c0df1beee7e47edb9fef", + "sha256:221aa7c16055e8b9f2eba718cbbf10f174e47f02e659156804d9679654c5cbb0", + "sha256:2227fcc88bebdc90ed87d924bdf8a76a730fc91796641e41ca747aabd13a5074", + "sha256:2584651c047718ec4a863ee81a5432f6f68974e6f0c58975f0aab408ff839798", + "sha256:26940710eece6b5b08a108e81d6325b47610990cd8bb28886e27d4a0d6d60930", + "sha256:2a05a5e018de23c4d2d75c8fbd8b58aba5199f752326f60a22aa37ef28d987bd", + "sha256:2b2f8e0bbdf49530ed09b2bc988082cab6ce24f4c49a0efd2ff5d9477cb29084", + "sha256:2b841c5529f9ca28cf23ed34c8040547ca6530b968a482c14de96a6ade470ee5", + "sha256:30b6a56388963ebe5428d835112439563bcaa9c8349742aeac68a8ad5a231221", + "sha256:37b5e7bba1f6df45058cff626c83a0e8a1259363095e768046a3da40b24e9c4f", + "sha256:3b539230fd64f283594a56633a9751d299cde5ab9c2791452ccb47a865842fa8", + "sha256:3cbae81bff4014ca7745fa11f7015f784198fadba8935cf5a71e139b0b124ff0", + "sha256:430e162d961af58f3dcac58aed038ba974ec7a73803ac6545db2338fbd0f4ed3", + "sha256:45aa7711e1933bac1679f9534f112767f1fe64c97a8576294b760015d0fb65e7", + "sha256:45f17adf1b8bc56becb1bc38f293b1714866786c9d79e245fb3d3731788622a6", + "sha256:4b449296e2ba009481385349138130f209bb502c4f890b3298bf3ea13d43a6d5", + "sha256:4d5af10c9f580002c0ea6c8f345c8cadb2e0c53dce77d3f2639b9e31e5f24d3d", + "sha256:4ee80f79c928ce7c18cf3ad18a5da7f3f0f1b08923e08d87143d628a6d5d2dba", + "sha256:4fcce63c1117ef0630a92a0bda3028a96dc17feed2c78c713de4c963d13d1881", + "sha256:5110ebfe3cbf892b41590fcf4aa70a17ac0a5e9a73b4a8945010bdb970ff1b93", + "sha256:52a8b7541c5d8240ae32d12014f8448e29e1ae794f9443ea020b926cff8691e1", + "sha256:56ead8d62b346c1ec67a6e8b2f66885180ea5bec05821d309ac1cb99ff4aacf5", + "sha256:5c0123db2d86d169554d5fb19421e8e455efcfe2e8e254328b85c77e712ab506", + "sha256:5e7d24e9c3b638f046fcd9a5374818257a8c6d1c3fc7542887521b81a970fbc2", + "sha256:6074904025bc462b0b3f7230b36d8942d9a611b783ce1431ade5ad6a8867b73d", + "sha256:60dcb45a3d762460ac5014755c190db36acf127f68d68643cde7d6d7ce0e5627", + "sha256:61bf6233d04ccba7906f5261ff3628fa97a68fc526cda3d9dd092d2f49926933", + "sha256:63157d66cf7682dec8b3117491cb87a5d8e1cd56df59156d5553ab9721895d19", + "sha256:6378871775e0feb225693cbdad3d997327af0ab4c7e39d93849008c73b867134", + "sha256:6614325ef69d8a53c731ed5e4bd55449ffc5fe86ad652789c0afc853099662ad", + "sha256:66248832212957d8bad28e8d9d307be1d987b94ffaf7e7cca658a349d52d3572", + "sha256:692603a8f82e7baa86bb3921d5002b711788cec547b626030f1f6cf017290ab7", + "sha256:701cd0ee20fe9087c21229db579f2222a75c229b44840a7df7b2d795522068c3", + "sha256:7331a7d2683e644b7830c924ac634fa3ec52257f5098f6415d8ad765d6bc29a8", + "sha256:74b2e94d3e410ed49c7a4cb2c3a5089a6632f7ab68e49bb612b972577e26e771", + "sha256:780313d2a1877adef0e3839ef9596ad53ab640715e7f453e7304c121cd7f262d", + "sha256:7a9d0efd6ff6f4f55ff7a37852e4fcdc24b1feb3b09e204df3dda990171fe725", + "sha256:7b7d46a6ca781a336c7317d9c1d381bebb3b0da5309c2293dd1c4fe3d62942bf", + "sha256:7d271fed8a4b46723db5001619c36192d94a3bd49d76ef186f13abb6897ff8e5", + "sha256:7d5d8eeb1051fac562d80aad7b6b496e2901f41fc2b0988c61016a1426996f66", + "sha256:7d8917677a64304db00ec46629aff335c935c788a10a164b29464b7e2d707463", + "sha256:7da21f0d9bebdc8ac1dde69b3c0951b339984883e2a751790f0f72cbfd1dd007", + "sha256:863d7401d3a109f75c7a5ca0e33e8fb7704a61007f4bda03e08e05f3bf1af40f", + "sha256:866c17223f7d734377a260a2800e14791cb5e55ec252de624e053a0b36b8568a", + "sha256:884d4f3509dfc810299d14faed24c0fbcac82ae2a9737b0cb1d8f7a5e8a291f8", + "sha256:88ff0c0bea02ce78af8a91b173fb43aad5f1945221182f77ba7816fd01bcbc4c", + "sha256:8910f022242c0a15f6d77d781c6ba16bb88d9fed3bff8964de652ee2580029ac", + "sha256:8bfdb95a85404a943197264461b904a2e9e228fd28cb86e4e57321f5b4d5be07", + "sha256:8d39e71705dccdcdf077752d4dc0fcc9554bf797f8af0c1db59f0025a72d4ed2", + "sha256:92a719bb1118f302f6fc3c7638e78e152de8bf279c0200325af831afa1b60f1a", + "sha256:9618070bb76a064c13020323b7fc23c332930604dfbc96b77e7ad7baca960c12", + "sha256:973d630c00bbaf07045870d331c8596bf4fa07aa8eb10d69a02c542af714f128", + "sha256:99febd7a9efab236d798d72ca878ae0d92fffadcc2e472636d6e093ce2677980", + "sha256:9eaf0f28ed19919bdeb02cfa541daaee8a05c070227eaab8d9732f1eebfe2869", + "sha256:9ee84156656d4a09010c280f41011f0a317c62e745f7a2cfafabd8035823fe2d", + "sha256:a999c5c50af0e564cab5bbbbbee97d494eb0e09f99481385108ddfd90049b3fe", + "sha256:ac210d628b9a50699189ec09f0f73630c78e60027d81d75c461deebf7aed752c", + "sha256:ac487adb2e838d03aed0c1a9df4ba348ca2c215bf2afa2f6e1d9449c7029971f", + "sha256:ad6775f8bd57e2c4068246e03c00e212e01b27ea0e96a4b4f17f9d45d80cd5d8", + "sha256:aef7e9b60b371f4d3c3ea80c0ef2d841623dd64aad7718ab815a3205bd4bdf08", + "sha256:b0e38cf49c17e35831ec38029854b772717d6071f0419b74b80be57571a83d0a", + "sha256:b68c0c9deb2fcd183376600df99e88032a9c192d352b0f781e130b09220ef1cf", + "sha256:b846a17f810708f1beff6ad088121fd35334729df3e520412163c74ef49433f7", + "sha256:bc8a06f7bc45219b2c191d68e779e6b3f62e32d09d2f8cf7b381ba1dcb7a68f9", + "sha256:bd6ca6e66b4fee5e879207854f125b94f6ad77e98ddae4d7778d2e96be94ede4", + "sha256:c115756cb1cad49862aa0c2687922ed10da6be7689cf35e3ab602c4a6da2d8fb", + "sha256:c2c4da0802f6897f7fb766c4f0e7f55c96b103981265fcf12b648d088bee3744", + "sha256:c464852c531e44abc5ba05d0c0c97a8fa63719106b3dca46fedae14daedf46ae", + "sha256:c48477c6ff32032624aa122323adc343055bb7e347e01146a86e652b06281731", + "sha256:c6dfa317e4b87052589253f50119211b801146ff7214b8684830e9084fa6eb0a", + "sha256:c763e42a29ac98e7240004e36b7ce231046054393182f1f630c897ce049579ed", + "sha256:c7fab0120e4ea5a2c170382bd27345b2b56e22b6270b40e4231a68f090ce17ed", + "sha256:cb56dcaf10bac9713fff133074d2460b0b217f27760a2b642efb2bc4179bfde6", + "sha256:cfcca979b72f240bac7c73564026eae4c97639151a415e6ced6392d120022d2d", + "sha256:d070756da822a538231d519ce290a1423ab108d6174ad1497cd020bee503d818", + "sha256:d5c35188fac7e448b52eb3916365fe5f59eb27fecec21ba757eea4f650584ca5", + "sha256:d8da09e318a2916da7110d1147355056ee89d61b4ded49ba3ada717517f2fc71", + "sha256:d957259a15e45e5fa5d51ce59ab7519cff8d3de0109d404627276ec68412c718", + "sha256:de1ab4f48fbcb4c2e578951338cc1c8245e510be061d2773a2d47616fb0d6470", + "sha256:de9f7a51f828f73ea0ca2e856a7cac8766752f336241abdb6c5f45f402dd59ea", + "sha256:e00aaf1574075439ccb0b827ca822c5a97c0103351ead292c42a9f17bd2eae0a", + "sha256:e6df05c2234786b15632cd154d60122c302fd860d89c3ee47c166ad92eb6ae55", + "sha256:e7a8f70c7c283d0b4af90314ff8d969c9ab2c7ee522bfb612f42c542935f6e11", + "sha256:ec1f6129c1175d15da7b7c13ae5d4226acf6b5fe362c5b01ac9787fa88c64781", + "sha256:ececd833be7fd8390371c082103916702170e81a1b22beb989452f934def78d6", + "sha256:ee77d3c82576baae66a3281c9a6431fc84281443a7e36a8490a45b3dbbb60446", + "sha256:f0a6cd797394761692cc6f33b10f2ea46789ac0b7fba82b6df737f51e1297122", + "sha256:f1b3930f0934057825227016a141ce16aad4b2a3805fb4e2de71064d042d72e9", + "sha256:f9dae6ef584d3241571674ed7bcd1a28b003a5f0c3a6ca561ab42e5ce0c482e3", + "sha256:fb09731156f54dfd8bb097ce80f9436c2a1a282061ba29e526c375c69086b764" + ], + "markers": "python_version >= '3.9'", + "version": "==1.21.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:3348e934d736fcdb68b6aa4030487097e23a501adf3e7827b63658df464dddd0", + "sha256:dbfe9c25fc6961c2078593de55fd19f2559f9e45b99f1272341f5b95dea4e56b" ], "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==1.7.5" + "markers": "python_version >= '3.9'", + "version": "==1.8.6" }, "black": { "hashes": [ @@ -1159,51 +1764,35 @@ }, "click": { "hashes": [ - "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", - "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" + "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", + "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4" ], - "markers": "python_version >= '3.7'", - "version": "==8.1.7" + "markers": "python_version >= '3.10'", + "version": "==8.3.0" }, "dill": { "hashes": [ - "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e", - "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03" + "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", + "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049" ], - "markers": "python_version < '3.11'", - "version": "==0.3.7" - }, - "gitdb": { - "hashes": [ - "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", - "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b" - ], - "markers": "python_version >= '3.7'", - "version": "==4.0.11" - }, - "gitpython": { - "hashes": [ - "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4", - "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a" - ], - "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 +1812,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 +1829,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:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", + "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf" ], - "markers": "python_version >= '3.7'", - "version": "==4.0.0" + "markers": "python_version >= '3.9'", + "version": "==4.4.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,99 +1862,145 @@ }, "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:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", + "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8" ], - "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.1.0" }, "stevedore": { "hashes": [ - "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d", - "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c" + "sha256:18363d4d268181e8e8452e71a38cd77630f345b2ef6b4a8d5614dac5ee0d18cf", + "sha256:d31496a4f4df9825e1a1e4f1f74d19abb0154aff311c3b376fcc89dae8fccd73" ], - "markers": "python_version >= '3.8'", - "version": "==5.1.0" + "markers": "python_version >= '3.9'", + "version": "==5.5.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": [ diff --git a/bot.py b/bot.py index 3f13ef7ced..671d9ab9c4 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.1.2" +__version__ = "4.2.0" import asyncio @@ -48,7 +48,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__) @@ -879,10 +887,182 @@ 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 + # Update the DB with the new channel_id after restoration + if thread.channel: + await self.api.logs.update_one( + {"recipient.id": str(thread.id)}, {"$set": {"channel_id": str(thread.channel.id)}} + ) + # Re-fetch the thread object to ensure channel is valid + thread = await self.threads.find(recipient=message.author) + if thread is None: delta = await self.get_thread_cooldown(message.author) if delta: @@ -1156,6 +1336,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): @@ -1193,8 +1386,6 @@ async def process_commands(self, message): 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") elif ctx.invoked_with: exc = commands.CommandNotFound('Command "{}" is not found'.format(ctx.invoked_with)) self.dispatch("command_error", ctx, exc) @@ -1212,7 +1403,10 @@ 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: + pass else: if not self.config.get("mod_typing"): return @@ -1222,7 +1416,10 @@ 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: + pass async def handle_reaction_events(self, payload): user = self.get_user(payload.user_id) @@ -1529,7 +1726,10 @@ async def on_command_error( return if isinstance(exception, (commands.BadArgument, commands.BadUnionArgument)): - await context.typing() + try: + await context.typing() + except Exception: + pass await context.send(embed=discord.Embed(color=self.error_color, description=str(exception))) elif isinstance(exception, commands.CommandNotFound): logger.warning("CommandNotFound: %s", exception) @@ -1820,7 +2020,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..a63eea9103 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1,8 +1,9 @@ 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 @@ -29,6 +30,19 @@ class Modmail(commands.Cog): def __init__(self, bot): self.bot = bot + 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 @checks.has_permissions(PermissionLevel.OWNER) @@ -143,6 +157,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: @@ -162,13 +191,14 @@ async def snippet(self, ctx, *, name: str.lower = None): 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() @@ -849,7 +879,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 +898,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: @@ -942,7 +977,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 +996,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: @@ -1036,7 +1076,7 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, 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 +1092,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: @@ -1125,7 +1167,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro 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 +1183,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: @@ -1156,6 +1200,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro @commands.group(invoke_without_command=True) @checks.has_permissions(PermissionLevel.SUPPORTER) + @checks.thread_only() async def logs(self, ctx, *, user: User = None): """ Get previous Modmail thread logs of a member. @@ -1165,7 +1210,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 +1343,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) @@ -1326,7 +1373,7 @@ async def reply(self, ctx, *, msg: str = ""): ctx.message.content = msg - async with ctx.typing(): + async with safe_typing(ctx): await ctx.thread.reply(ctx.message) @commands.command(aliases=["formatreply"]) @@ -1348,7 +1395,7 @@ async def freply(self, ctx, *, msg: str = ""): msg, channel=ctx.channel, recipient=ctx.thread.recipient, author=ctx.message.author ) ctx.message.content = msg - async with ctx.typing(): + async with safe_typing(ctx): await ctx.thread.reply(ctx.message) @commands.command(aliases=["formatanonreply"]) @@ -1370,7 +1417,7 @@ async def fareply(self, ctx, *, msg: str = ""): msg, channel=ctx.channel, recipient=ctx.thread.recipient, author=ctx.message.author ) ctx.message.content = msg - async with ctx.typing(): + async with safe_typing(ctx): await ctx.thread.reply(ctx.message, anonymous=True) @commands.command(aliases=["formatplainreply"]) @@ -1392,7 +1439,7 @@ async def fpreply(self, ctx, *, msg: str = ""): msg, channel=ctx.channel, recipient=ctx.thread.recipient, author=ctx.message.author ) ctx.message.content = msg - async with ctx.typing(): + async with safe_typing(ctx): await ctx.thread.reply(ctx.message, plain=True) @commands.command(aliases=["formatplainanonreply"]) @@ -1414,7 +1461,7 @@ async def fpareply(self, ctx, *, msg: str = ""): msg, channel=ctx.channel, recipient=ctx.thread.recipient, author=ctx.message.author ) ctx.message.content = msg - async with ctx.typing(): + async with safe_typing(ctx): await ctx.thread.reply(ctx.message, anonymous=True, plain=True) @commands.command(aliases=["anonreply", "anonymousreply"]) @@ -1431,7 +1478,7 @@ async def areply(self, ctx, *, msg: str = ""): and `anon_tag` config variables to do so. """ ctx.message.content = msg - async with ctx.typing(): + async with safe_typing(ctx): await ctx.thread.reply(ctx.message, anonymous=True) @commands.command(aliases=["plainreply"]) @@ -1445,7 +1492,7 @@ async def preply(self, ctx, *, msg: str = ""): automatically embedding image URLs. """ ctx.message.content = msg - async with ctx.typing(): + async with safe_typing(ctx): await ctx.thread.reply(ctx.message, plain=True) @commands.command(aliases=["plainanonreply", "plainanonymousreply"]) @@ -1459,7 +1506,7 @@ async def pareply(self, ctx, *, msg: str = ""): automatically embedding image URLs. """ ctx.message.content = msg - async with ctx.typing(): + async with safe_typing(ctx): await ctx.thread.reply(ctx.message, anonymous=True, plain=True) @commands.group(invoke_without_command=True) @@ -1472,7 +1519,7 @@ 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() @@ -1484,7 +1531,7 @@ 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) @@ -1621,6 +1668,7 @@ async def contact( creator=creator, category=category, manual_trigger=manual_trigger, + # The minimum character check is enforced in ThreadManager.create ) if thread.cancelled: @@ -1644,7 +1692,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) @@ -2213,6 +2263,243 @@ 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: deletes the channel, keeps the ticket open in DM, and restores it when the user replies or a moderator unsnoozes it. + Optionally specify a duration, e.g. 'snooze 2d' for 2 days. + Uses config: max_snooze_time, 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 + max_snooze = self.bot.config.get("max_snooze_time") + if max_snooze is None: + max_snooze = 604800 + max_snooze = int(max_snooze) + if duration: + snooze_for = int((duration.dt - duration.now).total_seconds()) + if snooze_for > max_snooze: + snooze_for = max_snooze + else: + snooze_for = max_snooze + + # Storing snooze_start and snooze_for in the log entry + now = datetime.now(timezone.utc) + await self.bot.api.logs.update_one( + {"recipient.id": str(thread.id)}, + {"$set": {"snooze_start": now.isoformat(), "snooze_for": snooze_for}}, + ) + 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: + 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.bot.loop.create_task(self.snooze_auto_unsnooze_task()) + + async def snooze_auto_unsnooze_task(self): + await self.bot.wait_until_ready() + while True: + now = datetime.now(timezone.utc) + snoozed = await self.bot.api.logs.find({"snoozed": True}).to_list(None) + for entry in snoozed: + start = entry.get("snooze_start") + snooze_for = entry.get("snooze_for") + if not start: + continue + start_dt = datetime.fromisoformat(start) + if snooze_for is not None: + duration = int(snooze_for) + else: + max_snooze = self.bot.config.get("max_snooze_time") + if max_snooze is None: + max_snooze = 604800 + duration = int(max_snooze) + if (now - start_dt).total_seconds() > duration: + # Auto-unsnooze + thread = await self.bot.threads.find(recipient_id=int(entry["recipient"]["id"])) + if thread and thread.snoozed: + await thread.restore_from_snooze() + await asyncio.sleep(60) + + 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..c7dceb7283 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__) @@ -484,7 +484,7 @@ 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 ) @@ -759,7 +759,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/utility.py b/cogs/utility.py index 31cb065a28..aa6c6881e9 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -1,3 +1,4 @@ +from core.utils import trigger_typing, truncate, safe_typing import asyncio import inspect import os @@ -90,7 +91,9 @@ async def format_cog_help(self, cog, *, no_cog=False): embed.add_field(name="Commands", value=format_ or "No commands.") name = cog.qualified_name + " - Help" if not no_cog else "Miscellaneous Commands" - embed.set_author(name=name, icon_url=bot.user.display_avatar.url) + embed.set_author( + name=name, icon_url=bot.user.display_avatar.url if bot.user.display_avatar else None + ) embed.set_footer( text=f'Type "{prefix}{self.command_attrs["name"]} command" ' @@ -322,10 +325,10 @@ async def about(self, ctx): embed = discord.Embed(color=self.bot.main_color, timestamp=discord.utils.utcnow()) embed.set_author( name="Modmail - About", - icon_url=self.bot.user.display_avatar.url, + icon_url=self.bot.user.display_avatar.url if self.bot.user.display_avatar else None, url="https://discord.gg/F34cRU8", ) - embed.set_thumbnail(url=self.bot.user.display_avatar.url) + embed.set_thumbnail(url=self.bot.user.display_avatar.url if self.bot.user.display_avatar else None) desc = "This is an open source Discord bot that serves as a means for " desc += "members to easily communicate with server administrators in " @@ -854,7 +857,10 @@ async def config_get(self, ctx, *, key: str.lower = None): if key in keys: desc = f"`{key}` is set to `{self.bot.config[key]}`" embed = discord.Embed(color=self.bot.main_color, description=desc) - embed.set_author(name="Config variable", icon_url=self.bot.user.display_avatar.url) + embed.set_author( + name="Config variable", + icon_url=self.bot.user.display_avatar.url if self.bot.user.display_avatar else None, + ) else: embed = discord.Embed( @@ -871,7 +877,10 @@ async def config_get(self, ctx, *, key: str.lower = None): color=self.bot.main_color, description="Here is a list of currently set configuration variable(s).", ) - embed.set_author(name="Current config(s):", icon_url=self.bot.user.display_avatar.url) + embed.set_author( + name="Current config(s):", + icon_url=self.bot.user.display_avatar.url if self.bot.user.display_avatar else None, + ) config = self.bot.config.filter_default(self.bot.config) for name, value in config.items(): @@ -1354,7 +1363,18 @@ async def permissions_add( key = self.bot.modmail_guild.get_member(value) if key is not None: logger.info("Granting %s access to Modmail category.", key.name) - await self.bot.main_category.set_permissions(key, read_messages=True) + try: + await self.bot.main_category.set_permissions(key, read_messages=True) + except discord.Forbidden: + warn = discord.Embed( + title="Missing Permissions", + color=self.bot.error_color, + description=( + "I couldn't update the Modmail category permissions. " + "Please grant me 'Manage Channels' and 'Manage Roles' for this category." + ), + ) + await ctx.send(embed=warn) embed = discord.Embed( title="Success", @@ -1445,17 +1465,50 @@ async def permissions_remove( if level > PermissionLevel.REGULAR: if value == -1: logger.info("Denying @everyone access to Modmail category.") - await self.bot.main_category.set_permissions( - self.bot.modmail_guild.default_role, read_messages=False - ) + try: + await self.bot.main_category.set_permissions( + self.bot.modmail_guild.default_role, read_messages=False + ) + except discord.Forbidden: + warn = discord.Embed( + title="Missing Permissions", + color=self.bot.error_color, + description=( + "I couldn't update the Modmail category permissions. " + "Please grant me 'Manage Channels' and 'Manage Roles' for this category." + ), + ) + await ctx.send(embed=warn) elif isinstance(user_or_role, discord.Role): logger.info("Denying %s access to Modmail category.", user_or_role.name) - await self.bot.main_category.set_permissions(user_or_role, overwrite=None) + try: + await self.bot.main_category.set_permissions(user_or_role, overwrite=None) + except discord.Forbidden: + warn = discord.Embed( + title="Missing Permissions", + color=self.bot.error_color, + description=( + "I couldn't update the Modmail category permissions. " + "Please grant me 'Manage Channels' and 'Manage Roles' for this category." + ), + ) + await ctx.send(embed=warn) else: member = self.bot.modmail_guild.get_member(value) if member is not None and member != self.bot.modmail_guild.me: logger.info("Denying %s access to Modmail category.", member.name) - await self.bot.main_category.set_permissions(member, overwrite=None) + try: + await self.bot.main_category.set_permissions(member, overwrite=None) + except discord.Forbidden: + warn = discord.Embed( + title="Missing Permissions", + color=self.bot.error_color, + description=( + "I couldn't update the Modmail category permissions. " + "Please grant me 'Manage Channels' and 'Manage Roles' for this category." + ), + ) + await ctx.send(embed=warn) embed = discord.Embed( title="Success", @@ -1912,8 +1965,12 @@ async def github(self, ctx): if data: embed = discord.Embed(title="GitHub", description="Current User", color=self.bot.main_color) user = data["user"] - embed.set_author(name=user["username"], icon_url=user["avatar_url"], url=user["url"]) - embed.set_thumbnail(url=user["avatar_url"]) + embed.set_author( + name=user["username"], + icon_url=user["avatar_url"] if user["avatar_url"] else None, + url=user["url"], + ) + embed.set_thumbnail(url=user["avatar_url"] if user["avatar_url"] else None) await ctx.send(embed=embed) else: await ctx.send(embed=discord.Embed(title="Invalid Github Token", color=self.bot.error_color)) @@ -1943,7 +2000,11 @@ async def update(self, ctx, *, flag: str = ""): data = await self.bot.api.get_user_info() if data: user = data["user"] - embed.set_author(name=user["username"], icon_url=user["avatar_url"], url=user["url"]) + embed.set_author( + name=user["username"], + icon_url=user["avatar_url"] if user["avatar_url"] else None, + url=user["url"], + ) await ctx.send(embed=embed) else: error = None @@ -1982,7 +2043,7 @@ async def update(self, ctx, *, flag: str = ""): embed.set_author( name=user["username"] + " - Updating bot", - icon_url=user["avatar_url"], + icon_url=user["avatar_url"] if user["avatar_url"] else None, url=user["url"], ) @@ -2000,7 +2061,11 @@ async def update(self, ctx, *, flag: str = ""): color=self.bot.main_color, ) embed.set_footer(text="Force update") - embed.set_author(name=user["username"], icon_url=user["avatar_url"], url=user["url"]) + embed.set_author( + name=user["username"], + icon_url=user["avatar_url"] if user["avatar_url"] else None, + url=user["url"], + ) await ctx.send(embed=embed) else: command = "git pull" diff --git a/core/_color_data.py b/core/_color_data.py index 0ac42d5c1f..13ec45620e 100644 --- a/core/_color_data.py +++ b/core/_color_data.py @@ -3,7 +3,6 @@ Slightly modified to conform with usage. """ - BASE_COLORS = { "b": "0000ff", "g": "007f00", diff --git a/core/changelog.py b/core/changelog.py index 06f141fce1..465479bf17 100644 --- a/core/changelog.py +++ b/core/changelog.py @@ -90,7 +90,7 @@ def embed(self) -> Embed: embed = Embed(color=self.bot.main_color, description=self.description) embed.set_author( name=f"v{self.version} - Changelog", - icon_url=self.bot.user.display_avatar.url, + icon_url=self.bot.user.display_avatar.url if self.bot.user.display_avatar else None, url=self.url, ) @@ -98,7 +98,7 @@ def embed(self) -> Embed: embed.add_field(name=name, value=truncate(value, 1024), inline=False) embed.set_footer(text=f"Current version: v{self.bot.version}") - embed.set_thumbnail(url=self.bot.user.display_avatar.url) + embed.set_thumbnail(url=self.bot.user.display_avatar.url if self.bot.user.display_avatar else None) return embed diff --git a/core/clients.py b/core/clients.py index 61c39fdd4b..459ee2ea6b 100644 --- a/core/clients.py +++ b/core/clients.py @@ -592,14 +592,14 @@ async def create_log_entry(self, recipient: Member, channel: TextChannel, creato "id": str(recipient.id), "name": recipient.name, "discriminator": recipient.discriminator, - "avatar_url": recipient.display_avatar.url, + "avatar_url": recipient.display_avatar.url if recipient.display_avatar else None, "mod": False, }, "creator": { "id": str(creator.id), "name": creator.name, "discriminator": creator.discriminator, - "avatar_url": creator.display_avatar.url, + "avatar_url": creator.display_avatar.url if creator.display_avatar else None, "mod": isinstance(creator, Member), }, "closer": None, @@ -661,7 +661,7 @@ async def append_log( "id": str(message.author.id), "name": message.author.name, "discriminator": message.author.discriminator, - "avatar_url": message.author.display_avatar.url, + "avatar_url": message.author.display_avatar.url if message.author.display_avatar else None, "mod": not isinstance(message.channel, DMChannel), }, "content": message.content, @@ -711,7 +711,9 @@ async def create_note(self, recipient: Member, message: Message, message_id: Uni "id": str(message.author.id), "name": message.author.name, "discriminator": message.author.discriminator, - "avatar_url": message.author.display_avatar.url, + "avatar_url": ( + message.author.display_avatar.url if message.author.display_avatar else None + ), }, "message": message.content, "message_id": str(message_id), diff --git a/core/config.py b/core/config.py index 5c6b0dd09d..a704443bb1 100644 --- a/core/config.py +++ b/core/config.py @@ -129,6 +129,17 @@ class ConfigManager: # regex "use_regex_autotrigger": False, "use_hoisted_top_role": True, + # Minimum characters for thread creation + "thread_min_characters": 0, + "thread_min_characters_title": "Message too short", + "thread_min_characters_response": "Your message is too short to create a thread. Please provide more details.", + "thread_min_characters_footer": "Minimum {min_characters} characters required.", + # --- SNOOZE FEATURE CONFIG --- + "max_snooze_time": 604800, # in seconds, default 7 days + "snooze_title": "Thread Snoozed", + "snooze_text": "This thread has been snoozed. The channel will be restored when the user replies or a moderator unsnoozes it.", + "unsnooze_text": "This thread has been unsnoozed and restored.", + "unsnooze_notify_channel": "thread", # Can be a channel ID or 'thread' for the thread's own channel } private_keys = { diff --git a/core/config_help.json b/core/config_help.json index d301763fe4..462e4e1c03 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -1222,5 +1222,105 @@ "If this configuration is enabled, only roles that are hoisted (displayed seperately in member list) will be used. If a user has no hoisted roles, it will return 'None'.", "If you would like to display the top role of a user regardless of if it's hoisted or not, disable `use_hoisted_top_role`." ] + }, + "thread_min_characters": { + "default": "0", + "description": "The minimum number of characters required in the initial message to create a thread. Set to 0 to disable.", + "examples": [ + "`{prefix}config set thread_min_characters 20`" + ], + "notes": [ + "If a user tries to create a thread with a message shorter than this, an error will be shown.", + "See also: `thread_min_characters_title`, `thread_min_characters_response`, `thread_min_characters_footer`." + ] + }, + "thread_min_characters_title": { + "default": "Message too short", + "description": "The title of the error embed when a user tries to create a thread with too few characters.", + "examples": [ + "`{prefix}config set thread_min_characters_title Too short!`" + ], + "notes": [ + "See also: `thread_min_characters`, `thread_min_characters_response`, `thread_min_characters_footer`." + ] + }, + "thread_min_characters_response": { + "default": "Your message is too short to create a thread. Please provide more details.", + "description": "The description of the error embed when a user tries to create a thread with too few characters.", + "examples": [ + "`{prefix}config set thread_min_characters_response Please write a longer message.`" + ], + "notes": [ + "You can use `{min_characters}` as a placeholder for the minimum required characters.", + "See also: `thread_min_characters`, `thread_min_characters_title`, `thread_min_characters_footer`." + ] + }, + "thread_min_characters_footer": { + "default": "Minimum {min_characters} characters required.", + "description": "The footer of the error embed when a user tries to create a thread with too few characters.", + "examples": [ + "`{prefix}config set thread_min_characters_footer At least {min_characters} characters needed.`" + ], + "notes": [ + "You can use `{min_characters}` as a placeholder for the minimum required characters.", + "See also: `thread_min_characters`, `thread_min_characters_title`, `thread_min_characters_response`." + ] + }, + "max_snooze_time": { + "default": "604800 (7 days in seconds)", + "description": "The maximum duration in seconds that a thread can be snoozed. When a thread is snoozed, it is temporarily hidden until the user replies or a moderator unsnoozes it.", + "examples": [ + "`{prefix}config set max_snooze_time 86400` (1 day)", + "`{prefix}config set max_snooze_time 1209600` (14 days)" + ], + "notes": [ + "The value must be specified in seconds.", + "See also: `snooze_title`, `snooze_text`, `unsnooze_text`, `unsnooze_notify_channel`." + ] + }, + "snooze_title": { + "default": "\"Thread Snoozed\"", + "description": "This is the message embed title sent when a thread is snoozed.", + "examples": [ + "`{prefix}config set snooze_title Thread Paused`" + ], + "notes": [ + "See also: `snooze_text`, `unsnooze_title`, `max_snooze_time`." + ] + }, + "snooze_text": { + "default": "\"This thread has been snoozed. The channel will be restored when the user replies or a moderator unsnoozes it.\"", + "description": "This is the message embed content sent when a thread is snoozed.", + "examples": [ + "`{prefix}config set snooze_text This conversation is on hold temporarily.`" + ], + "notes": [ + "Discord flavoured markdown is fully supported in `snooze_text`.", + "See also: `snooze_title`, `unsnooze_text`, `max_snooze_time`." + ] + }, + "unsnooze_text": { + "default": "\"This thread has been unsnoozed and restored.\"", + "description": "This is the message content sent when a thread is unsnoozed and restored.", + "examples": [ + "`{prefix}config set unsnooze_text Thread has been reactivated.`" + ], + "notes": [ + "Discord flavoured markdown is fully supported in `unsnooze_text`.", + "See also: `snooze_text`, `unsnooze_notify_channel`, `max_snooze_time`." + ] + }, + "unsnooze_notify_channel": { + "default": "\"thread\"", + "description": "This is the channel where the unsnooze notification will be sent. Set to \"thread\" to send in the thread's own channel, or provide a specific channel ID.", + "examples": [ + "`{prefix}config set unsnooze_notify_channel thread`", + "`{prefix}config set unsnooze_notify_channel 9234932582312` (9234932582312 is the channel ID)" + ], + "notes": [ + "If set to \"thread\", the notification will be sent in the thread channel itself.", + "If set to a channel ID, the notification will be sent to that specific channel.", + "See also: `unsnooze_text`, `max_snooze_time`." + ] } -} +} \ No newline at end of file diff --git a/core/paginator.py b/core/paginator.py index 5a6844f382..48222d283e 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -149,16 +149,27 @@ def last_page(self): """Returns the index of the last page""" return len(self.pages) - 1 - async def run(self) -> typing.Optional[Message]: + async def run(self) -> None: """ Starts the pagination session. """ if not self.running: await self.show_page(self.current) - if self.view is not None: - await self.view.wait() + # Don't block command execution while waiting for the View timeout. + # Schedule the wait-and-close sequence in the background so the command + # returns immediately (prevents typing indicator from hanging). + if self.view is not None: + + async def _wait_and_close(): + try: + await self.view.wait() + finally: + await self.close(delete=False) + # Fire and forget + self.ctx.bot.loop.create_task(_wait_and_close()) + else: await self.close(delete=False) async def close( @@ -223,8 +234,7 @@ def __init__(self, handler: PaginatorSession, *args, **kwargs): self.clear_items() # clear first so we can control the order self.fill_items() - @discord.ui.button(label="Stop", style=ButtonStyle.danger) - async def stop_button(self, interaction: Interaction, button: Button): + async def stop_callback(self, interaction: Interaction): await self.handler.close(interaction=interaction) def fill_items(self): @@ -244,7 +254,10 @@ def fill_items(self): self.handler._buttons_map[label] = button self.add_item(button) - self.add_item(self.stop_button) + + stop_button = Button(label="Stop", style=ButtonStyle.danger) + stop_button.callback = self.stop_callback + self.add_item(stop_button) async def interaction_check(self, interaction: Interaction): """Only allow the message author to interact""" @@ -314,7 +327,7 @@ def __init__(self, ctx: commands.Context, *embeds, **options): footer_text = footer_text + " • " + embed.footer.text if embed.footer.icon: - icon_url = embed.footer.icon.url + icon_url = embed.footer.icon.url if embed.footer.icon else None else: icon_url = None embed.set_footer(text=footer_text, icon_url=icon_url) @@ -375,7 +388,7 @@ def _set_footer(self): footer_text = footer_text + " • " + self.footer_text if self.embed.footer.icon: - icon_url = self.embed.footer.icon.url + icon_url = self.embed.footer.icon.url if self.embed.footer.icon else None else: icon_url = None diff --git a/core/thread.py b/core/thread.py index 00060ab7f5..d380552694 100644 --- a/core/thread.py +++ b/core/thread.py @@ -8,7 +8,7 @@ import traceback import typing import warnings -from datetime import timedelta +from datetime import timedelta, datetime, timezone from types import SimpleNamespace import isodate @@ -33,6 +33,7 @@ DenyButton, ConfirmThreadCreationView, DummyParam, + extract_forwarded_content, ) logger = getLogger(__name__) @@ -66,6 +67,10 @@ def __init__( self.close_task = None self.auto_close_task = None self._cancelled = False + # --- SNOOZE STATE --- + self.snoozed = False # True if thread is snoozed + self.snooze_data = None # Dict with channel/category/position/messages for restoration + self.log_key = None # Ensure log_key always exists def __repr__(self): return f'Thread(recipient="{self.recipient or self.id}", channel={self.channel.id}, other_recipients={len(self._other_recipients)})' @@ -126,6 +131,202 @@ def cancelled(self, flag: bool): for i in self.wait_tasks: i.cancel() + async def snooze(self, moderator=None, command_used=None, snooze_for=None): + """ + Save channel/category/position/messages to DB, mark as snoozed, delete channel. + """ + if self.snoozed: + return False # Already snoozed + channel = self.channel + if not isinstance(channel, discord.TextChannel): + return False + # Ensure self.log_key is set before snoozing + if not self.log_key: + # Try to fetch from DB using channel_id + log_entry = await self.bot.api.get_log(self.channel.id) + if log_entry and "key" in log_entry: + self.log_key = log_entry["key"] + # Fallback: try by recipient id + elif hasattr(self, "id"): + log_entry = await self.bot.api.get_log(str(self.id)) + if log_entry and "key" in log_entry: + self.log_key = log_entry["key"] + + now = datetime.now(timezone.utc) + self.snooze_data = { + "category_id": channel.category_id, + "position": channel.position, + "name": channel.name, + "topic": channel.topic, + "slowmode_delay": channel.slowmode_delay, + "nsfw": channel.nsfw, + "overwrites": [(role.id, perm._values) for role, perm in channel.overwrites.items()], + "messages": [ + { + "author_id": m.author.id, + "content": m.content, + "attachments": [a.url for a in m.attachments], + "embeds": [e.to_dict() for e in m.embeds], + "created_at": m.created_at.isoformat(), + "type": ( + "mod_only" + if ( + m.embeds + and getattr(m.embeds[0], "author", None) + and ( + getattr(m.embeds[0].author, "name", "").startswith("📝 Note") + or getattr(m.embeds[0].author, "name", "").startswith("📝 Persistent Note") + ) + ) + else None + ), + "author_name": getattr(m.author, "name", None), + } + async for m in channel.history(limit=None, oldest_first=True) + if not ( + m.embeds + and getattr(m.embeds[0], "author", None) + and ( + getattr(m.embeds[0].author, "name", "").startswith("📝 Note") + or getattr(m.embeds[0].author, "name", "").startswith("📝 Persistent Note") + ) + ) + and getattr(m, "type", None) not in ("internal", "note") + ], + "snoozed_by": getattr(moderator, "name", None) if moderator else None, + "snooze_command": command_used, + "log_key": self.log_key, + "snooze_start": now.isoformat(), + "snooze_for": snooze_for, + } + self.snoozed = True + # Save to DB (robust: try recipient.id, then channel_id) + result = await self.bot.api.logs.update_one( + {"recipient.id": str(self.id)}, + {"$set": {"snoozed": True, "snooze_data": self.snooze_data}}, + ) + if result.modified_count == 0 and self.channel: + result = await self.bot.api.logs.update_one( + {"channel_id": str(self.channel.id)}, + {"$set": {"snoozed": True, "snooze_data": self.snooze_data}}, + ) + import logging + + logging.info(f"[SNOOZE] DB update result: {result.modified_count}") + # Delete channel + await channel.delete(reason="Thread snoozed by moderator") + self._channel = None + return True + + async def restore_from_snooze(self): + """ + Recreate channel in original category/position, replay messages, mark as not snoozed. + """ + if not self.snooze_data or not isinstance(self.snooze_data, dict): + import logging + + logging.warning( + f"[UNSNOOZE] Tried to restore thread {self.id} but snooze_data is None or not a dict." + ) + return False + # Now safe to access self.snooze_data + snoozed_by = self.snooze_data.get("snoozed_by") + snooze_command = self.snooze_data.get("snooze_command") + guild = self.bot.modmail_guild + category = guild.get_channel(self.snooze_data["category_id"]) + overwrites = {} + for role_id, perm_values in self.snooze_data["overwrites"]: + role = guild.get_role(role_id) or guild.get_member(role_id) + if role: + overwrites[role] = discord.PermissionOverwrite(**perm_values) + channel = await guild.create_text_channel( + name=self.snooze_data["name"], + category=category, + topic=self.snooze_data["topic"], + slowmode_delay=self.snooze_data["slowmode_delay"], + overwrites=overwrites, + nsfw=self.snooze_data["nsfw"], + position=self.snooze_data["position"], + reason="Thread unsnoozed/restored", + ) + self._channel = channel + # Strictly restore the log_key from snooze_data (never create a new one) + self.log_key = self.snooze_data.get("log_key") + # Replay messages + for msg in self.snooze_data["messages"]: + author = self.bot.get_user(msg["author_id"]) or await self.bot.get_or_fetch_user(msg["author_id"]) + content = msg["content"] + embeds = [discord.Embed.from_dict(e) for e in msg.get("embeds", []) if e] + attachments = msg.get("attachments", []) + msg_type = msg.get("type") + # Only send if there is content, embeds, or attachments + if not content and not embeds and not attachments: + continue # Skip empty messages + author_is_mod = msg["author_id"] not in [r.id for r in self.recipients] + if author_is_mod: + username = msg.get("author_name") or (getattr(author, "name", None)) or "Unknown" + user_id = msg.get("author_id") + if embeds: + embeds[0].set_author( + name=f"{username} ({user_id})", + icon_url=( + author.display_avatar.url + if author and hasattr(author, "display_avatar") + else None + ), + ) + await channel.send(embeds=embeds) + else: + formatted = ( + f"**{username} ({user_id})**: {content}" if content else f"**{username} ({user_id})**" + ) + await channel.send(formatted) + else: + await channel.send(content=content or None, embeds=embeds or None) + self.snoozed = False + # Store snooze_data for notification before clearing + snooze_data_for_notify = self.snooze_data + self.snooze_data = None + # Update channel_id in DB and clear snooze_data (robust: try log_key first) + if self.log_key: + result = await self.bot.api.logs.update_one( + {"key": self.log_key}, + {"$set": {"channel_id": str(channel.id)}, "$unset": {"snoozed": "", "snooze_data": ""}}, + ) + else: + result = await self.bot.api.logs.update_one( + {"recipient.id": str(self.id)}, + {"$set": {"channel_id": str(channel.id)}, "$unset": {"snoozed": "", "snooze_data": ""}}, + ) + if result.modified_count == 0: + result = await self.bot.api.logs.update_one( + {"channel_id": str(channel.id)}, + { + "$set": {"channel_id": str(channel.id)}, + "$unset": {"snoozed": "", "snooze_data": ""}, + }, + ) + import logging + + logging.info(f"[UNSNOOZE] DB update result: {result.modified_count}") + # Notify in the configured channel + notify_channel = self.bot.config.get("unsnooze_notify_channel") or "thread" + notify_text = self.bot.config.get("unsnooze_text") or "This thread has been unsnoozed and restored." + if notify_channel == "thread": + await channel.send(notify_text) + else: + ch = self.bot.get_channel(int(notify_channel)) + if ch: + await ch.send(f"Thread for user <@{self.id}> has been unsnoozed and restored.") + # Show who ran the snooze command and the command used + # Use snooze_data_for_notify to avoid accessing self.snooze_data after it is set to None + snoozed_by = snooze_data_for_notify.get("snoozed_by") if snooze_data_for_notify else None + snooze_command = snooze_data_for_notify.get("snooze_command") if snooze_data_for_notify else None + if snoozed_by or snooze_command: + info = f"Snoozed by: {snoozed_by or 'Unknown'} | Command: {snooze_command or '?snooze'}" + await channel.send(info) + return True + @classmethod async def from_channel(cls, manager: "ThreadManager", channel: discord.TextChannel) -> "Thread": # there is a chance it grabs from another recipient's main thread @@ -415,6 +616,8 @@ async def close( await self._close(closer, silent, delete_channel, message) async def _close(self, closer, silent=False, delete_channel=True, message=None, scheduled=False): + if self.channel: + self.manager.closing.add(self.channel.id) try: self.manager.cache.pop(self.id) except KeyError as e: @@ -541,10 +744,15 @@ async def _close(self, closer, silent=False, delete_channel=True, message=None, if user is not None: tasks.append(user.send(embed=embed)) - if delete_channel: + if delete_channel and self.channel: tasks.append(self.channel.delete()) - await asyncio.gather(*tasks) + try: + await asyncio.gather(*tasks) + finally: + if self.channel: + self.manager.closing.discard(self.channel.id) + self.bot.dispatch("thread_close", self, closer, silent, delete_channel, message, scheduled) async def cancel_closure(self, auto_close: bool = False, all: bool = False) -> None: @@ -620,10 +828,7 @@ async def find_linked_messages( ): raise ValueError("Thread message not found.") - if message1.embeds[0].color.value == self.bot.main_color and ( - message1.embeds[0].author.name.startswith("Note") - or message1.embeds[0].author.name.startswith("Persistent Note") - ): + if message1.embeds[0].footer and "Internal Message" in message1.embeds[0].footer.text: if not note: raise ValueError("Thread message not found.") return message1, None @@ -686,7 +891,7 @@ async def edit_message(self, message_id: typing.Optional[int], message: str) -> embed1.description = message tasks = [self.bot.api.edit_message(message1.id, message), message1.edit(embed=embed1)] - if message1.embeds[0].author.name.startswith("Persistent Note"): + if message1.embeds[0].footer and "Persistent Internal Message" in message1.embeds[0].footer.text: tasks += [self.bot.api.edit_note(message1.id, message)] else: for m2 in message2: @@ -713,7 +918,7 @@ async def delete_message( if m2 is not None: tasks += [m2.delete()] - if message1.embeds[0].author.name.startswith("Persistent Note"): + if message1.embeds[0].footer and "Persistent Internal Message" in message1.embeds[0].footer.text: tasks += [self.bot.api.delete_note(message1.id)] if tasks: @@ -811,8 +1016,9 @@ async def note( thread_creation=thread_creation, ) + # Log as 'note' type for logviewer self.bot.loop.create_task( - self.bot.api.append_log(message, message_id=msg.id, channel_id=self.channel.id, type_="system") + self.bot.api.append_log(message, message_id=msg.id, channel_id=self.channel.id, type_="note") ) return msg @@ -920,6 +1126,38 @@ async def send( persistent_note: bool = False, thread_creation: bool = False, ) -> None: + # Handle notes with Discord-like system message format - return early + if note: + destination = destination or self.channel + content = message.content or "[No content]" + + # Create embed for note with Discord system message style + embed = discord.Embed( + description=content, color=0x5865F2 # Discord blurple color for system messages + ) + + # Set author with note icon and username + if persistent_note: + note_type = "Persistent Note" + else: + note_type = "Note" + + embed.set_author( + name=f"📝 {note_type} ({message.author.name})", icon_url=message.author.display_avatar.url + ) + + # Add timestamp if enabled + if self.bot.config["show_timestamp"]: + embed.timestamp = message.created_at + + # Add a subtle footer to distinguish from replies + if persistent_note: + embed.set_footer(text="Persistent Internal Note") + else: + embed.set_footer(text="Internal Note") + + return await destination.send(embed=embed) + if not note and from_mod: self.bot.loop.create_task(self._restart_close_timer()) # Start or restart thread auto close @@ -943,6 +1181,15 @@ async def send( destination = destination or self.channel + if destination is None: + logger.error("Attempted to send a message to a thread with no channel (destination is None).") + return + try: + await destination.typing() + except discord.NotFound: + logger.warning("Channel not found when trying to send message.") + return + author = message.author member = self.bot.guild.get_member(author.id) if member: @@ -950,10 +1197,57 @@ async def send( else: avatar_url = author.display_avatar.url - embed = discord.Embed(description=message.content) + # Handle forwarded messages first + forwarded_jump_url = None + if hasattr(message, "message_snapshots") and len(message.message_snapshots) > 0: + snap = message.message_snapshots[0] + # Only show "No content" if there's truly no content (no text, attachments, embeds, or stickers) + if not snap.content and not message.attachments and not message.embeds and not message.stickers: + content = "No content" + else: + content = snap.content or "" + + # Get jump_url from cached_message, fetch if not cached + if hasattr(snap, "cached_message") and snap.cached_message is not None: + forwarded_jump_url = snap.cached_message.jump_url + else: + if ( + hasattr(message, "reference") + and message.reference + and message.reference.type == discord.MessageReferenceType.forward + ): + try: + original_msg_channel = self.bot.get_channel(message.reference.channel_id) + original_msg = await original_msg_channel.fetch_message(message.reference.message_id) + forwarded_jump_url = original_msg.jump_url + except (discord.NotFound, discord.Forbidden, AttributeError): + pass + + content = f"📨 **Forwarded message:**\n{content}" if content else "📨 **Forwarded message:**" + else: + # Only show "No content" if there's truly no content (no text, attachments, embeds, or stickers) + if ( + not message.content + and not message.attachments + and not message.embeds + and not message.stickers + ): + content = "No content" + else: + content = message.content or "" + + # Only set description if there's actual content to show + if content: + embed = discord.Embed(description=content) + else: + embed = discord.Embed() if self.bot.config["show_timestamp"]: embed.timestamp = message.created_at + # Add forwarded message context + if forwarded_jump_url: + embed.add_field(name="Context", value=f"- {forwarded_jump_url}", inline=True) + system_avatar_url = "https://discordapp.com/assets/f78426a064bc9dd24847519259bc42af.png" if not note: @@ -983,12 +1277,18 @@ async def send( url=f"https://discordapp.com/users/{author.id}#{message.id}", ) else: - # Special note messages + # Notes use system message style with note icon + if persistent_note: + note_type = "Persistent Note" + else: + note_type = "Note" + embed.set_author( - name=f"{'Persistent' if persistent_note else ''} Note ({author.name})", - icon_url=system_avatar_url, + name=f"📝 {note_type} ({str(author)})", + icon_url=avatar_url, url=f"https://discordapp.com/users/{author.id}#{message.id}", ) + embed.color = 0x5865F2 # Discord blurple for system messages ext = [(a.url, a.filename, False) for a in message.attachments] @@ -1001,7 +1301,7 @@ async def send( attachments.append(attachment) image_urls = re.findall( - r"http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$\-_@.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", + r"http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", message.content, ) @@ -1113,22 +1413,33 @@ def lottie_to_png(data): file_upload_count += 1 if from_mod: - embed.colour = self.bot.mod_color - # Anonymous reply sent in thread channel - if anonymous and isinstance(destination, discord.TextChannel): - embed.set_footer(text="Anonymous Reply") - # Normal messages - elif not anonymous: - mod_tag = self.bot.config["mod_tag"] - if mod_tag is None: - mod_tag = str(get_top_role(message.author, self.bot.config["use_hoisted_top_role"])) - embed.set_footer(text=mod_tag) # Normal messages + if note: + # Notes use Discord blurple and special footer + embed.colour = 0x5865F2 + if persistent_note: + embed.set_footer(text="Persistent Internal Note") + else: + embed.set_footer(text="Internal Note") else: - embed.set_footer(text=self.bot.config["anon_tag"]) - elif note: - embed.colour = self.bot.main_color + # Regular mod messages + embed.colour = self.bot.mod_color + # Anonymous reply sent in thread channel + if anonymous and isinstance(destination, discord.TextChannel): + embed.set_footer(text="Anonymous Reply") + # Normal messages + elif not anonymous: + mod_tag = self.bot.config["mod_tag"] + if mod_tag is None: + mod_tag = str(get_top_role(message.author, self.bot.config["use_hoisted_top_role"])) + embed.set_footer(text=mod_tag) # Normal messages + else: + embed.set_footer(text=self.bot.config["anon_tag"]) else: - embed.set_footer(text=f"Message ID: {message.id}") + # Add forwarded message indicator in footer for mods + footer_text = f"Message ID: {message.id}" + if hasattr(message, "message_snapshots") and len(message.message_snapshots) > 0: + footer_text += " • Forwarded" + embed.set_footer(text=footer_text) embed.colour = self.bot.recipient_color if (from_mod or note) and not thread_creation: @@ -1146,11 +1457,14 @@ def lottie_to_png(data): ): logger.info("Sending a message to %s when DM disabled is set.", self.recipient) + # Best-effort typing: never block message delivery if typing fails try: await destination.typing() except discord.NotFound: logger.warning("Channel not found.") raise + except (discord.Forbidden, discord.HTTPException, Exception) as e: + logger.warning("Unable to send typing to %s: %s. Continuing without typing.", destination, e) if not from_mod and not note: mentions = await self.get_notifications() @@ -1278,6 +1592,7 @@ class ThreadManager: def __init__(self, bot): self.bot = bot self.cache = {} + self.closing = set() async def populate_cache(self) -> None: for channel in self.bot.modmail_guild.text_channels: @@ -1301,6 +1616,8 @@ async def find( ) -> typing.Optional[Thread]: """Finds a thread from cache or from discord channel topics.""" if recipient is None and channel is not None and isinstance(channel, discord.TextChannel): + if channel.id in self.closing: + return None thread = await self._find_from_channel(channel) if thread is None: user_id, thread = next( @@ -1322,11 +1639,8 @@ async def find( logger.warning("Thread for %s cancelled.", recipient) return thread else: - if not thread.cancelled and ( - not thread.channel or not self.bot.get_channel(thread.channel.id) - ): - logger.warning("Found existing thread for %s but the channel is invalid.", recipient_id) - await thread.close(closer=self.bot.user, silent=True, delete_channel=False) + # If the thread is snoozed (channel is None), return it for restoration + if thread.cancelled: thread = None else: @@ -1406,6 +1720,33 @@ async def create( ) -> Thread: """Creates a Modmail thread""" + # Minimum character check + min_chars = self.bot.config.get("thread_min_characters") + if min_chars is None: + min_chars = 0 + try: + min_chars = int(min_chars) + except ValueError: + min_chars = 0 + if min_chars > 0 and message is not None and message.content is not None: + if len(message.content.strip()) < min_chars: + embed = discord.Embed( + title=self.bot.config["thread_min_characters_title"], + description=self.bot.config["thread_min_characters_response"].replace( + "{min_characters}", str(min_chars) + ), + color=self.bot.error_color, + ) + embed.set_footer( + text=self.bot.config["thread_min_characters_footer"].replace( + "{min_characters}", str(min_chars) + ) + ) + await message.channel.send(embed=embed) + thread = Thread(self, recipient) + thread.cancelled = True + return thread + # checks for existing thread in cache thread = self.cache.get(recipient.id) if thread: @@ -1433,8 +1774,10 @@ async def create( else: destination = message.channel view = ConfirmThreadCreationView() - view.add_item(AcceptButton(self.bot.config["confirm_thread_creation_accept"])) - view.add_item(DenyButton(self.bot.config["confirm_thread_creation_deny"])) + view.add_item( + AcceptButton("accept-thread-creation", self.bot.config["confirm_thread_creation_accept"]) + ) + view.add_item(DenyButton("deny-thread-creation", self.bot.config["confirm_thread_creation_deny"])) confirm = await destination.send( embed=discord.Embed( title=self.bot.config["confirm_thread_creation_title"], diff --git a/core/time.py b/core/time.py index c56c7264e2..b6ce91f419 100644 --- a/core/time.py +++ b/core/time.py @@ -3,6 +3,7 @@ Source: https://github.com/Rapptz/RoboDanny/blob/rewrite/cogs/utils/time.py """ + from __future__ import annotations import datetime @@ -159,6 +160,30 @@ def __init__(self, dt: datetime.datetime, now: datetime.datetime = None): async def ensure_constraints( self, ctx: Context, uft: UserFriendlyTime, now: datetime.datetime, remaining: str ) -> None: + # Strip stray connector words like "in", "to", or "at" that may + # remain when the natural language parser isolates the time token + # positioned at the end (e.g. "in 10m" leaves "in" before the token). + if isinstance(remaining, str): + cleaned = remaining.strip(" ,.!") + stray_tokens = { + "in", + "to", + "at", + "me", + # also treat vague times of day as stray tokens when they are the only leftover word + "evening", + "night", + "midnight", + "morning", + "afternoon", + "tonight", + "noon", + "today", + "tomorrow", + } + if cleaned.lower() in stray_tokens: + remaining = "" + if self.dt < now: raise commands.BadArgument("This time is in the past.") @@ -198,6 +223,26 @@ async def convert(self, ctx: Context, argument: str, *, now=None) -> FriendlyTim if now is None: now = ctx.message.created_at + # Heuristic: If the user provides only certain single words that are commonly + # used as salutations or vague times of day, interpret them as a message + # rather than a schedule. This avoids accidental scheduling when the intent + # is a short message (e.g. '?close evening'). Explicit scheduling still works + # via 'in 2h', '2m30s', 'at 8pm', etc. + if argument.strip().lower() in { + "evening", + "night", + "midnight", + "morning", + "afternoon", + "tonight", + "noon", + "today", + "tomorrow", + }: + result = FriendlyTimeResult(now) + await result.ensure_constraints(ctx, self, now, argument) + return result + match = regex.match(argument) if match is not None and match.group(0): data = {k: int(v) for k, v in match.groupdict(default=0).items()} @@ -244,7 +289,10 @@ async def convert(self, ctx: Context, argument: str, *, now=None) -> FriendlyTim if not status.hasDateOrTime: raise commands.BadArgument('Invalid time provided, try e.g. "tomorrow" or "3 days".') - if begin not in (0, 1) and end != len(argument): + # If the parsed time token is embedded in the text but only followed by + # trailing punctuation/whitespace, treat it as if it's positioned at the end. + trailing = argument[end:].strip(" ,.!") + if begin not in (0, 1) and trailing != "": raise commands.BadArgument( "Time is either in an inappropriate location, which " "must be either at the end or beginning of your input, " @@ -259,6 +307,20 @@ async def convert(self, ctx: Context, argument: str, *, now=None) -> FriendlyTim if status.accuracy == pdt.pdtContext.ACU_HALFDAY: dt = dt.replace(day=now.day + 1) + # Heuristic: If the matched time string is a vague time-of-day (e.g., + # 'evening', 'morning', 'afternoon', 'night') and there's additional + # non-punctuation text besides that token, assume the user intended a + # closing message rather than scheduling. This avoids cases like + # '?close Have a good evening!' being treated as a scheduled close. + vague_tod = {"evening", "morning", "afternoon", "night"} + matched_text = dt_string.strip().strip('"').rstrip(" ,.!").lower() + pre_text = argument[:begin].strip(" ,.!") + post_text = argument[end:].strip(" ,.!") + if matched_text in vague_tod and (pre_text or post_text): + result = FriendlyTimeResult(now) + await result.ensure_constraints(ctx, self, now, argument) + return result + result = FriendlyTimeResult(dt.replace(tzinfo=datetime.timezone.utc), now) remaining = "" diff --git a/core/utils.py b/core/utils.py index 9f9f572f5a..19ff4cd37b 100644 --- a/core/utils.py +++ b/core/utils.py @@ -1,10 +1,10 @@ import base64 import functools +import contextlib import re import typing from datetime import datetime, timezone from difflib import get_close_matches -from distutils.util import strtobool as _stb # pylint: disable=import-error from itertools import takewhile, zip_longest from urllib import parse @@ -34,15 +34,18 @@ "normalize_alias", "format_description", "trigger_typing", + "safe_typing", "escape_code_block", "tryint", "get_top_role", "get_joint_id", "extract_block_timestamp", + "return_or_truncate", "AcceptButton", "DenyButton", "ConfirmThreadCreationView", "DummyParam", + "extract_forwarded_content", ] @@ -52,15 +55,12 @@ def strtobool(val): if isinstance(val, bool): return val - try: - return _stb(str(val)) - except ValueError: - val = val.lower() - if val == "enable": - return 1 - if val == "disable": - return 0 - raise + val = str(val).lower() + if val in ("y", "yes", "on", "1", "true", "t", "enable"): + return 1 + if val in ("n", "no", "off", "0", "false", "f", "disable"): + return 0 + raise ValueError(f"invalid truth value {val}") class User(commands.MemberConverter): @@ -391,7 +391,7 @@ def decode_alias(m): iterate = [alias] for a in iterate: - a = re.sub("\x1AU(.+?)\x1AU", decode_alias, a) + a = re.sub(r"\x1AU(.+?)\x1AU", decode_alias, a) if a[0] == a[-1] == '"': a = a[1:-1] aliases.append(a) @@ -423,11 +423,42 @@ def format_description(i, names): ) +class _SafeTyping: + """Best-effort typing context manager. + + Suppresses errors from Discord's typing endpoint so core flows continue + when typing is disabled or experiencing outages. + """ + + def __init__(self, target): + # target can be a Context or any Messageable (channel/DM/user) + self._target = target + self._cm = None + + async def __aenter__(self): + try: + self._cm = self._target.typing() + return await self._cm.__aenter__() + except Exception: + # typing is best-effort; ignore any failure + self._cm = None + + async def __aexit__(self, exc_type, exc, tb): + if self._cm is not None: + with contextlib.suppress(Exception): + return await self._cm.__aexit__(exc_type, exc, tb) + + +def safe_typing(target): + return _SafeTyping(target) + + def trigger_typing(func): @functools.wraps(func) async def wrapper(self, ctx: commands.Context, *args, **kwargs): - await ctx.typing() - return await func(self, ctx, *args, **kwargs) + # Keep typing active for the duration of the command; suppress failures + async with safe_typing(ctx): + return await func(self, ctx, *args, **kwargs) return wrapper @@ -573,9 +604,15 @@ def extract_block_timestamp(reason, id_): return end_time, after +def return_or_truncate(text, max_length): + if len(text) <= max_length: + return text + return text[: max_length - 3] + "..." + + class AcceptButton(discord.ui.Button): - def __init__(self, emoji): - super().__init__(style=discord.ButtonStyle.gray, emoji=emoji) + def __init__(self, custom_id: str, emoji: str): + super().__init__(style=discord.ButtonStyle.gray, emoji=emoji, custom_id=custom_id) async def callback(self, interaction: discord.Interaction): self.view.value = True @@ -584,8 +621,8 @@ async def callback(self, interaction: discord.Interaction): class DenyButton(discord.ui.Button): - def __init__(self, emoji): - super().__init__(style=discord.ButtonStyle.gray, emoji=emoji) + def __init__(self, custom_id: str, emoji: str): + super().__init__(style=discord.ButtonStyle.gray, emoji=emoji, custom_id=custom_id) async def callback(self, interaction: discord.Interaction): self.view.value = False @@ -599,6 +636,100 @@ def __init__(self): self.value = None +def extract_forwarded_content(message) -> typing.Optional[str]: + """ + Extract forwarded message content from Discord forwarded messages. + + Parameters + ---------- + message : discord.Message + The message to extract forwarded content from. + + Returns + ------- + Optional[str] + The extracted forwarded content, or None if not a forwarded message. + """ + import discord + + try: + # Handle multi-forward (message_snapshots) + if hasattr(message, "flags") and getattr(message.flags, "has_snapshot", False): + if hasattr(message, "message_snapshots") and message.message_snapshots: + forwarded_parts = [] + for snap in message.message_snapshots: + author = getattr(snap, "author", None) + author_name = getattr(author, "name", "Unknown") if author else "Unknown" + snap_content = getattr(snap, "content", "") + + if snap_content: + # Truncate very long messages to prevent spam + if len(snap_content) > 500: + snap_content = snap_content[:497] + "..." + forwarded_parts.append(f"**{author_name}:** {snap_content}") + elif getattr(snap, "embeds", None): + for embed in snap.embeds: + if hasattr(embed, "description") and embed.description: + embed_desc = embed.description + if len(embed_desc) > 300: + embed_desc = embed_desc[:297] + "..." + forwarded_parts.append(f"**{author_name}:** {embed_desc}") + break + elif getattr(snap, "attachments", None): + attachment_info = ", ".join( + [getattr(a, "filename", "Unknown") for a in snap.attachments[:3]] + ) + if len(snap.attachments) > 3: + attachment_info += f" (+{len(snap.attachments) - 3} more)" + forwarded_parts.append(f"**{author_name}:** [Attachments: {attachment_info}]") + else: + forwarded_parts.append(f"**{author_name}:** [No content]") + + if forwarded_parts: + return "\n".join(forwarded_parts) + + # Handle single-message forward + elif getattr(message, "type", None) == getattr(discord.MessageType, "forward", None): + ref = getattr(message, "reference", None) + if ( + ref + and hasattr(discord, "MessageReferenceType") + and getattr(ref, "type", None) == getattr(discord.MessageReferenceType, "forward", None) + ): + try: + ref_msg = getattr(ref, "resolved", None) + if ref_msg: + ref_author = getattr(ref_msg, "author", None) + ref_author_name = getattr(ref_author, "name", "Unknown") if ref_author else "Unknown" + ref_content = getattr(ref_msg, "content", "") + + if ref_content: + if len(ref_content) > 500: + ref_content = ref_content[:497] + "..." + return f"**{ref_author_name}:** {ref_content}" + elif getattr(ref_msg, "embeds", None): + for embed in ref_msg.embeds: + if hasattr(embed, "description") and embed.description: + embed_desc = embed.description + if len(embed_desc) > 300: + embed_desc = embed_desc[:297] + "..." + return f"**{ref_author_name}:** {embed_desc}" + elif getattr(ref_msg, "attachments", None): + attachment_info = ", ".join( + [getattr(a, "filename", "Unknown") for a in ref_msg.attachments[:3]] + ) + if len(ref_msg.attachments) > 3: + attachment_info += f" (+{len(ref_msg.attachments) - 3} more)" + return f"**{ref_author_name}:** [Attachments: {attachment_info}]" + except Exception: + pass + except Exception: + # Silently handle any unexpected errors + pass + + return None + + class DummyParam: """ A dummy parameter that can be used for MissingRequiredArgument. diff --git a/pyproject.toml b/pyproject.toml index 7e29a4d4ef..0a6d6eaa6c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.1.2' +version = '4.2.0' description = "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." license = 'AGPL-3.0-only' authors = [ diff --git a/requirements.txt b/requirements.txt index 2c7bdb7880..8530e8e0d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,41 +1,43 @@ -i https://pypi.org/simple -aiodns==3.1.1 +aiodns==3.5.0; python_version >= '3.9' aiohttp==3.9.0; python_version >= '3.8' -aiosignal==1.3.1; python_version >= '3.7' -async-timeout==4.0.3; python_version < '3.11' -attrs==23.1.0; python_version >= '3.7' +aiosignal==1.4.0; python_version >= '3.9' +attrs==25.3.0; python_version >= '3.8' +audioop-lts==0.2.2; python_version >= '3.13' brotli==1.1.0 -cairocffi==1.6.1; python_version >= '3.7' -cairosvg==2.7.1; python_version >= '3.5' -certifi==2023.11.17; python_version >= '3.6' -cffi==1.16.0; python_version >= '3.8' -charset-normalizer==3.3.2; python_full_version >= '3.7.0' +cairocffi==1.7.1; python_version >= '3.8' +cairosvg==2.8.2; python_version >= '3.9' +certifi==2025.10.5; python_version >= '3.7' +cffi==2.0.0; python_version >= '3.9' +charset-normalizer==3.4.3; python_version >= '3.7' colorama==0.4.6; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6' -cssselect2==0.7.0; python_version >= '3.7' +cssselect2==0.8.0; python_version >= '3.9' defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -discord.py[speed]==2.3.2; python_full_version >= '3.8.0' -dnspython==2.4.2; python_version >= '3.8' and python_version < '4.0' +discord.py[speed]==2.6.3; python_version >= '3.8' +dnspython==2.8.0; python_version >= '3.10' emoji==2.8.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -frozenlist==1.4.0; python_version >= '3.8' -idna==3.4; python_version >= '3.5' +frozenlist==1.8.0; python_version >= '3.9' +idna==3.10; python_version >= '3.6' isodate==0.6.1 lottie[pdf]==0.7.0; python_version >= '3' motor==3.3.2; python_version >= '3.7' -multidict==6.0.4; python_version >= '3.7' +multidict==6.6.4; python_version >= '3.9' natural==0.2.0 -orjson==3.9.10 +orjson==3.11.3; python_version >= '3.9' packaging==23.2; python_version >= '3.7' parsedatetime==2.6 -pillow==10.1.0; python_version >= '3.8' -pycares==4.4.0; python_version >= '3.8' -pycparser==2.21 -pymongo[srv]==4.6.0; python_version >= '3.7' -python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +pillow==11.3.0; python_version >= '3.9' +propcache==0.4.0; python_version >= '3.9' +pycares==4.11.0; python_version >= '3.9' +pycparser==2.23; python_version >= '3.8' +pymongo[srv]==4.15.2; python_version >= '3.9' +python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' python-dotenv==1.0.0; python_version >= '3.8' requests==2.31.0; python_version >= '3.7' -six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -tinycss2==1.2.1; python_version >= '3.7' -urllib3==2.1.0; python_version >= '3.8' -uvloop==0.19.0; sys_platform != 'win32' +six==1.17.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' +tinycss2==1.4.0; python_version >= '3.8' +urllib3==2.5.0; python_version >= '3.9' +uvloop==0.21.0; sys_platform != 'win32' webencodings==0.5.1 -yarl==1.9.3; python_version >= '3.7' +yarl==1.21.0; python_version >= '3.9' +zstandard==0.25.0; python_version >= '3.9'