mirror of
https://github.com/allthingslinux/tux.git
synced 2024-10-02 16:43:12 +00:00
Merge branch 'main' into gif_limiter
This commit is contained in:
commit
d9e840b2d6
29 changed files with 594 additions and 379 deletions
2
.github/workflows/linting.yml
vendored
2
.github/workflows/linting.yml
vendored
|
@ -9,7 +9,7 @@ permissions:
|
|||
|
||||
jobs:
|
||||
Linting:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@v4
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
repos:
|
||||
- repo: https://github.com/gitleaks/gitleaks
|
||||
rev: v8.18.4
|
||||
rev: v8.19.2
|
||||
hooks:
|
||||
- id: gitleaks
|
||||
|
||||
|
@ -12,7 +12,7 @@ repos:
|
|||
- id: check-toml
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.6.4
|
||||
rev: v0.6.7
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff
|
||||
|
|
|
@ -10,8 +10,8 @@ USER_IDS:
|
|||
- 123456789012345679
|
||||
BOT_OWNER: 123456789012345679
|
||||
|
||||
TEMPVC_CATEGORY_ID: 123456789012345
|
||||
TEMPVC_CHANNEL_ID: 123456789012345
|
||||
TEMPVC_CATEGORY_ID: 123456789012345679
|
||||
TEMPVC_CHANNEL_ID: 123456789012345679
|
||||
|
||||
EMBED_COLORS:
|
||||
DEFAULT: 16044058
|
||||
|
|
306
poetry.lock
generated
306
poetry.lock
generated
|
@ -2,13 +2,13 @@
|
|||
|
||||
[[package]]
|
||||
name = "aiocache"
|
||||
version = "0.12.2"
|
||||
version = "0.12.3"
|
||||
description = "multi backend asyncio cache"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "aiocache-0.12.2-py2.py3-none-any.whl", hash = "sha256:9b6fa30634ab0bfc3ecc44928a91ff07c6ea16d27d55469636b296ebc6eb5918"},
|
||||
{file = "aiocache-0.12.2.tar.gz", hash = "sha256:b41c9a145b050a5dcbae1599f847db6dd445193b1f3bd172d8e0fe0cb9e96684"},
|
||||
{file = "aiocache-0.12.3-py2.py3-none-any.whl", hash = "sha256:889086fc24710f431937b87ad3720a289f7fc31c4fd8b68e9f918b9bacd8270d"},
|
||||
{file = "aiocache-0.12.3.tar.gz", hash = "sha256:f528b27bf4d436b497a1d0d1a8f59a542c153ab1e37c3621713cb376d44c4713"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
|
@ -190,13 +190,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.4.0"
|
||||
version = "4.5.0"
|
||||
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"},
|
||||
{file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"},
|
||||
{file = "anyio-4.5.0-py3-none-any.whl", hash = "sha256:fdeb095b7cc5a5563175eedd926ec4ae55413bb4be5770c424af0ba46ccb4a78"},
|
||||
{file = "anyio-4.5.0.tar.gz", hash = "sha256:c5a275fe5ca0afd788001f58fca1e69e29ce706d746e317d660e21f70c530ef9"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -204,9 +204,9 @@ idna = ">=2.8"
|
|||
sniffio = ">=1.1"
|
||||
|
||||
[package.extras]
|
||||
doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
|
||||
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
|
||||
trio = ["trio (>=0.23)"]
|
||||
doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
|
||||
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.21.0b1)"]
|
||||
trio = ["trio (>=0.26.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "astunparse"
|
||||
|
@ -692,18 +692,18 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.16.0"
|
||||
version = "3.16.1"
|
||||
description = "A platform independent file lock."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "filelock-3.16.0-py3-none-any.whl", hash = "sha256:f6ed4c963184f4c84dd5557ce8fece759a3724b37b80c6c4f20a2f63a4dc6609"},
|
||||
{file = "filelock-3.16.0.tar.gz", hash = "sha256:81de9eb8453c769b63369f87f11131a7ab04e367f8d97ad39dc230daa07e3bec"},
|
||||
{file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"},
|
||||
{file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"]
|
||||
testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.1.1)", "pytest (>=8.3.2)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.3)"]
|
||||
docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"]
|
||||
testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"]
|
||||
typing = ["typing-extensions (>=4.12.2)"]
|
||||
|
||||
[[package]]
|
||||
|
@ -811,13 +811,13 @@ dev = ["flake8", "markdown", "twine", "wheel"]
|
|||
|
||||
[[package]]
|
||||
name = "githubkit"
|
||||
version = "0.11.9"
|
||||
version = "0.11.10"
|
||||
description = "GitHub SDK for Python"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.8"
|
||||
files = [
|
||||
{file = "githubkit-0.11.9-py3-none-any.whl", hash = "sha256:68933ff9867467418c90176e2ea77c7623fa7ab8fbf64723c2ca56c09b14a0f6"},
|
||||
{file = "githubkit-0.11.9.tar.gz", hash = "sha256:d25da1a667cce32f3d1ab0f33cf52fa328a55e85a6916e19da2765b0602c472a"},
|
||||
{file = "githubkit-0.11.10-py3-none-any.whl", hash = "sha256:e95074916af4a5f357d47005022a555984e16729d9e6204161ef67bc29a78789"},
|
||||
{file = "githubkit-0.11.10.tar.gz", hash = "sha256:9729783ba44935ca47b3bebaad76971ccc3d3b548b8af54e06d16a489b0ece90"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -914,13 +914,13 @@ zstd = ["zstandard (>=0.18.0)"]
|
|||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.6.0"
|
||||
version = "2.6.1"
|
||||
description = "File identification library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "identify-2.6.0-py2.py3-none-any.whl", hash = "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0"},
|
||||
{file = "identify-2.6.0.tar.gz", hash = "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf"},
|
||||
{file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"},
|
||||
{file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
|
@ -928,13 +928,13 @@ license = ["ukkonen"]
|
|||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.9"
|
||||
version = "3.10"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "idna-3.9-py3-none-any.whl", hash = "sha256:69297d5da0cc9281c77efffb4e730254dd45943f45bbfb461de5991713989b1e"},
|
||||
{file = "idna-3.9.tar.gz", hash = "sha256:e5c5dafde284f26e9e0f28f6ea2d6400abd5ca099864a67f576f3981c6476124"},
|
||||
{file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
|
||||
{file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
|
@ -1160,13 +1160,13 @@ pyyaml = ">=5.1"
|
|||
|
||||
[[package]]
|
||||
name = "mkdocs-material"
|
||||
version = "9.5.34"
|
||||
version = "9.5.38"
|
||||
description = "Documentation that simply works"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "mkdocs_material-9.5.34-py3-none-any.whl", hash = "sha256:54caa8be708de2b75167fd4d3b9f3d949579294f49cb242515d4653dbee9227e"},
|
||||
{file = "mkdocs_material-9.5.34.tar.gz", hash = "sha256:1e60ddf716cfb5679dfd65900b8a25d277064ed82d9a53cd5190e3f894df7840"},
|
||||
{file = "mkdocs_material-9.5.38-py3-none-any.whl", hash = "sha256:d4779051d52ba9f1e7e344b34de95449c7c366c212b388e4a2db9a3db043c228"},
|
||||
{file = "mkdocs_material-9.5.38.tar.gz", hash = "sha256:1843c5171ad6b489550aeaf7358e5b7128cc03ddcf0fb4d91d19aa1e691a63b8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -1446,13 +1446,13 @@ xmp = ["defusedxml"]
|
|||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "4.3.3"
|
||||
version = "4.3.6"
|
||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "platformdirs-4.3.3-py3-none-any.whl", hash = "sha256:50a5450e2e84f44539718293cbb1da0a0885c9d14adf21b77bae4e66fc99d9b5"},
|
||||
{file = "platformdirs-4.3.3.tar.gz", hash = "sha256:d4e0b7d8ec176b341fb03cb11ca12d0276faa8c485f9cd218f613840463fc2c0"},
|
||||
{file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"},
|
||||
{file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
|
@ -1556,18 +1556,18 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.9.1"
|
||||
version = "2.9.2"
|
||||
description = "Data validation using Python type hints"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pydantic-2.9.1-py3-none-any.whl", hash = "sha256:7aff4db5fdf3cf573d4b3c30926a510a10e19a0774d38fc4967f78beb6deb612"},
|
||||
{file = "pydantic-2.9.1.tar.gz", hash = "sha256:1363c7d975c7036df0db2b4a61f2e062fbc0aa5ab5f2772e0ffc7191a4f4bce2"},
|
||||
{file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"},
|
||||
{file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
annotated-types = ">=0.6.0"
|
||||
pydantic-core = "2.23.3"
|
||||
pydantic-core = "2.23.4"
|
||||
typing-extensions = [
|
||||
{version = ">=4.12.2", markers = "python_version >= \"3.13\""},
|
||||
{version = ">=4.6.1", markers = "python_version < \"3.13\""},
|
||||
|
@ -1579,100 +1579,100 @@ timezone = ["tzdata"]
|
|||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.23.3"
|
||||
version = "2.23.4"
|
||||
description = "Core functionality for Pydantic validation and serialization"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pydantic_core-2.23.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7f10a5d1b9281392f1bf507d16ac720e78285dfd635b05737c3911637601bae6"},
|
||||
{file = "pydantic_core-2.23.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3c09a7885dd33ee8c65266e5aa7fb7e2f23d49d8043f089989726391dd7350c5"},
|
||||
{file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6470b5a1ec4d1c2e9afe928c6cb37eb33381cab99292a708b8cb9aa89e62429b"},
|
||||
{file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9172d2088e27d9a185ea0a6c8cebe227a9139fd90295221d7d495944d2367700"},
|
||||
{file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86fc6c762ca7ac8fbbdff80d61b2c59fb6b7d144aa46e2d54d9e1b7b0e780e01"},
|
||||
{file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0cb80fd5c2df4898693aa841425ea1727b1b6d2167448253077d2a49003e0ed"},
|
||||
{file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03667cec5daf43ac4995cefa8aaf58f99de036204a37b889c24a80927b629cec"},
|
||||
{file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:047531242f8e9c2db733599f1c612925de095e93c9cc0e599e96cf536aaf56ba"},
|
||||
{file = "pydantic_core-2.23.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5499798317fff7f25dbef9347f4451b91ac2a4330c6669821c8202fd354c7bee"},
|
||||
{file = "pydantic_core-2.23.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bbb5e45eab7624440516ee3722a3044b83fff4c0372efe183fd6ba678ff681fe"},
|
||||
{file = "pydantic_core-2.23.3-cp310-none-win32.whl", hash = "sha256:8b5b3ed73abb147704a6e9f556d8c5cb078f8c095be4588e669d315e0d11893b"},
|
||||
{file = "pydantic_core-2.23.3-cp310-none-win_amd64.whl", hash = "sha256:2b603cde285322758a0279995b5796d64b63060bfbe214b50a3ca23b5cee3e83"},
|
||||
{file = "pydantic_core-2.23.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:c889fd87e1f1bbeb877c2ee56b63bb297de4636661cc9bbfcf4b34e5e925bc27"},
|
||||
{file = "pydantic_core-2.23.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea85bda3189fb27503af4c45273735bcde3dd31c1ab17d11f37b04877859ef45"},
|
||||
{file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7f7f72f721223f33d3dc98a791666ebc6a91fa023ce63733709f4894a7dc611"},
|
||||
{file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b2b55b0448e9da68f56b696f313949cda1039e8ec7b5d294285335b53104b61"},
|
||||
{file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c24574c7e92e2c56379706b9a3f07c1e0c7f2f87a41b6ee86653100c4ce343e5"},
|
||||
{file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2b05e6ccbee333a8f4b8f4d7c244fdb7a979e90977ad9c51ea31261e2085ce0"},
|
||||
{file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2c409ce1c219c091e47cb03feb3c4ed8c2b8e004efc940da0166aaee8f9d6c8"},
|
||||
{file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d965e8b325f443ed3196db890d85dfebbb09f7384486a77461347f4adb1fa7f8"},
|
||||
{file = "pydantic_core-2.23.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f56af3a420fb1ffaf43ece3ea09c2d27c444e7c40dcb7c6e7cf57aae764f2b48"},
|
||||
{file = "pydantic_core-2.23.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5b01a078dd4f9a52494370af21aa52964e0a96d4862ac64ff7cea06e0f12d2c5"},
|
||||
{file = "pydantic_core-2.23.3-cp311-none-win32.whl", hash = "sha256:560e32f0df04ac69b3dd818f71339983f6d1f70eb99d4d1f8e9705fb6c34a5c1"},
|
||||
{file = "pydantic_core-2.23.3-cp311-none-win_amd64.whl", hash = "sha256:c744fa100fdea0d000d8bcddee95213d2de2e95b9c12be083370b2072333a0fa"},
|
||||
{file = "pydantic_core-2.23.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e0ec50663feedf64d21bad0809f5857bac1ce91deded203efc4a84b31b2e4305"},
|
||||
{file = "pydantic_core-2.23.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db6e6afcb95edbe6b357786684b71008499836e91f2a4a1e55b840955b341dbb"},
|
||||
{file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98ccd69edcf49f0875d86942f4418a4e83eb3047f20eb897bffa62a5d419c8fa"},
|
||||
{file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a678c1ac5c5ec5685af0133262103defb427114e62eafeda12f1357a12140162"},
|
||||
{file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01491d8b4d8db9f3391d93b0df60701e644ff0894352947f31fff3e52bd5c801"},
|
||||
{file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fcf31facf2796a2d3b7fe338fe8640aa0166e4e55b4cb108dbfd1058049bf4cb"},
|
||||
{file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7200fd561fb3be06827340da066df4311d0b6b8eb0c2116a110be5245dceb326"},
|
||||
{file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dc1636770a809dee2bd44dd74b89cc80eb41172bcad8af75dd0bc182c2666d4c"},
|
||||
{file = "pydantic_core-2.23.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:67a5def279309f2e23014b608c4150b0c2d323bd7bccd27ff07b001c12c2415c"},
|
||||
{file = "pydantic_core-2.23.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:748bdf985014c6dd3e1e4cc3db90f1c3ecc7246ff5a3cd4ddab20c768b2f1dab"},
|
||||
{file = "pydantic_core-2.23.3-cp312-none-win32.whl", hash = "sha256:255ec6dcb899c115f1e2a64bc9ebc24cc0e3ab097775755244f77360d1f3c06c"},
|
||||
{file = "pydantic_core-2.23.3-cp312-none-win_amd64.whl", hash = "sha256:40b8441be16c1e940abebed83cd006ddb9e3737a279e339dbd6d31578b802f7b"},
|
||||
{file = "pydantic_core-2.23.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6daaf5b1ba1369a22c8b050b643250e3e5efc6a78366d323294aee54953a4d5f"},
|
||||
{file = "pydantic_core-2.23.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d015e63b985a78a3d4ccffd3bdf22b7c20b3bbd4b8227809b3e8e75bc37f9cb2"},
|
||||
{file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3fc572d9b5b5cfe13f8e8a6e26271d5d13f80173724b738557a8c7f3a8a3791"},
|
||||
{file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f6bd91345b5163ee7448bee201ed7dd601ca24f43f439109b0212e296eb5b423"},
|
||||
{file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc379c73fd66606628b866f661e8785088afe2adaba78e6bbe80796baf708a63"},
|
||||
{file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbdce4b47592f9e296e19ac31667daed8753c8367ebb34b9a9bd89dacaa299c9"},
|
||||
{file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc3cf31edf405a161a0adad83246568647c54404739b614b1ff43dad2b02e6d5"},
|
||||
{file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8e22b477bf90db71c156f89a55bfe4d25177b81fce4aa09294d9e805eec13855"},
|
||||
{file = "pydantic_core-2.23.3-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:0a0137ddf462575d9bce863c4c95bac3493ba8e22f8c28ca94634b4a1d3e2bb4"},
|
||||
{file = "pydantic_core-2.23.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:203171e48946c3164fe7691fc349c79241ff8f28306abd4cad5f4f75ed80bc8d"},
|
||||
{file = "pydantic_core-2.23.3-cp313-none-win32.whl", hash = "sha256:76bdab0de4acb3f119c2a4bff740e0c7dc2e6de7692774620f7452ce11ca76c8"},
|
||||
{file = "pydantic_core-2.23.3-cp313-none-win_amd64.whl", hash = "sha256:37ba321ac2a46100c578a92e9a6aa33afe9ec99ffa084424291d84e456f490c1"},
|
||||
{file = "pydantic_core-2.23.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d063c6b9fed7d992bcbebfc9133f4c24b7a7f215d6b102f3e082b1117cddb72c"},
|
||||
{file = "pydantic_core-2.23.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6cb968da9a0746a0cf521b2b5ef25fc5a0bee9b9a1a8214e0a1cfaea5be7e8a4"},
|
||||
{file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edbefe079a520c5984e30e1f1f29325054b59534729c25b874a16a5048028d16"},
|
||||
{file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cbaaf2ef20d282659093913da9d402108203f7cb5955020bd8d1ae5a2325d1c4"},
|
||||
{file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb539d7e5dc4aac345846f290cf504d2fd3c1be26ac4e8b5e4c2b688069ff4cf"},
|
||||
{file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e6f33503c5495059148cc486867e1d24ca35df5fc064686e631e314d959ad5b"},
|
||||
{file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04b07490bc2f6f2717b10c3969e1b830f5720b632f8ae2f3b8b1542394c47a8e"},
|
||||
{file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:03795b9e8a5d7fda05f3873efc3f59105e2dcff14231680296b87b80bb327295"},
|
||||
{file = "pydantic_core-2.23.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c483dab0f14b8d3f0df0c6c18d70b21b086f74c87ab03c59250dbf6d3c89baba"},
|
||||
{file = "pydantic_core-2.23.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b2682038e255e94baf2c473dca914a7460069171ff5cdd4080be18ab8a7fd6e"},
|
||||
{file = "pydantic_core-2.23.3-cp38-none-win32.whl", hash = "sha256:f4a57db8966b3a1d1a350012839c6a0099f0898c56512dfade8a1fe5fb278710"},
|
||||
{file = "pydantic_core-2.23.3-cp38-none-win_amd64.whl", hash = "sha256:13dd45ba2561603681a2676ca56006d6dee94493f03d5cadc055d2055615c3ea"},
|
||||
{file = "pydantic_core-2.23.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:82da2f4703894134a9f000e24965df73cc103e31e8c31906cc1ee89fde72cbd8"},
|
||||
{file = "pydantic_core-2.23.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dd9be0a42de08f4b58a3cc73a123f124f65c24698b95a54c1543065baca8cf0e"},
|
||||
{file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89b731f25c80830c76fdb13705c68fef6a2b6dc494402987c7ea9584fe189f5d"},
|
||||
{file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6de1ec30c4bb94f3a69c9f5f2182baeda5b809f806676675e9ef6b8dc936f28"},
|
||||
{file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb68b41c3fa64587412b104294b9cbb027509dc2f6958446c502638d481525ef"},
|
||||
{file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c3980f2843de5184656aab58698011b42763ccba11c4a8c35936c8dd6c7068c"},
|
||||
{file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94f85614f2cba13f62c3c6481716e4adeae48e1eaa7e8bac379b9d177d93947a"},
|
||||
{file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:510b7fb0a86dc8f10a8bb43bd2f97beb63cffad1203071dc434dac26453955cd"},
|
||||
{file = "pydantic_core-2.23.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1eba2f7ce3e30ee2170410e2171867ea73dbd692433b81a93758ab2de6c64835"},
|
||||
{file = "pydantic_core-2.23.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b259fd8409ab84b4041b7b3f24dcc41e4696f180b775961ca8142b5b21d0e70"},
|
||||
{file = "pydantic_core-2.23.3-cp39-none-win32.whl", hash = "sha256:40d9bd259538dba2f40963286009bf7caf18b5112b19d2b55b09c14dde6db6a7"},
|
||||
{file = "pydantic_core-2.23.3-cp39-none-win_amd64.whl", hash = "sha256:5a8cd3074a98ee70173a8633ad3c10e00dcb991ecec57263aacb4095c5efb958"},
|
||||
{file = "pydantic_core-2.23.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f399e8657c67313476a121a6944311fab377085ca7f490648c9af97fc732732d"},
|
||||
{file = "pydantic_core-2.23.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:6b5547d098c76e1694ba85f05b595720d7c60d342f24d5aad32c3049131fa5c4"},
|
||||
{file = "pydantic_core-2.23.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0dda0290a6f608504882d9f7650975b4651ff91c85673341789a476b1159f211"},
|
||||
{file = "pydantic_core-2.23.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65b6e5da855e9c55a0c67f4db8a492bf13d8d3316a59999cfbaf98cc6e401961"},
|
||||
{file = "pydantic_core-2.23.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:09e926397f392059ce0afdcac920df29d9c833256354d0c55f1584b0b70cf07e"},
|
||||
{file = "pydantic_core-2.23.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:87cfa0ed6b8c5bd6ae8b66de941cece179281239d482f363814d2b986b79cedc"},
|
||||
{file = "pydantic_core-2.23.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e61328920154b6a44d98cabcb709f10e8b74276bc709c9a513a8c37a18786cc4"},
|
||||
{file = "pydantic_core-2.23.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce3317d155628301d649fe5e16a99528d5680af4ec7aa70b90b8dacd2d725c9b"},
|
||||
{file = "pydantic_core-2.23.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e89513f014c6be0d17b00a9a7c81b1c426f4eb9224b15433f3d98c1a071f8433"},
|
||||
{file = "pydantic_core-2.23.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:4f62c1c953d7ee375df5eb2e44ad50ce2f5aff931723b398b8bc6f0ac159791a"},
|
||||
{file = "pydantic_core-2.23.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2718443bc671c7ac331de4eef9b673063b10af32a0bb385019ad61dcf2cc8f6c"},
|
||||
{file = "pydantic_core-2.23.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0d90e08b2727c5d01af1b5ef4121d2f0c99fbee692c762f4d9d0409c9da6541"},
|
||||
{file = "pydantic_core-2.23.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b676583fc459c64146debea14ba3af54e540b61762dfc0613dc4e98c3f66eeb"},
|
||||
{file = "pydantic_core-2.23.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:50e4661f3337977740fdbfbae084ae5693e505ca2b3130a6d4eb0f2281dc43b8"},
|
||||
{file = "pydantic_core-2.23.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:68f4cf373f0de6abfe599a38307f4417c1c867ca381c03df27c873a9069cda25"},
|
||||
{file = "pydantic_core-2.23.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:59d52cf01854cb26c46958552a21acb10dd78a52aa34c86f284e66b209db8cab"},
|
||||
{file = "pydantic_core-2.23.3.tar.gz", hash = "sha256:3cb0f65d8b4121c1b015c60104a685feb929a29d7cf204387c7f2688c7974690"},
|
||||
{file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"},
|
||||
{file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"},
|
||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"},
|
||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"},
|
||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"},
|
||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"},
|
||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"},
|
||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"},
|
||||
{file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"},
|
||||
{file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"},
|
||||
{file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"},
|
||||
{file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"},
|
||||
{file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"},
|
||||
{file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"},
|
||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"},
|
||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"},
|
||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"},
|
||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"},
|
||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"},
|
||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"},
|
||||
{file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"},
|
||||
{file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"},
|
||||
{file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"},
|
||||
{file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"},
|
||||
{file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"},
|
||||
{file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"},
|
||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"},
|
||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"},
|
||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"},
|
||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"},
|
||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"},
|
||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"},
|
||||
{file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"},
|
||||
{file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"},
|
||||
{file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"},
|
||||
{file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"},
|
||||
{file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"},
|
||||
{file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"},
|
||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"},
|
||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"},
|
||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"},
|
||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"},
|
||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"},
|
||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"},
|
||||
{file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"},
|
||||
{file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"},
|
||||
{file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"},
|
||||
{file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"},
|
||||
{file = "pydantic_core-2.23.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555"},
|
||||
{file = "pydantic_core-2.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658"},
|
||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271"},
|
||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665"},
|
||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368"},
|
||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13"},
|
||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad"},
|
||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12"},
|
||||
{file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2"},
|
||||
{file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb"},
|
||||
{file = "pydantic_core-2.23.4-cp38-none-win32.whl", hash = "sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6"},
|
||||
{file = "pydantic_core-2.23.4-cp38-none-win_amd64.whl", hash = "sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556"},
|
||||
{file = "pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a"},
|
||||
{file = "pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36"},
|
||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b"},
|
||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323"},
|
||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3"},
|
||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df"},
|
||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c"},
|
||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55"},
|
||||
{file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040"},
|
||||
{file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605"},
|
||||
{file = "pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6"},
|
||||
{file = "pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29"},
|
||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"},
|
||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"},
|
||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"},
|
||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"},
|
||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"},
|
||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"},
|
||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"},
|
||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"},
|
||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21"},
|
||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb"},
|
||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59"},
|
||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577"},
|
||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744"},
|
||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef"},
|
||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8"},
|
||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e"},
|
||||
{file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -1758,21 +1758,23 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"]
|
|||
|
||||
[[package]]
|
||||
name = "pyright"
|
||||
version = "1.1.380"
|
||||
version = "1.1.382"
|
||||
description = "Command line wrapper for pyright"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pyright-1.1.380-py3-none-any.whl", hash = "sha256:a6404392053d8848bacc7aebcbd9d318bb46baf1a1a000359305481920f43879"},
|
||||
{file = "pyright-1.1.380.tar.gz", hash = "sha256:e6ceb1a5f7e9f03106e0aa1d6fbb4d97735a5e7ffb59f3de6b2db590baf935b2"},
|
||||
{file = "pyright-1.1.382-py3-none-any.whl", hash = "sha256:b6658802b2eca1107a6d63b6816903da4c7a53dffebc27cdbc02ebd904b7a18e"},
|
||||
{file = "pyright-1.1.382.tar.gz", hash = "sha256:0c953837aa9f1e1d8d46772ee7ebae845104db657e9216834dbdde567a11f177"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
nodeenv = ">=1.6.0"
|
||||
typing-extensions = ">=4.1"
|
||||
|
||||
[package.extras]
|
||||
all = ["twine (>=3.4.1)"]
|
||||
all = ["nodejs-wheel-binaries", "twine (>=3.4.1)"]
|
||||
dev = ["twine (>=3.4.1)"]
|
||||
nodejs = ["nodejs-wheel-binaries"]
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
|
@ -2043,29 +2045,29 @@ pyasn1 = ">=0.1.3"
|
|||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.6.5"
|
||||
version = "0.6.8"
|
||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruff-0.6.5-py3-none-linux_armv6l.whl", hash = "sha256:7e4e308f16e07c95fc7753fc1aaac690a323b2bb9f4ec5e844a97bb7fbebd748"},
|
||||
{file = "ruff-0.6.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:932cd69eefe4daf8c7d92bd6689f7e8182571cb934ea720af218929da7bd7d69"},
|
||||
{file = "ruff-0.6.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3a8d42d11fff8d3143ff4da41742a98f8f233bf8890e9fe23077826818f8d680"},
|
||||
{file = "ruff-0.6.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a50af6e828ee692fb10ff2dfe53f05caecf077f4210fae9677e06a808275754f"},
|
||||
{file = "ruff-0.6.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:794ada3400a0d0b89e3015f1a7e01f4c97320ac665b7bc3ade24b50b54cb2972"},
|
||||
{file = "ruff-0.6.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:381413ec47f71ce1d1c614f7779d88886f406f1fd53d289c77e4e533dc6ea200"},
|
||||
{file = "ruff-0.6.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:52e75a82bbc9b42e63c08d22ad0ac525117e72aee9729a069d7c4f235fc4d276"},
|
||||
{file = "ruff-0.6.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09c72a833fd3551135ceddcba5ebdb68ff89225d30758027280968c9acdc7810"},
|
||||
{file = "ruff-0.6.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:800c50371bdcb99b3c1551d5691e14d16d6f07063a518770254227f7f6e8c178"},
|
||||
{file = "ruff-0.6.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e25ddd9cd63ba1f3bd51c1f09903904a6adf8429df34f17d728a8fa11174253"},
|
||||
{file = "ruff-0.6.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7291e64d7129f24d1b0c947ec3ec4c0076e958d1475c61202497c6aced35dd19"},
|
||||
{file = "ruff-0.6.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9ad7dfbd138d09d9a7e6931e6a7e797651ce29becd688be8a0d4d5f8177b4b0c"},
|
||||
{file = "ruff-0.6.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:005256d977021790cc52aa23d78f06bb5090dc0bfbd42de46d49c201533982ae"},
|
||||
{file = "ruff-0.6.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:482c1e6bfeb615eafc5899127b805d28e387bd87db38b2c0c41d271f5e58d8cc"},
|
||||
{file = "ruff-0.6.5-py3-none-win32.whl", hash = "sha256:cf4d3fa53644137f6a4a27a2b397381d16454a1566ae5335855c187fbf67e4f5"},
|
||||
{file = "ruff-0.6.5-py3-none-win_amd64.whl", hash = "sha256:3e42a57b58e3612051a636bc1ac4e6b838679530235520e8f095f7c44f706ff9"},
|
||||
{file = "ruff-0.6.5-py3-none-win_arm64.whl", hash = "sha256:51935067740773afdf97493ba9b8231279e9beef0f2a8079188c4776c25688e0"},
|
||||
{file = "ruff-0.6.5.tar.gz", hash = "sha256:4d32d87fab433c0cf285c3683dd4dae63be05fd7a1d65b3f5bf7cdd05a6b96fb"},
|
||||
{file = "ruff-0.6.8-py3-none-linux_armv6l.whl", hash = "sha256:77944bca110ff0a43b768f05a529fecd0706aac7bcce36d7f1eeb4cbfca5f0f2"},
|
||||
{file = "ruff-0.6.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:27b87e1801e786cd6ede4ada3faa5e254ce774de835e6723fd94551464c56b8c"},
|
||||
{file = "ruff-0.6.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd48f945da2a6334f1793d7f701725a76ba93bf3d73c36f6b21fb04d5338dcf5"},
|
||||
{file = "ruff-0.6.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:677e03c00f37c66cea033274295a983c7c546edea5043d0c798833adf4cf4c6f"},
|
||||
{file = "ruff-0.6.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9f1476236b3eacfacfc0f66aa9e6cd39f2a624cb73ea99189556015f27c0bdeb"},
|
||||
{file = "ruff-0.6.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f5a2f17c7d32991169195d52a04c95b256378bbf0de8cb98478351eb70d526f"},
|
||||
{file = "ruff-0.6.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5fd0d4b7b1457c49e435ee1e437900ced9b35cb8dc5178921dfb7d98d65a08d0"},
|
||||
{file = "ruff-0.6.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8034b19b993e9601f2ddf2c517451e17a6ab5cdb1c13fdff50c1442a7171d87"},
|
||||
{file = "ruff-0.6.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6cfb227b932ba8ef6e56c9f875d987973cd5e35bc5d05f5abf045af78ad8e098"},
|
||||
{file = "ruff-0.6.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ef0411eccfc3909269fed47c61ffebdcb84a04504bafa6b6df9b85c27e813b0"},
|
||||
{file = "ruff-0.6.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:007dee844738c3d2e6c24ab5bc7d43c99ba3e1943bd2d95d598582e9c1b27750"},
|
||||
{file = "ruff-0.6.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ce60058d3cdd8490e5e5471ef086b3f1e90ab872b548814e35930e21d848c9ce"},
|
||||
{file = "ruff-0.6.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1085c455d1b3fdb8021ad534379c60353b81ba079712bce7a900e834859182fa"},
|
||||
{file = "ruff-0.6.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:70edf6a93b19481affd287d696d9e311388d808671bc209fb8907b46a8c3af44"},
|
||||
{file = "ruff-0.6.8-py3-none-win32.whl", hash = "sha256:792213f7be25316f9b46b854df80a77e0da87ec66691e8f012f887b4a671ab5a"},
|
||||
{file = "ruff-0.6.8-py3-none-win_amd64.whl", hash = "sha256:ec0517dc0f37cad14a5319ba7bba6e7e339d03fbf967a6d69b0907d61be7a263"},
|
||||
{file = "ruff-0.6.8-py3-none-win_arm64.whl", hash = "sha256:8d3bb2e3fbb9875172119021a13eed38849e762499e3cfde9588e4b4d70968dc"},
|
||||
{file = "ruff-0.6.8.tar.gz", hash = "sha256:a5bf44b1aa0adaf6d9d20f86162b34f7c593bfedabc51239953e446aefc8ce18"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2218,13 +2220,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "types-pyyaml"
|
||||
version = "6.0.12.20240808"
|
||||
version = "6.0.12.20240917"
|
||||
description = "Typing stubs for PyYAML"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "types-PyYAML-6.0.12.20240808.tar.gz", hash = "sha256:b8f76ddbd7f65440a8bda5526a9607e4c7a322dc2f8e1a8c405644f9a6f4b9af"},
|
||||
{file = "types_PyYAML-6.0.12.20240808-py3-none-any.whl", hash = "sha256:deda34c5c655265fc517b546c902aa6eed2ef8d3e921e4765fe606fe2afe8d35"},
|
||||
{file = "types-PyYAML-6.0.12.20240917.tar.gz", hash = "sha256:d1405a86f9576682234ef83bcb4e6fff7c9305c8b1fbad5e0bcd4f7dbdc9c587"},
|
||||
{file = "types_PyYAML-6.0.12.20240917-py3-none-any.whl", hash = "sha256:392b267f1c0fe6022952462bf5d6523f31e37f6cea49b14cee7ad634b6301570"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2285,13 +2287,13 @@ zstd = ["zstandard (>=0.18.0)"]
|
|||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.26.4"
|
||||
version = "20.26.5"
|
||||
description = "Virtual Python Environment builder"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "virtualenv-20.26.4-py3-none-any.whl", hash = "sha256:48f2695d9809277003f30776d155615ffc11328e6a0a8c1f0ec80188d7874a55"},
|
||||
{file = "virtualenv-20.26.4.tar.gz", hash = "sha256:c17f4e0f3e6036e9f26700446f85c76ab11df65ff6d8a9cbfad9f71aabfcf23c"},
|
||||
{file = "virtualenv-20.26.5-py3-none-any.whl", hash = "sha256:4f3ac17b81fba3ce3bd6f4ead2749a72da5929c01774948e243db9ba41df4ff6"},
|
||||
{file = "virtualenv-20.26.5.tar.gz", hash = "sha256:ce489cac131aa58f4b25e321d6d186171f78e6cb13fafbf32a840cee67733ff4"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
|
@ -110,6 +110,7 @@ model Reminder {
|
|||
reminder_expires_at DateTime
|
||||
reminder_channel_id BigInt
|
||||
reminder_user_id BigInt
|
||||
reminder_sent Boolean @default(false)
|
||||
guild_id BigInt
|
||||
guild Guild @relation(fields: [guild_id], references: [guild_id])
|
||||
|
||||
|
@ -169,4 +170,6 @@ enum CaseType {
|
|||
UNJAIL
|
||||
SNIPPETUNBAN
|
||||
UNTEMPBAN
|
||||
POLLBAN
|
||||
POLLUNBAN
|
||||
}
|
||||
|
|
|
@ -99,7 +99,8 @@ class Mail(commands.Cog):
|
|||
delete_after=30,
|
||||
)
|
||||
|
||||
def _generate_password(self) -> str:
|
||||
@staticmethod
|
||||
def _generate_password() -> str:
|
||||
password = "changeme" + "".join(str(random.randint(0, 9)) for _ in range(6))
|
||||
password += "".join(random.choice("!@#$%^&*") for _ in range(4))
|
||||
return password
|
||||
|
@ -161,7 +162,8 @@ class Mail(commands.Cog):
|
|||
delete_after=30,
|
||||
)
|
||||
|
||||
def _extract_mailbox_info(self, result: list[dict[str, str | None]]) -> str | None:
|
||||
@staticmethod
|
||||
def _extract_mailbox_info(result: list[dict[str, str | None]]) -> str | None:
|
||||
for item in result:
|
||||
if "msg" in item:
|
||||
msg = item["msg"]
|
||||
|
@ -173,8 +175,8 @@ class Mail(commands.Cog):
|
|||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
async def _send_dm(
|
||||
self,
|
||||
interaction: discord.Interaction,
|
||||
member: discord.Member,
|
||||
mailbox_info: str,
|
||||
|
|
|
@ -17,7 +17,6 @@ class Fact(commands.Cog):
|
|||
"Linus Torvalds was around 22 years old when he started work on the Linux Kernel in 1991. In the same year, he also released prototypes of the kernel publicly.",
|
||||
"Linux's 1.0 release was in March 1994.",
|
||||
"Less than 1% of the latest kernel release includes code written by Linus Torvalds.",
|
||||
"Linux is used by every major space programme in the world.",
|
||||
"Approximately 13.3% of the latest Linux kernel is made up of blank lines.",
|
||||
"Vim has various easter eggs. A notable one is found by typing :help 42 into the command bar.",
|
||||
"Slackware is the oldest active linux distribution being released on the 17th July 1993.",
|
||||
|
|
|
@ -14,33 +14,57 @@ from tux.ui.embeds import EmbedCreator
|
|||
class ImgEffect(commands.Cog):
|
||||
def __init__(self, bot: Tux) -> None:
|
||||
self.bot = bot
|
||||
self.allowed_mimetypes = [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
]
|
||||
self.allowed_mimetypes = ["image/jpeg", "image/png"]
|
||||
|
||||
imgeffect = app_commands.Group(name="imgeffect", description="Image effects")
|
||||
|
||||
@imgeffect.command(
|
||||
name="deepfry",
|
||||
description="Deepfry an image",
|
||||
)
|
||||
@imgeffect.command(name="deepfry", description="Deepfry an image")
|
||||
async def deepfry(self, interaction: discord.Interaction, image: discord.Attachment) -> None:
|
||||
"""
|
||||
Deepfry an image.
|
||||
if not self.is_valid_image(image):
|
||||
await self.send_invalid_image_response(interaction)
|
||||
return
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction : discord.Interaction
|
||||
The interaction object for the command.
|
||||
image : discord.File
|
||||
The image to deepfry.
|
||||
"""
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
# check if the image is a image
|
||||
pil_image = await self.fetch_image(image.url)
|
||||
|
||||
if pil_image:
|
||||
deepfried_image = self.deepfry_image(pil_image)
|
||||
await self.send_deepfried_image(interaction, deepfried_image)
|
||||
|
||||
else:
|
||||
await self.send_error_response(interaction)
|
||||
|
||||
def is_valid_image(self, image: discord.Attachment) -> bool:
|
||||
logger.info(f"Content type: {image.content_type}, Filename: {image.filename}, URL: {image.url}")
|
||||
|
||||
if image.content_type not in self.allowed_mimetypes:
|
||||
return image.content_type in self.allowed_mimetypes
|
||||
|
||||
@staticmethod
|
||||
async def fetch_image(url: str) -> Image.Image:
|
||||
logger.info("Fetching image from URL with HTTPX...")
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(url)
|
||||
|
||||
return Image.open(io.BytesIO(response.content)).convert("RGB")
|
||||
|
||||
@staticmethod
|
||||
def deepfry_image(pil_image: Image.Image) -> Image.Image:
|
||||
pil_image = pil_image.resize((int(pil_image.width * 0.25), int(pil_image.height * 0.25)))
|
||||
pil_image = ImageEnhance.Sharpness(pil_image).enhance(100.0)
|
||||
|
||||
r = pil_image.split()[0]
|
||||
r = ImageEnhance.Contrast(r).enhance(2.0)
|
||||
r = ImageEnhance.Brightness(r).enhance(1.5)
|
||||
|
||||
colours = ((254, 0, 2), (255, 255, 15))
|
||||
r = ImageOps.colorize(r, colours[0], colours[1])
|
||||
pil_image = Image.blend(pil_image, r, 0.75)
|
||||
|
||||
return pil_image.resize((int(pil_image.width * 4), int(pil_image.height * 4)))
|
||||
|
||||
async def send_invalid_image_response(self, interaction: discord.Interaction) -> None:
|
||||
logger.error("The file is not a permitted image.")
|
||||
|
||||
embed = EmbedCreator.create_embed(
|
||||
|
@ -53,47 +77,27 @@ class ImgEffect(commands.Cog):
|
|||
)
|
||||
|
||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||
return
|
||||
|
||||
# say that the image is being processed
|
||||
logger.info("Processing image...")
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
async def send_error_response(self, interaction: discord.Interaction) -> None:
|
||||
logger.error("Error processing the image.")
|
||||
|
||||
# open url with PIL
|
||||
logger.info("Opening image with PIL and HTTPX...")
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(image.url)
|
||||
embed = EmbedCreator.create_embed(
|
||||
bot=self.bot,
|
||||
embed_type=EmbedCreator.ERROR,
|
||||
user_name=interaction.user.name,
|
||||
user_display_avatar=interaction.user.display_avatar.url,
|
||||
title="Error",
|
||||
description="An error occurred while processing the image.",
|
||||
)
|
||||
|
||||
pil_image = Image.open(io.BytesIO(response.content))
|
||||
pil_image = pil_image.convert("RGB")
|
||||
logger.info("Image opened with PIL.")
|
||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||
|
||||
# resize image to 25% then back to original size
|
||||
logger.info("Resizing image...")
|
||||
pil_image = pil_image.resize((int(pil_image.width * 0.25), int(pil_image.height * 0.25)))
|
||||
logger.info("Image resized.")
|
||||
|
||||
# increase sharpness
|
||||
logger.info("Increasing sharpness...")
|
||||
pil_image = ImageEnhance.Sharpness(pil_image).enhance(100.0)
|
||||
logger.info("Sharpness increased.")
|
||||
|
||||
logger.info("Adjusting color...")
|
||||
r = pil_image.split()[0]
|
||||
r = ImageEnhance.Contrast(r).enhance(2.0)
|
||||
r = ImageEnhance.Brightness(r).enhance(1.5)
|
||||
|
||||
colours = ((254, 0, 2), (255, 255, 15))
|
||||
r = ImageOps.colorize(r, colours[0], colours[1])
|
||||
pil_image = Image.blend(pil_image, r, 0.75)
|
||||
logger.info("Color adjustment complete.")
|
||||
|
||||
# send image
|
||||
logger.info("Sending image...")
|
||||
pil_image = pil_image.resize((int(pil_image.width * 4), int(pil_image.height * 4)))
|
||||
@staticmethod
|
||||
async def send_deepfried_image(interaction: discord.Interaction, deepfried_image: Image.Image) -> None:
|
||||
arr = io.BytesIO()
|
||||
pil_image.save(arr, format="JPEG", quality=1)
|
||||
deepfried_image.save(arr, format="JPEG", quality=1)
|
||||
arr.seek(0)
|
||||
|
||||
file = discord.File(arr, filename="deepfried.jpg")
|
||||
|
||||
await interaction.followup.send(file=file, ephemeral=True)
|
||||
|
|
|
@ -57,7 +57,13 @@ class Random(commands.Cog):
|
|||
aliases=["eightball", "8b"],
|
||||
)
|
||||
@commands.guild_only()
|
||||
async def eight_ball(self, ctx: commands.Context[Tux], *, question: str, cow: bool = False) -> None:
|
||||
async def eight_ball(
|
||||
self,
|
||||
ctx: commands.Context[Tux],
|
||||
*,
|
||||
question: str,
|
||||
cow: bool = False,
|
||||
) -> None:
|
||||
"""
|
||||
Ask the magic 8ball a question.
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ class Info(commands.Cog):
|
|||
custom_color=discord.Color.blurple(),
|
||||
custom_author_text="Server Information",
|
||||
custom_author_icon_url=guild.icon.url,
|
||||
custom_footer_text=f"ID: {guild.id} | Created: {guild.created_at.strftime('%B %d, %Y')}",
|
||||
custom_footer_text=f"ID: {guild.id} | Created: {guild.created_at.strftime("%B %d, %Y")}",
|
||||
)
|
||||
.add_field(name="Owner", value=str(guild.owner.mention) if guild.owner else "Unknown")
|
||||
.add_field(name="Vanity URL", value=guild.vanity_url_code or "None")
|
||||
|
@ -213,7 +213,7 @@ class Info(commands.Cog):
|
|||
menu: ViewMenu = ViewMenu(ctx, menu_type=ViewMenu.TypeEmbed)
|
||||
for chunk in chunks:
|
||||
page_embed: discord.Embed = embed.copy()
|
||||
page_embed.description = f"{list_type.capitalize()} list for {guild_name}:\n{' '.join(chunk)}"
|
||||
page_embed.description = f"{list_type.capitalize()} list for {guild_name}:\n{" ".join(chunk)}"
|
||||
menu.add_page(page_embed)
|
||||
|
||||
buttons = [
|
||||
|
@ -229,7 +229,8 @@ class Info(commands.Cog):
|
|||
|
||||
await menu.start()
|
||||
|
||||
def _chunks(self, it: Iterator[str], size: int) -> Generator[list[str], None, None]:
|
||||
@staticmethod
|
||||
def _chunks(it: Iterator[str], size: int) -> Generator[list[str], None, None]:
|
||||
"""
|
||||
Split an iterator into chunks of a specified size.
|
||||
|
||||
|
|
|
@ -100,8 +100,8 @@ class ModerationCogBase(commands.Cog):
|
|||
if isinstance(log_channel, discord.TextChannel):
|
||||
await log_channel.send(embed=embed)
|
||||
|
||||
@staticmethod
|
||||
async def send_dm(
|
||||
self,
|
||||
ctx: commands.Context[Tux],
|
||||
silent: bool,
|
||||
user: discord.Member,
|
||||
|
@ -250,3 +250,31 @@ class ModerationCogBase(commands.Cog):
|
|||
|
||||
await self.send_embed(ctx, embed, log_type="mod")
|
||||
await ctx.send(embed=embed, delete_after=30, ephemeral=True)
|
||||
|
||||
async def is_pollbanned(self, guild_id: int, user_id: int) -> bool:
|
||||
"""
|
||||
Check if a user is poll banned.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
guild_id : int
|
||||
The ID of the guild to check in.
|
||||
user_id : int
|
||||
The ID of the user to check.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if the user is poll banned, False otherwise.
|
||||
"""
|
||||
|
||||
# ban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLBAN)
|
||||
# unban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN)
|
||||
|
||||
ban_cases = await self.db.case.get_all_cases_by_type(guild_id, CaseType.POLLBAN)
|
||||
unban_cases = await self.db.case.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN)
|
||||
|
||||
ban_count = sum(case.case_user_id == user_id for case in ban_cases)
|
||||
unban_count = sum(case.case_user_id == user_id for case in unban_cases)
|
||||
|
||||
return ban_count > unban_count
|
||||
|
|
|
@ -319,8 +319,8 @@ class Cases(ModerationCogBase):
|
|||
|
||||
await menu.start()
|
||||
|
||||
@staticmethod
|
||||
def _create_case_fields(
|
||||
self,
|
||||
moderator: discord.Member,
|
||||
user: discord.Member | discord.User,
|
||||
reason: str,
|
||||
|
@ -361,7 +361,8 @@ class Cases(ModerationCogBase):
|
|||
|
||||
return embed
|
||||
|
||||
def _format_emoji(self, emoji: discord.Emoji | None) -> str:
|
||||
@staticmethod
|
||||
def _format_emoji(emoji: discord.Emoji | None) -> str:
|
||||
return f"<:{emoji.name}:{emoji.id}>" if emoji else ""
|
||||
|
||||
def _get_case_status_emoji(self, case_status: bool | None) -> discord.Emoji | None:
|
||||
|
@ -392,16 +393,16 @@ class Cases(ModerationCogBase):
|
|||
def _get_case_action_emoji(self, case_type: CaseType) -> discord.Emoji | None:
|
||||
action = None
|
||||
|
||||
if case_type in [
|
||||
if case_type in {
|
||||
CaseType.BAN,
|
||||
CaseType.KICK,
|
||||
CaseType.TIMEOUT,
|
||||
CaseType.WARN,
|
||||
CaseType.JAIL,
|
||||
CaseType.SNIPPETBAN,
|
||||
]:
|
||||
}:
|
||||
action = "added"
|
||||
elif case_type in [CaseType.UNBAN, CaseType.UNTIMEOUT, CaseType.UNJAIL, CaseType.SNIPPETUNBAN]:
|
||||
elif case_type in {CaseType.UNBAN, CaseType.UNTIMEOUT, CaseType.UNJAIL, CaseType.SNIPPETUNBAN}:
|
||||
action = "removed"
|
||||
|
||||
if action is not None:
|
||||
|
@ -410,8 +411,8 @@ class Cases(ModerationCogBase):
|
|||
return self.bot.get_emoji(emoji_id)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _get_case_description(
|
||||
self,
|
||||
case: Case,
|
||||
case_status_emoji: str,
|
||||
case_type_emoji: str,
|
||||
|
|
|
@ -105,8 +105,8 @@ class Jail(ModerationCogBase):
|
|||
dm_sent = await self.send_dm(ctx, flags.silent, member, flags.reason, "jailed")
|
||||
await self.handle_case_response(ctx, CaseType.JAIL, case.case_number, flags.reason, member, dm_sent)
|
||||
|
||||
@staticmethod
|
||||
def _get_manageable_roles(
|
||||
self,
|
||||
member: discord.Member,
|
||||
jail_role: discord.Role,
|
||||
) -> list[discord.Role]:
|
||||
|
|
71
tux/cogs/moderation/pollban.py
Normal file
71
tux/cogs/moderation/pollban.py
Normal file
|
@ -0,0 +1,71 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from loguru import logger
|
||||
|
||||
from prisma.enums import CaseType
|
||||
from tux.bot import Tux
|
||||
from tux.database.controllers.case import CaseController
|
||||
from tux.utils import checks
|
||||
from tux.utils.flags import PollBanFlags, generate_usage
|
||||
|
||||
from . import ModerationCogBase
|
||||
|
||||
|
||||
class PollBan(ModerationCogBase):
|
||||
def __init__(self, bot: Tux) -> None:
|
||||
super().__init__(bot)
|
||||
self.case_controller = CaseController()
|
||||
self.poll_ban.usage = generate_usage(self.poll_ban, PollBanFlags)
|
||||
|
||||
@commands.hybrid_command(
|
||||
name="pollban",
|
||||
aliases=["pb"],
|
||||
)
|
||||
@commands.guild_only()
|
||||
@checks.has_pl(3)
|
||||
async def poll_ban(
|
||||
self,
|
||||
ctx: commands.Context[Tux],
|
||||
member: discord.Member,
|
||||
*,
|
||||
flags: PollBanFlags,
|
||||
) -> None:
|
||||
"""
|
||||
Ban a user from creating polls using tux.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx : commands.Context[Tux]
|
||||
The context object.
|
||||
member : discord.Member
|
||||
The member to poll ban.
|
||||
flags : PollBanFlags
|
||||
The flags for the command. (reason: str, silent: bool)
|
||||
"""
|
||||
|
||||
assert ctx.guild
|
||||
|
||||
if await self.is_pollbanned(ctx.guild.id, member.id):
|
||||
await ctx.send("User is already poll banned.", delete_after=30, ephemeral=True)
|
||||
return
|
||||
|
||||
try:
|
||||
case = await self.db.case.insert_case(
|
||||
case_user_id=member.id,
|
||||
case_moderator_id=ctx.author.id,
|
||||
case_type=CaseType.POLLBAN,
|
||||
case_reason=flags.reason,
|
||||
guild_id=ctx.guild.id,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to ban {member}. {e}")
|
||||
await ctx.send(f"Failed to ban {member}. {e}", delete_after=30)
|
||||
return
|
||||
|
||||
dm_sent = await self.send_dm(ctx, flags.silent, member, flags.reason, "poll banned")
|
||||
await self.handle_case_response(ctx, CaseType.POLLBAN, case.case_number, flags.reason, member, dm_sent)
|
||||
|
||||
|
||||
async def setup(bot: Tux) -> None:
|
||||
await bot.add_cog(PollBan(bot))
|
71
tux/cogs/moderation/pollunban.py
Normal file
71
tux/cogs/moderation/pollunban.py
Normal file
|
@ -0,0 +1,71 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from loguru import logger
|
||||
|
||||
from prisma.enums import CaseType
|
||||
from tux.bot import Tux
|
||||
from tux.database.controllers.case import CaseController
|
||||
from tux.utils import checks
|
||||
from tux.utils.flags import PollUnbanFlags, generate_usage
|
||||
|
||||
from . import ModerationCogBase
|
||||
|
||||
|
||||
class PollUnban(ModerationCogBase):
|
||||
def __init__(self, bot: Tux) -> None:
|
||||
super().__init__(bot)
|
||||
self.case_controller = CaseController()
|
||||
self.poll_unban.usage = generate_usage(self.poll_unban, PollUnbanFlags)
|
||||
|
||||
@commands.hybrid_command(
|
||||
name="pollunban",
|
||||
aliases=["pub"],
|
||||
)
|
||||
@commands.guild_only()
|
||||
@checks.has_pl(3)
|
||||
async def poll_unban(
|
||||
self,
|
||||
ctx: commands.Context[Tux],
|
||||
member: discord.Member,
|
||||
*,
|
||||
flags: PollUnbanFlags,
|
||||
):
|
||||
"""
|
||||
Unban a user from creating snippets.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx : commands.Context[Tux]
|
||||
The context object.
|
||||
member : discord.Member
|
||||
The member to snippet unban.
|
||||
flags : PollUnbanFlags
|
||||
The flags for the command. (reason: str, silent: bool)
|
||||
"""
|
||||
|
||||
assert ctx.guild
|
||||
|
||||
if not await self.is_pollbanned(ctx.guild.id, member.id):
|
||||
await ctx.send("User is not poll banned.", delete_after=30, ephemeral=True)
|
||||
return
|
||||
|
||||
try:
|
||||
case = await self.db.case.insert_case(
|
||||
case_user_id=member.id,
|
||||
case_moderator_id=ctx.author.id,
|
||||
case_type=CaseType.POLLUNBAN,
|
||||
case_reason=flags.reason,
|
||||
guild_id=ctx.guild.id,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to poll unban {member}. {e}")
|
||||
await ctx.send(f"Failed to poll unban {member}. {e}", delete_after=30, ephemeral=True)
|
||||
return
|
||||
|
||||
dm_sent = await self.send_dm(ctx, flags.silent, member, flags.reason, "poll unbanned")
|
||||
await self.handle_case_response(ctx, CaseType.POLLUNBAN, case.case_number, flags.reason, member, dm_sent)
|
||||
|
||||
|
||||
async def setup(bot: Tux) -> None:
|
||||
await bot.add_cog(PollUnban(bot))
|
|
@ -15,7 +15,8 @@ class Slowmode(commands.Cog):
|
|||
@commands.hybrid_command(
|
||||
name="slowmode",
|
||||
aliases=["sm"],
|
||||
usage="slowmode <delay|get> [channel]\nor slowmode [channel] <delay|get>", # only place where generate_usage shouldn't be used
|
||||
# only place where generate_usage shouldn't be used:
|
||||
usage="slowmode <delay|get> [channel]\nor slowmode [channel] <delay|get>",
|
||||
)
|
||||
@commands.guild_only()
|
||||
@checks.has_pl(2)
|
||||
|
@ -83,11 +84,12 @@ class Slowmode(commands.Cog):
|
|||
|
||||
return action, channel
|
||||
|
||||
def _get_channel(self, ctx: commands.Context[Tux]) -> discord.TextChannel | discord.Thread | None:
|
||||
@staticmethod
|
||||
def _get_channel(ctx: commands.Context[Tux]) -> discord.TextChannel | discord.Thread | None:
|
||||
return ctx.channel if isinstance(ctx.channel, discord.TextChannel | discord.Thread) else None
|
||||
|
||||
@staticmethod
|
||||
async def _get_slowmode(
|
||||
self,
|
||||
ctx: commands.Context[Tux],
|
||||
channel: discord.TextChannel | discord.Thread,
|
||||
) -> None:
|
||||
|
@ -135,7 +137,8 @@ class Slowmode(commands.Cog):
|
|||
await ctx.send(f"Failed to set slowmode. Error: {error}", delete_after=30, ephemeral=True)
|
||||
logger.error(f"Failed to set slowmode. Error: {error}")
|
||||
|
||||
def _parse_delay(self, delay: str) -> int | None:
|
||||
@staticmethod
|
||||
def _parse_delay(delay: str) -> int | None:
|
||||
try:
|
||||
if delay.endswith("s"):
|
||||
delay = delay[:-1]
|
||||
|
|
|
@ -71,8 +71,8 @@ class Bookmarks(commands.Cog):
|
|||
|
||||
return embed
|
||||
|
||||
@staticmethod
|
||||
async def _send_bookmark(
|
||||
self,
|
||||
user: discord.User,
|
||||
message: discord.Message,
|
||||
embed: discord.Embed,
|
||||
|
|
|
@ -96,7 +96,6 @@ class GifLimiter(commands.Cog):
|
|||
self.recent_gifs_by_channel[channel_id] = [
|
||||
t for t in timestamps if current_time - t < self.recent_gif_age
|
||||
]
|
||||
|
||||
for user_id, timestamps in list(self.recent_gifs_by_user.items()):
|
||||
filtered_timestamps = [t for t in timestamps if current_time - t < self.recent_gif_age]
|
||||
if filtered_timestamps:
|
||||
|
|
|
@ -3,7 +3,9 @@ from discord import app_commands
|
|||
from discord.ext import commands
|
||||
from loguru import logger
|
||||
|
||||
from prisma.enums import CaseType
|
||||
from tux.bot import Tux
|
||||
from tux.database.controllers import CaseController
|
||||
from tux.ui.embeds import EmbedCreator
|
||||
|
||||
# TODO: Create option inputs for the poll command instead of using a comma separated string
|
||||
|
@ -12,6 +14,35 @@ from tux.ui.embeds import EmbedCreator
|
|||
class Poll(commands.Cog):
|
||||
def __init__(self, bot: Tux) -> None:
|
||||
self.bot = bot
|
||||
self.case_controller = CaseController()
|
||||
|
||||
# TODO: for the moment this is duplicated code from ModerationCogBase in a attempt to get the code out sooner
|
||||
async def is_pollbanned(self, guild_id: int, user_id: int) -> bool:
|
||||
"""
|
||||
Check if a user is poll banned.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
guild_id : int
|
||||
The ID of the guild to check in.
|
||||
user_id : int
|
||||
The ID of the user to check.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if the user is poll banned, False otherwise.
|
||||
"""
|
||||
|
||||
ban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLBAN)
|
||||
unban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN)
|
||||
|
||||
ban_count = sum(case.case_user_id == user_id for case in ban_cases)
|
||||
unban_count = sum(case.case_user_id == user_id for case in unban_cases)
|
||||
|
||||
return (
|
||||
ban_count > unban_count
|
||||
) # TODO: this implementation is flawed, if someone bans and unbans the same user multiple times, this will not work as expected
|
||||
|
||||
@commands.Cog.listener() # listen for messages
|
||||
async def on_message(self, message: discord.Message) -> None:
|
||||
|
@ -40,7 +71,6 @@ class Poll(commands.Cog):
|
|||
@commands.Cog.listener()
|
||||
async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User) -> None:
|
||||
# Block any reactions that are not numbers for the poll
|
||||
|
||||
if reaction.message.embeds:
|
||||
embed = reaction.message.embeds[0]
|
||||
if (
|
||||
|
@ -64,7 +94,12 @@ class Poll(commands.Cog):
|
|||
The title of the poll.
|
||||
options : str
|
||||
The options for the poll, separated by commas.
|
||||
|
||||
|
||||
"""
|
||||
if interaction.guild_id is None:
|
||||
await interaction.response.send_message("This command can only be used in a server.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Split the options by comma
|
||||
options_list = options.split(",")
|
||||
|
@ -72,6 +107,17 @@ class Poll(commands.Cog):
|
|||
# Remove any leading or trailing whitespaces from the options
|
||||
options_list = [option.strip() for option in options_list]
|
||||
|
||||
if await self.is_pollbanned(interaction.guild_id, interaction.user.id):
|
||||
embed = EmbedCreator.create_embed(
|
||||
bot=self.bot,
|
||||
embed_type=EmbedCreator.ERROR,
|
||||
user_name=interaction.user.name,
|
||||
user_display_avatar=interaction.user.display_avatar.url,
|
||||
title="Poll Banned",
|
||||
description="You are poll banned and cannot create a poll.",
|
||||
)
|
||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||
return
|
||||
# Check if the options count is between 2-9
|
||||
if len(options_list) < 2 or len(options_list) > 9:
|
||||
embed = EmbedCreator.create_embed(
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import asyncio
|
||||
import contextlib
|
||||
import datetime
|
||||
|
||||
import discord
|
||||
from discord import app_commands
|
||||
from discord.ext import commands
|
||||
from discord.ext import commands, tasks
|
||||
from loguru import logger
|
||||
|
||||
from prisma.models import Reminder
|
||||
|
@ -14,40 +13,26 @@ from tux.ui.embeds import EmbedCreator
|
|||
from tux.utils.functions import convert_to_seconds
|
||||
|
||||
|
||||
def get_closest_reminder(reminders: list[Reminder]) -> Reminder | None:
|
||||
"""
|
||||
Check if there are any reminders and return the closest one.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
reminders : list[Reminder]
|
||||
A list of reminders to check.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Reminder | None
|
||||
The closest reminder or None if there are no reminders.
|
||||
"""
|
||||
return min(reminders, key=lambda x: x.reminder_expires_at) if reminders else None
|
||||
|
||||
|
||||
class RemindMe(commands.Cog):
|
||||
def __init__(self, bot: Tux) -> None:
|
||||
self.bot = bot
|
||||
self.db = DatabaseController().reminder
|
||||
self.bot.loop.create_task(self.update())
|
||||
self.check_reminders.start()
|
||||
|
||||
async def send_reminders(self, reminder: Reminder) -> None:
|
||||
"""
|
||||
Send the reminder to the user.
|
||||
@tasks.loop(seconds=120)
|
||||
async def check_reminders(self):
|
||||
reminders = await self.db.get_unsent_reminders()
|
||||
|
||||
Parameters
|
||||
----------
|
||||
reminder : Reminder
|
||||
The reminder object.
|
||||
"""
|
||||
try:
|
||||
for reminder in reminders:
|
||||
await self.send_reminder(reminder)
|
||||
await self.db.update_reminder_status(reminder.reminder_id, sent=True)
|
||||
logger.debug(f'Status of reminder {reminder.reminder_id} updated to "sent".')
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error sending reminders: {e}")
|
||||
|
||||
async def send_reminder(self, reminder: Reminder) -> None:
|
||||
user = self.bot.get_user(reminder.reminder_user_id)
|
||||
|
||||
if user is not None:
|
||||
|
@ -64,103 +49,37 @@ class RemindMe(commands.Cog):
|
|||
await user.send(embed=embed)
|
||||
|
||||
except discord.Forbidden:
|
||||
# Send a message in the channel if the user has DMs closed
|
||||
channel: discord.abc.GuildChannel | discord.Thread | discord.abc.PrivateChannel | None = (
|
||||
self.bot.get_channel(reminder.reminder_channel_id)
|
||||
)
|
||||
channel = self.bot.get_channel(reminder.reminder_channel_id)
|
||||
|
||||
if channel is not None and isinstance(
|
||||
channel,
|
||||
discord.TextChannel | discord.Thread | discord.VoiceChannel,
|
||||
):
|
||||
if isinstance(channel, discord.TextChannel | discord.Thread | discord.VoiceChannel):
|
||||
with contextlib.suppress(discord.Forbidden):
|
||||
await channel.send(
|
||||
content=f"{user.mention} Failed to DM you, sending in channel",
|
||||
embed=embed,
|
||||
)
|
||||
return
|
||||
|
||||
else:
|
||||
logger.error(
|
||||
f"Failed to send reminder to {user.id}, DMs closed and channel not found.",
|
||||
f"Failed to send reminder {reminder.reminder_id}, DMs closed and channel not found.",
|
||||
)
|
||||
|
||||
else:
|
||||
logger.error(f"Failed to send reminder to {reminder.reminder_user_id}, user not found.")
|
||||
logger.error(
|
||||
f"Failed to send reminder {reminder.reminder_id}, user with ID {reminder.reminder_user_id} not found.",
|
||||
)
|
||||
|
||||
# Delete the reminder after sending
|
||||
await self.db.delete_reminder_by_id(reminder.reminder_id)
|
||||
|
||||
# wait for a second so that the reminder is deleted before checking for more reminders
|
||||
# who knows if this works, it seems to
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# Run update again to check if there are any more reminders
|
||||
await self.update()
|
||||
|
||||
async def end_timer(self, reminder: Reminder) -> None:
|
||||
"""
|
||||
End the timer for the reminder.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
reminder : Reminder
|
||||
The reminder object.
|
||||
"""
|
||||
|
||||
# Wait until the reminder expires
|
||||
await discord.utils.sleep_until(reminder.reminder_expires_at)
|
||||
await self.send_reminders(reminder)
|
||||
|
||||
async def update(self) -> None:
|
||||
"""
|
||||
Update the reminders
|
||||
|
||||
Check if there are any reminders and send the closest one.
|
||||
"""
|
||||
|
||||
try:
|
||||
# Get all reminders
|
||||
reminders = await self.db.get_all_reminders()
|
||||
# Get the closest reminder
|
||||
closest_reminder = get_closest_reminder(reminders)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting reminders: {e}")
|
||||
return
|
||||
|
||||
# If there are no reminders, return
|
||||
if closest_reminder is None:
|
||||
return
|
||||
|
||||
# Check if it's expired
|
||||
if closest_reminder.reminder_expires_at < datetime.datetime.now(datetime.UTC):
|
||||
await self.send_reminders(closest_reminder)
|
||||
return
|
||||
|
||||
# Create a task to wait until the reminder expires
|
||||
self.bot.loop.create_task(self.end_timer(closest_reminder))
|
||||
@check_reminders.before_loop
|
||||
async def before_check_reminders(self):
|
||||
await self.bot.wait_until_ready()
|
||||
|
||||
@app_commands.command(
|
||||
name="remindme",
|
||||
description="Reminds you after a certain amount of time.",
|
||||
)
|
||||
async def remindme(self, interaction: discord.Interaction, time: str, *, reminder: str) -> None:
|
||||
"""
|
||||
Set a reminder for a certain amount of time.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interaction : discord.Interaction
|
||||
The discord interaction object.
|
||||
time : str
|
||||
Time in the format `[number][M/w/d/h/m/s]`.
|
||||
reminder : str
|
||||
Reminder content.
|
||||
"""
|
||||
|
||||
seconds = convert_to_seconds(time)
|
||||
|
||||
# Check if the time is valid (this is set to 0 if the time is invalid via convert_to_seconds)
|
||||
if seconds == 0:
|
||||
await interaction.response.send_message(
|
||||
"Invalid time format. Please use the format `[number][M/w/d/h/m/s]`.",
|
||||
|
@ -169,13 +88,13 @@ class RemindMe(commands.Cog):
|
|||
)
|
||||
return
|
||||
|
||||
seconds = datetime.datetime.now(datetime.UTC) + datetime.timedelta(seconds=seconds)
|
||||
expires_at = datetime.datetime.now(datetime.UTC) + datetime.timedelta(seconds=seconds)
|
||||
|
||||
try:
|
||||
await self.db.insert_reminder(
|
||||
reminder_user_id=interaction.user.id,
|
||||
reminder_content=reminder,
|
||||
reminder_expires_at=seconds,
|
||||
reminder_expires_at=expires_at,
|
||||
reminder_channel_id=interaction.channel_id or 0,
|
||||
guild_id=interaction.guild_id or 0,
|
||||
)
|
||||
|
@ -186,12 +105,13 @@ class RemindMe(commands.Cog):
|
|||
user_name=interaction.user.name,
|
||||
user_display_avatar=interaction.user.display_avatar.url,
|
||||
title="Reminder Set",
|
||||
description=f"Reminder set for <t:{int(seconds.timestamp())}:f>.",
|
||||
description=f"Reminder set for <t:{int(expires_at.timestamp())}:f>.",
|
||||
)
|
||||
|
||||
embed.add_field(
|
||||
name="Note",
|
||||
value="If you have DMs closed, the reminder may not reach you. We will attempt to send it in this channel instead, however it is not guaranteed.",
|
||||
value="- If you have DMs closed, we will attempt to send it in this channel instead.\n"
|
||||
"- The reminder may be delayed by up to 120 seconds due to the way Tux works.",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
@ -207,9 +127,6 @@ class RemindMe(commands.Cog):
|
|||
|
||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||
|
||||
# Run update again to check if this reminder is the closest
|
||||
await self.update()
|
||||
|
||||
|
||||
async def setup(bot: Tux) -> None:
|
||||
await bot.add_cog(RemindMe(bot))
|
||||
|
|
|
@ -46,7 +46,8 @@ class Run(commands.Cog):
|
|||
self.run.usage = generate_usage(self.run)
|
||||
self.languages.usage = generate_usage(self.languages)
|
||||
|
||||
def remove_ansi(self, ansi: str) -> str:
|
||||
@staticmethod
|
||||
def remove_ansi(ansi: str) -> str:
|
||||
"""
|
||||
Converts ANSI encoded text into non-ANSI.
|
||||
|
||||
|
@ -63,7 +64,8 @@ class Run(commands.Cog):
|
|||
|
||||
return ansi_re.sub("", ansi)
|
||||
|
||||
def remove_backticks(self, st: str) -> str:
|
||||
@staticmethod
|
||||
def remove_backticks(st: str) -> str:
|
||||
"""
|
||||
Removes backticks from the provided string.
|
||||
|
||||
|
@ -277,7 +279,7 @@ class Run(commands.Cog):
|
|||
code,
|
||||
)
|
||||
await msg.delete()
|
||||
if filtered_output == "" and gen_one == "" and normalized_lang == "":
|
||||
if not filtered_output and not gen_one and not normalized_lang:
|
||||
return
|
||||
await self.send_embedded_reply(
|
||||
ctx,
|
||||
|
@ -340,7 +342,7 @@ class Run(commands.Cog):
|
|||
user_name=ctx.author.name,
|
||||
user_display_avatar=ctx.author.display_avatar.url,
|
||||
title="Supported Languages",
|
||||
description=f"```{', '.join(compiler_map.keys())}```",
|
||||
description=f"```{", ".join(compiler_map.keys())}```",
|
||||
)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
|
|
@ -321,7 +321,7 @@ class Snippets(commands.Cog):
|
|||
embed.add_field(name="Name", value=snippet.snippet_name, inline=False)
|
||||
embed.add_field(
|
||||
name="Author",
|
||||
value=f"{author.mention if author else f'<@!{snippet.snippet_user_id}>'}",
|
||||
value=f"{author.mention if author else f"<@!{snippet.snippet_user_id}>"}",
|
||||
inline=False,
|
||||
)
|
||||
embed.add_field(name="Content", value=f"> {snippet.snippet_content}", inline=False)
|
||||
|
@ -495,7 +495,7 @@ class Snippets(commands.Cog):
|
|||
if author := self.bot.get_user(snippet.snippet_user_id):
|
||||
with contextlib.suppress(discord.Forbidden):
|
||||
await author.send(
|
||||
f"""Your snippet `{snippet.snippet_name}` has been {'locked' if status.locked else 'unlocked'}.
|
||||
f"""Your snippet `{snippet.snippet_name}` has been {"locked" if status.locked else "unlocked"}.
|
||||
|
||||
**What does this mean?**
|
||||
If a snippet is locked, it cannot be edited by anyone other than moderators. This means that you can no longer edit this snippet.
|
||||
|
|
|
@ -135,7 +135,8 @@ class Tldr(commands.Cog):
|
|||
|
||||
return self._run_subprocess(["tldr", "--list"], "No TLDR pages found.").split("\n")
|
||||
|
||||
def _run_subprocess(self, command_list: list[str], default_response: str) -> str:
|
||||
@staticmethod
|
||||
def _run_subprocess(command_list: list[str], default_response: str) -> str:
|
||||
"""
|
||||
Helper method to run subprocesses for CLI interactions.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from datetime import datetime
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from prisma.models import Guild, Reminder
|
||||
from tux.database.client import db
|
||||
|
@ -21,6 +21,10 @@ class ReminderController:
|
|||
async def get_reminder_by_id(self, reminder_id: int) -> Reminder | None:
|
||||
return await self.table.find_first(where={"reminder_id": reminder_id})
|
||||
|
||||
async def get_unsent_reminders(self) -> list[Reminder]:
|
||||
now = datetime.now(UTC)
|
||||
return await self.table.find_many(where={"reminder_sent": False, "reminder_expires_at": {"lte": now}})
|
||||
|
||||
async def insert_reminder(
|
||||
self,
|
||||
reminder_user_id: int,
|
||||
|
@ -38,6 +42,7 @@ class ReminderController:
|
|||
"reminder_expires_at": reminder_expires_at,
|
||||
"reminder_channel_id": reminder_channel_id,
|
||||
"guild_id": guild_id,
|
||||
"reminder_sent": False,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -53,3 +58,19 @@ class ReminderController:
|
|||
where={"reminder_id": reminder_id},
|
||||
data={"reminder_content": reminder_content},
|
||||
)
|
||||
|
||||
async def update_reminder_status(self, reminder_id: int, sent: bool = True) -> None:
|
||||
"""
|
||||
Update the status of a reminder. This sets the value "reminder_sent" to True by default.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
reminder_id : int
|
||||
The ID of the reminder to update.
|
||||
sent : bool
|
||||
The new status of the reminder.
|
||||
"""
|
||||
await self.table.update(
|
||||
where={"reminder_id": reminder_id},
|
||||
data={"reminder_sent": sent},
|
||||
)
|
||||
|
|
|
@ -13,7 +13,8 @@ class ActivityHandler(commands.Cog):
|
|||
self.delay = delay
|
||||
self.activities = self.build_activity_list()
|
||||
|
||||
def build_activity_list(self) -> list[discord.Activity | discord.Streaming]:
|
||||
@staticmethod
|
||||
def build_activity_list() -> list[discord.Activity | discord.Streaming]:
|
||||
activity_data = [
|
||||
{"type": discord.ActivityType.watching, "name": "{member_count} members"},
|
||||
{"type": discord.ActivityType.watching, "name": "All Things Linux"},
|
||||
|
|
|
@ -273,7 +273,8 @@ class ErrorHandler(commands.Cog):
|
|||
|
||||
return error_map.get(type(error), self.error_message).format(error=error)
|
||||
|
||||
def log_error_traceback(self, error: Exception) -> None:
|
||||
@staticmethod
|
||||
def log_error_traceback(error: Exception) -> None:
|
||||
"""
|
||||
Log the error traceback.
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@ class EventHandler(commands.Cog):
|
|||
async def on_guild_remove(self, guild: discord.Guild) -> None:
|
||||
await self.db.guild.delete_guild_by_id(guild.id)
|
||||
|
||||
async def handle_harmful_message(self, message: discord.Message) -> None:
|
||||
@staticmethod
|
||||
async def handle_harmful_message(message: discord.Message) -> None:
|
||||
if message.author.bot:
|
||||
return
|
||||
|
||||
|
|
35
tux/help.py
35
tux/help.py
|
@ -38,7 +38,8 @@ class TuxHelp(commands.HelpCommand):
|
|||
|
||||
return self.context.clean_prefix or CONST.DEFAULT_PREFIX
|
||||
|
||||
def _embed_base(self, title: str, description: str | None = None) -> discord.Embed:
|
||||
@staticmethod
|
||||
def _embed_base(title: str, description: str | None = None) -> discord.Embed:
|
||||
"""
|
||||
Creates a base embed with uniform styling.
|
||||
|
||||
|
@ -61,8 +62,8 @@ class TuxHelp(commands.HelpCommand):
|
|||
color=CONST.EMBED_COLORS["DEFAULT"],
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _add_command_field(
|
||||
self,
|
||||
embed: discord.Embed,
|
||||
command: commands.Command[Any, Any, Any],
|
||||
prefix: str,
|
||||
|
@ -84,11 +85,12 @@ class TuxHelp(commands.HelpCommand):
|
|||
|
||||
embed.add_field(
|
||||
name=f"{prefix}{command.qualified_name} ({command_aliases})",
|
||||
value=f"> {command.short_doc or 'No documentation summary.'}",
|
||||
value=f"> {command.short_doc or "No documentation summary."}",
|
||||
inline=False,
|
||||
)
|
||||
|
||||
def _get_flag_type(self, flag_annotation: Any) -> str:
|
||||
@staticmethod
|
||||
def _get_flag_type(flag_annotation: Any) -> str:
|
||||
"""
|
||||
Determines the type of a flag based on its annotation.
|
||||
|
||||
|
@ -111,7 +113,8 @@ class TuxHelp(commands.HelpCommand):
|
|||
case _:
|
||||
return str(flag_annotation)
|
||||
|
||||
def _format_flag_name(self, flag: commands.Flag) -> str:
|
||||
@staticmethod
|
||||
def _format_flag_name(flag: commands.Flag) -> str:
|
||||
"""
|
||||
Formats the flag name based on whether it is required.
|
||||
|
||||
|
@ -158,11 +161,11 @@ class TuxHelp(commands.HelpCommand):
|
|||
flag_str = self._format_flag_name(flag)
|
||||
|
||||
if flag.aliases:
|
||||
flag_str += f" ({', '.join(flag.aliases)})"
|
||||
flag_str += f" ({", ".join(flag.aliases)})"
|
||||
# else:
|
||||
# flag_str += f" : {flag_type}"
|
||||
|
||||
flag_str += f"\n\t{flag.description or 'No description provided.'}"
|
||||
flag_str += f"\n\t{flag.description or "No description provided."}"
|
||||
|
||||
if flag.default is not discord.utils.MISSING:
|
||||
flag_str += f"\n\tDefault: {flag.default}"
|
||||
|
@ -289,12 +292,13 @@ class TuxHelp(commands.HelpCommand):
|
|||
for command in mapping_commands:
|
||||
cmd_name_and_aliases = f"`{command.name}`"
|
||||
if command.aliases:
|
||||
cmd_name_and_aliases += f" ({', '.join(f'`{alias}`' for alias in command.aliases)})"
|
||||
cmd_name_and_aliases += f" ({", ".join(f"`{alias}`" for alias in command.aliases)})"
|
||||
command_categories[cog_group][command.name] = cmd_name_and_aliases
|
||||
|
||||
return command_categories
|
||||
|
||||
def _get_cog_groups(self) -> list[str]:
|
||||
@staticmethod
|
||||
def _get_cog_groups() -> list[str]:
|
||||
"""
|
||||
Retrieves a list of cog groups from the 'cogs' folder.
|
||||
|
||||
|
@ -349,8 +353,8 @@ class TuxHelp(commands.HelpCommand):
|
|||
|
||||
return select_options
|
||||
|
||||
@staticmethod
|
||||
def _add_navigation_and_selection(
|
||||
self,
|
||||
menu: ViewMenu,
|
||||
select_options: dict[discord.SelectOption, list[Page]],
|
||||
) -> None:
|
||||
|
@ -368,7 +372,8 @@ class TuxHelp(commands.HelpCommand):
|
|||
menu.add_select(ViewSelect(title="Command Categories", options=select_options))
|
||||
menu.add_button(ViewButton.end_session())
|
||||
|
||||
def _extract_cog_group(self, cog: commands.Cog) -> str | None:
|
||||
@staticmethod
|
||||
def _extract_cog_group(cog: commands.Cog) -> str | None:
|
||||
"""
|
||||
Extracts the cog group from a cog's string representation.
|
||||
|
||||
|
@ -424,7 +429,7 @@ class TuxHelp(commands.HelpCommand):
|
|||
|
||||
embed = self._embed_base(
|
||||
title=f"{prefix}{command.qualified_name}",
|
||||
description=f"> {command.help or 'No documentation available.'}",
|
||||
description=f"> {command.help or "No documentation available."}",
|
||||
)
|
||||
|
||||
await self._add_command_help_fields(embed, command)
|
||||
|
@ -450,12 +455,12 @@ class TuxHelp(commands.HelpCommand):
|
|||
|
||||
embed.add_field(
|
||||
name="Usage",
|
||||
value=f"`{prefix}{command.usage or 'No usage.'}`",
|
||||
value=f"`{prefix}{command.usage or "No usage."}`",
|
||||
inline=False,
|
||||
)
|
||||
embed.add_field(
|
||||
name="Aliases",
|
||||
value=(f"`{', '.join(command.aliases)}`" if command.aliases else "No aliases."),
|
||||
value=(f"`{", ".join(command.aliases)}`" if command.aliases else "No aliases."),
|
||||
inline=False,
|
||||
)
|
||||
|
||||
|
@ -471,7 +476,7 @@ class TuxHelp(commands.HelpCommand):
|
|||
|
||||
prefix = await self._get_prefix()
|
||||
|
||||
embed = self._embed_base(f"{group.name}", f"> {group.help or 'No documentation available.'}")
|
||||
embed = self._embed_base(f"{group.name}", f"> {group.help or "No documentation available."}")
|
||||
|
||||
await self._add_command_help_fields(embed, group)
|
||||
for command in group.commands:
|
||||
|
|
|
@ -37,7 +37,7 @@ def generate_usage(
|
|||
flags: dict[str, commands.Flag] = flag_converter.get_flags() if flag_converter else {}
|
||||
|
||||
for param_name, param in parameters.items():
|
||||
if param_name in ["ctx", "flags"]:
|
||||
if param_name in {"ctx", "flags"}:
|
||||
continue
|
||||
is_required = param.default == inspect.Parameter.empty
|
||||
matching_string = get_matching_string(param_name)
|
||||
|
@ -60,7 +60,7 @@ def generate_usage(
|
|||
usage += f" {flag}"
|
||||
|
||||
if optional_flags:
|
||||
usage += f" [{' | '.join(optional_flags)}]"
|
||||
usage += f" [{" | ".join(optional_flags)}]"
|
||||
|
||||
return usage
|
||||
|
||||
|
@ -309,3 +309,33 @@ class SnippetUnbanFlags(commands.FlagConverter, case_insensitive=True, delimiter
|
|||
aliases=["s", "quiet"],
|
||||
default=False,
|
||||
)
|
||||
|
||||
|
||||
class PollBanFlags(commands.FlagConverter, case_insensitive=True, delimiter=" ", prefix="-"):
|
||||
reason: str = commands.flag(
|
||||
name="reason",
|
||||
description="Reason for the poll ban.",
|
||||
aliases=["r"],
|
||||
default=MISSING,
|
||||
)
|
||||
silent: bool = commands.flag(
|
||||
name="silent",
|
||||
description="Do not send a DM to the target.",
|
||||
aliases=["s", "quiet"],
|
||||
default=False,
|
||||
)
|
||||
|
||||
|
||||
class PollUnbanFlags(commands.FlagConverter, case_insensitive=True, delimiter=" ", prefix="-"):
|
||||
reason: str = commands.flag(
|
||||
name="reason",
|
||||
description="Reason for the poll unban",
|
||||
aliases=["r"],
|
||||
default=MISSING,
|
||||
)
|
||||
silent: bool = commands.flag(
|
||||
name="silent",
|
||||
description="Do not send a DM to the target.",
|
||||
aliases=["s", "quiet"],
|
||||
default=False,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue