diff options
author | 2023-05-07 16:00:28 +0100 | |
---|---|---|
committer | 2023-05-07 16:00:28 +0100 | |
commit | 804ef7543843786a82a0a42aaf5ada818dab3f26 (patch) | |
tree | d9497896da7fb1fb042741a764df77c1c694755d | |
parent | update forgotten mentions of sir-lancebot-commands channel (diff) | |
parent | Merge pull request #949 from python-discord/hedyhli-edit-on-github (diff) |
Merge branch 'main' into update-sir-lancebot-contrib-guide
25 files changed, 759 insertions, 383 deletions
diff --git a/.coveragerc b/.coveragerc index 38926b22..b41a2140 100644 --- a/.coveragerc +++ b/.coveragerc @@ -11,6 +11,8 @@ omit = */apps.py */urls.py pydis_site/apps/api/models/bot/metricity.py + # GitHub API functions are mocked away + pydis_site/apps/content/utils.py pydis_site/wsgi.py pydis_site/settings.py pydis_site/utils/resources.py diff --git a/.github/workflows/lint-test.yaml b/.github/workflows/lint-test.yaml index 45c733b2..1c744470 100644 --- a/.github/workflows/lint-test.yaml +++ b/.github/workflows/lint-test.yaml @@ -54,7 +54,7 @@ jobs: # This step will publish the coverage reports coveralls.io and # link the report to the commit - name: Publish Coverage Report - uses: coverallsapp/[email protected] + uses: coverallsapp/[email protected] with: github-token: ${{ secrets.GITHUB_TOKEN }} file: ./coverage.lcov diff --git a/poetry.lock b/poetry.lock index 93a5d792..3a068aa9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -291,63 +291,63 @@ files = [ [[package]] name = "coverage" -version = "7.2.3" +version = "7.2.5" description = "Code coverage measurement for Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "coverage-7.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e58c0d41d336569d63d1b113bd573db8363bc4146f39444125b7f8060e4e04f5"}, - {file = "coverage-7.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:344e714bd0fe921fc72d97404ebbdbf9127bac0ca1ff66d7b79efc143cf7c0c4"}, - {file = "coverage-7.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974bc90d6f6c1e59ceb1516ab00cf1cdfbb2e555795d49fa9571d611f449bcb2"}, - {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0743b0035d4b0e32bc1df5de70fba3059662ace5b9a2a86a9f894cfe66569013"}, - {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d0391fb4cfc171ce40437f67eb050a340fdbd0f9f49d6353a387f1b7f9dd4fa"}, - {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a42e1eff0ca9a7cb7dc9ecda41dfc7cbc17cb1d02117214be0561bd1134772b"}, - {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be19931a8dcbe6ab464f3339966856996b12a00f9fe53f346ab3be872d03e257"}, - {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72fcae5bcac3333a4cf3b8f34eec99cea1187acd55af723bcbd559adfdcb5535"}, - {file = "coverage-7.2.3-cp310-cp310-win32.whl", hash = "sha256:aeae2aa38395b18106e552833f2a50c27ea0000122bde421c31d11ed7e6f9c91"}, - {file = "coverage-7.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:83957d349838a636e768251c7e9979e899a569794b44c3728eaebd11d848e58e"}, - {file = "coverage-7.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dfd393094cd82ceb9b40df4c77976015a314b267d498268a076e940fe7be6b79"}, - {file = "coverage-7.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:182eb9ac3f2b4874a1f41b78b87db20b66da6b9cdc32737fbbf4fea0c35b23fc"}, - {file = "coverage-7.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bb1e77a9a311346294621be905ea8a2c30d3ad371fc15bb72e98bfcfae532df"}, - {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca0f34363e2634deffd390a0fef1aa99168ae9ed2af01af4a1f5865e362f8623"}, - {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55416d7385774285b6e2a5feca0af9652f7f444a4fa3d29d8ab052fafef9d00d"}, - {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:06ddd9c0249a0546997fdda5a30fbcb40f23926df0a874a60a8a185bc3a87d93"}, - {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fff5aaa6becf2c6a1699ae6a39e2e6fb0672c2d42eca8eb0cafa91cf2e9bd312"}, - {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ea53151d87c52e98133eb8ac78f1206498c015849662ca8dc246255265d9c3c4"}, - {file = "coverage-7.2.3-cp311-cp311-win32.whl", hash = "sha256:8f6c930fd70d91ddee53194e93029e3ef2aabe26725aa3c2753df057e296b925"}, - {file = "coverage-7.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:fa546d66639d69aa967bf08156eb8c9d0cd6f6de84be9e8c9819f52ad499c910"}, - {file = "coverage-7.2.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2317d5ed777bf5a033e83d4f1389fd4ef045763141d8f10eb09a7035cee774c"}, - {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be9824c1c874b73b96288c6d3de793bf7f3a597770205068c6163ea1f326e8b9"}, - {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c3b2803e730dc2797a017335827e9da6da0e84c745ce0f552e66400abdfb9a1"}, - {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f69770f5ca1994cb32c38965e95f57504d3aea96b6c024624fdd5bb1aa494a1"}, - {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1127b16220f7bfb3f1049ed4a62d26d81970a723544e8252db0efde853268e21"}, - {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:aa784405f0c640940595fa0f14064d8e84aff0b0f762fa18393e2760a2cf5841"}, - {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3146b8e16fa60427e03884301bf8209221f5761ac754ee6b267642a2fd354c48"}, - {file = "coverage-7.2.3-cp37-cp37m-win32.whl", hash = "sha256:1fd78b911aea9cec3b7e1e2622c8018d51c0d2bbcf8faaf53c2497eb114911c1"}, - {file = "coverage-7.2.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f3736a5d34e091b0a611964c6262fd68ca4363df56185902528f0b75dbb9c1f"}, - {file = "coverage-7.2.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:981b4df72c93e3bc04478153df516d385317628bd9c10be699c93c26ddcca8ab"}, - {file = "coverage-7.2.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0045f8f23a5fb30b2eb3b8a83664d8dc4fb58faddf8155d7109166adb9f2040"}, - {file = "coverage-7.2.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f760073fcf8f3d6933178d67754f4f2d4e924e321f4bb0dcef0424ca0215eba1"}, - {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c86bd45d1659b1ae3d0ba1909326b03598affbc9ed71520e0ff8c31a993ad911"}, - {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:172db976ae6327ed4728e2507daf8a4de73c7cc89796483e0a9198fd2e47b462"}, - {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d2a3a6146fe9319926e1d477842ca2a63fe99af5ae690b1f5c11e6af074a6b5c"}, - {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f649dd53833b495c3ebd04d6eec58479454a1784987af8afb77540d6c1767abd"}, - {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c4ed4e9f3b123aa403ab424430b426a1992e6f4c8fd3cb56ea520446e04d152"}, - {file = "coverage-7.2.3-cp38-cp38-win32.whl", hash = "sha256:eb0edc3ce9760d2f21637766c3aa04822030e7451981ce569a1b3456b7053f22"}, - {file = "coverage-7.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:63cdeaac4ae85a179a8d6bc09b77b564c096250d759eed343a89d91bce8b6367"}, - {file = "coverage-7.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:20d1a2a76bb4eb00e4d36b9699f9b7aba93271c9c29220ad4c6a9581a0320235"}, - {file = "coverage-7.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ea748802cc0de4de92ef8244dd84ffd793bd2e7be784cd8394d557a3c751e21"}, - {file = "coverage-7.2.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21b154aba06df42e4b96fc915512ab39595105f6c483991287021ed95776d934"}, - {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd214917cabdd6f673a29d708574e9fbdb892cb77eb426d0eae3490d95ca7859"}, - {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2e58e45fe53fab81f85474e5d4d226eeab0f27b45aa062856c89389da2f0d9"}, - {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:87ecc7c9a1a9f912e306997ffee020297ccb5ea388421fe62a2a02747e4d5539"}, - {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:387065e420aed3c71b61af7e82c7b6bc1c592f7e3c7a66e9f78dd178699da4fe"}, - {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ea3f5bc91d7d457da7d48c7a732beaf79d0c8131df3ab278e6bba6297e23c6c4"}, - {file = "coverage-7.2.3-cp39-cp39-win32.whl", hash = "sha256:ae7863a1d8db6a014b6f2ff9c1582ab1aad55a6d25bac19710a8df68921b6e30"}, - {file = "coverage-7.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:3f04becd4fcda03c0160d0da9c8f0c246bc78f2f7af0feea1ec0930e7c93fa4a"}, - {file = "coverage-7.2.3-pp37.pp38.pp39-none-any.whl", hash = "sha256:965ee3e782c7892befc25575fa171b521d33798132692df428a09efacaffe8d0"}, - {file = "coverage-7.2.3.tar.gz", hash = "sha256:d298c2815fa4891edd9abe5ad6e6cb4207104c7dd9fd13aea3fdebf6f9b91259"}, + {file = "coverage-7.2.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:883123d0bbe1c136f76b56276074b0c79b5817dd4238097ffa64ac67257f4b6c"}, + {file = "coverage-7.2.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d2fbc2a127e857d2f8898aaabcc34c37771bf78a4d5e17d3e1f5c30cd0cbc62a"}, + {file = "coverage-7.2.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f3671662dc4b422b15776cdca89c041a6349b4864a43aa2350b6b0b03bbcc7f"}, + {file = "coverage-7.2.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780551e47d62095e088f251f5db428473c26db7829884323e56d9c0c3118791a"}, + {file = "coverage-7.2.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:066b44897c493e0dcbc9e6a6d9f8bbb6607ef82367cf6810d387c09f0cd4fe9a"}, + {file = "coverage-7.2.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9a4ee55174b04f6af539218f9f8083140f61a46eabcaa4234f3c2a452c4ed11"}, + {file = "coverage-7.2.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:706ec567267c96717ab9363904d846ec009a48d5f832140b6ad08aad3791b1f5"}, + {file = "coverage-7.2.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ae453f655640157d76209f42c62c64c4d4f2c7f97256d3567e3b439bd5c9b06c"}, + {file = "coverage-7.2.5-cp310-cp310-win32.whl", hash = "sha256:f81c9b4bd8aa747d417407a7f6f0b1469a43b36a85748145e144ac4e8d303cb5"}, + {file = "coverage-7.2.5-cp310-cp310-win_amd64.whl", hash = "sha256:dc945064a8783b86fcce9a0a705abd7db2117d95e340df8a4333f00be5efb64c"}, + {file = "coverage-7.2.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:40cc0f91c6cde033da493227797be2826cbf8f388eaa36a0271a97a332bfd7ce"}, + {file = "coverage-7.2.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a66e055254a26c82aead7ff420d9fa8dc2da10c82679ea850d8feebf11074d88"}, + {file = "coverage-7.2.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c10fbc8a64aa0f3ed136b0b086b6b577bc64d67d5581acd7cc129af52654384e"}, + {file = "coverage-7.2.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a22cbb5ede6fade0482111fa7f01115ff04039795d7092ed0db43522431b4f2"}, + {file = "coverage-7.2.5-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:292300f76440651529b8ceec283a9370532f4ecba9ad67d120617021bb5ef139"}, + {file = "coverage-7.2.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7ff8f3fb38233035028dbc93715551d81eadc110199e14bbbfa01c5c4a43f8d8"}, + {file = "coverage-7.2.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a08c7401d0b24e8c2982f4e307124b671c6736d40d1c39e09d7a8687bddf83ed"}, + {file = "coverage-7.2.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef9659d1cda9ce9ac9585c045aaa1e59223b143f2407db0eaee0b61a4f266fb6"}, + {file = "coverage-7.2.5-cp311-cp311-win32.whl", hash = "sha256:30dcaf05adfa69c2a7b9f7dfd9f60bc8e36b282d7ed25c308ef9e114de7fc23b"}, + {file = "coverage-7.2.5-cp311-cp311-win_amd64.whl", hash = "sha256:97072cc90f1009386c8a5b7de9d4fc1a9f91ba5ef2146c55c1f005e7b5c5e068"}, + {file = "coverage-7.2.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bebea5f5ed41f618797ce3ffb4606c64a5de92e9c3f26d26c2e0aae292f015c1"}, + {file = "coverage-7.2.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828189fcdda99aae0d6bf718ea766b2e715eabc1868670a0a07bf8404bf58c33"}, + {file = "coverage-7.2.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e8a95f243d01ba572341c52f89f3acb98a3b6d1d5d830efba86033dd3687ade"}, + {file = "coverage-7.2.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8834e5f17d89e05697c3c043d3e58a8b19682bf365048837383abfe39adaed5"}, + {file = "coverage-7.2.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d1f25ee9de21a39b3a8516f2c5feb8de248f17da7eead089c2e04aa097936b47"}, + {file = "coverage-7.2.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1637253b11a18f453e34013c665d8bf15904c9e3c44fbda34c643fbdc9d452cd"}, + {file = "coverage-7.2.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8e575a59315a91ccd00c7757127f6b2488c2f914096077c745c2f1ba5b8c0969"}, + {file = "coverage-7.2.5-cp37-cp37m-win32.whl", hash = "sha256:509ecd8334c380000d259dc66feb191dd0a93b21f2453faa75f7f9cdcefc0718"}, + {file = "coverage-7.2.5-cp37-cp37m-win_amd64.whl", hash = "sha256:12580845917b1e59f8a1c2ffa6af6d0908cb39220f3019e36c110c943dc875b0"}, + {file = "coverage-7.2.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b5016e331b75310610c2cf955d9f58a9749943ed5f7b8cfc0bb89c6134ab0a84"}, + {file = "coverage-7.2.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:373ea34dca98f2fdb3e5cb33d83b6d801007a8074f992b80311fc589d3e6b790"}, + {file = "coverage-7.2.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a063aad9f7b4c9f9da7b2550eae0a582ffc7623dca1c925e50c3fbde7a579771"}, + {file = "coverage-7.2.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38c0a497a000d50491055805313ed83ddba069353d102ece8aef5d11b5faf045"}, + {file = "coverage-7.2.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b3b05e22a77bb0ae1a3125126a4e08535961c946b62f30985535ed40e26614"}, + {file = "coverage-7.2.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0342a28617e63ad15d96dca0f7ae9479a37b7d8a295f749c14f3436ea59fdcb3"}, + {file = "coverage-7.2.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf97ed82ca986e5c637ea286ba2793c85325b30f869bf64d3009ccc1a31ae3fd"}, + {file = "coverage-7.2.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c2c41c1b1866b670573657d584de413df701f482574bad7e28214a2362cb1fd1"}, + {file = "coverage-7.2.5-cp38-cp38-win32.whl", hash = "sha256:10b15394c13544fce02382360cab54e51a9e0fd1bd61ae9ce012c0d1e103c813"}, + {file = "coverage-7.2.5-cp38-cp38-win_amd64.whl", hash = "sha256:a0b273fe6dc655b110e8dc89b8ec7f1a778d78c9fd9b4bda7c384c8906072212"}, + {file = "coverage-7.2.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c587f52c81211d4530fa6857884d37f514bcf9453bdeee0ff93eaaf906a5c1b"}, + {file = "coverage-7.2.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4436cc9ba5414c2c998eaedee5343f49c02ca93b21769c5fdfa4f9d799e84200"}, + {file = "coverage-7.2.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6599bf92f33ab041e36e06d25890afbdf12078aacfe1f1d08c713906e49a3fe5"}, + {file = "coverage-7.2.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:857abe2fa6a4973f8663e039ead8d22215d31db613ace76e4a98f52ec919068e"}, + {file = "coverage-7.2.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f5cab2d7f0c12f8187a376cc6582c477d2df91d63f75341307fcdcb5d60303"}, + {file = "coverage-7.2.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aa387bd7489f3e1787ff82068b295bcaafbf6f79c3dad3cbc82ef88ce3f48ad3"}, + {file = "coverage-7.2.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:156192e5fd3dbbcb11cd777cc469cf010a294f4c736a2b2c891c77618cb1379a"}, + {file = "coverage-7.2.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bd3b4b8175c1db502adf209d06136c000df4d245105c8839e9d0be71c94aefe1"}, + {file = "coverage-7.2.5-cp39-cp39-win32.whl", hash = "sha256:ddc5a54edb653e9e215f75de377354e2455376f416c4378e1d43b08ec50acc31"}, + {file = "coverage-7.2.5-cp39-cp39-win_amd64.whl", hash = "sha256:338aa9d9883aaaad53695cb14ccdeb36d4060485bb9388446330bef9c361c252"}, + {file = "coverage-7.2.5-pp37.pp38.pp39-none-any.whl", hash = "sha256:8877d9b437b35a85c18e3c6499b23674684bf690f5d96c1006a1ef61f9fdf0f3"}, + {file = "coverage-7.2.5.tar.gz", hash = "sha256:f99ef080288f09ffc687423b8d60978cf3a465d3f404a18d1a05474bd8575a47"}, ] [package.extras] @@ -413,14 +413,14 @@ files = [ [[package]] name = "django" -version = "4.2" +version = "4.2.1" description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "Django-4.2-py3-none-any.whl", hash = "sha256:ad33ed68db9398f5dfb33282704925bce044bef4261cd4fb59e4e7f9ae505a78"}, - {file = "Django-4.2.tar.gz", hash = "sha256:c36e2ab12824e2ac36afa8b2515a70c53c7742f0d6eaefa7311ec379558db997"}, + {file = "Django-4.2.1-py3-none-any.whl", hash = "sha256:066b6debb5ac335458d2a713ed995570536c8b59a580005acb0732378d5eb1ee"}, + {file = "Django-4.2.1.tar.gz", hash = "sha256:7efa6b1f781a6119a10ac94b4794ded90db8accbe7802281cd26f8664ffed59c"}, ] [package.dependencies] @@ -471,14 +471,14 @@ testing = ["coverage[toml] (>=5.0a4)", "pytest (>=4.6.11)"] [[package]] name = "django-filter" -version = "23.1" +version = "23.2" description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "django-filter-23.1.tar.gz", hash = "sha256:dee5dcf2cea4d7f767e271b6d01f767fce7500676d5e5dc58dac8154000b87df"}, - {file = "django_filter-23.1-py3-none-any.whl", hash = "sha256:e3c52ad83c32fb5882125105efb5fea2a1d6a85e7dc64b04ef52edbf14451b6c"}, + {file = "django-filter-23.2.tar.gz", hash = "sha256:2fe15f78108475eda525692813205fa6f9e8c1caf1ae65daa5862d403c6dbf00"}, + {file = "django_filter-23.2-py3-none-any.whl", hash = "sha256:d12d8e0fc6d3eb26641e553e5d53b191eb8cec611427d4bdce0becb1f7c172b5"}, ] [package.dependencies] @@ -944,14 +944,14 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytes [[package]] name = "pre-commit" -version = "3.2.2" +version = "3.3.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "pre_commit-3.2.2-py2.py3-none-any.whl", hash = "sha256:0b4210aea813fe81144e87c5a291f09ea66f199f367fa1df41b55e1d26e1e2b4"}, - {file = "pre_commit-3.2.2.tar.gz", hash = "sha256:5b808fcbda4afbccf6d6633a56663fed35b6c2bc08096fd3d47ce197ac351d9d"}, + {file = "pre_commit-3.3.0-py2.py3-none-any.whl", hash = "sha256:7577a012399334d9f001873b5553f9fabc1ccc5b3e2b29e0793f84ce18e9d042"}, + {file = "pre_commit-3.3.0.tar.gz", hash = "sha256:06acda43a7b6b63fdcc29aa90bf1228cf4d4029a4e4d70971347a9d2593c94d4"}, ] [package.dependencies] @@ -1286,14 +1286,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "sentry-sdk" -version = "1.19.1" +version = "1.21.1" description = "Python client for Sentry (https://sentry.io)" category = "main" optional = false python-versions = "*" files = [ - {file = "sentry-sdk-1.19.1.tar.gz", hash = "sha256:7ae78bd921981a5010ab540d6bdf3b793659a4db8cccf7f16180702d48a80d84"}, - {file = "sentry_sdk-1.19.1-py2.py3-none-any.whl", hash = "sha256:885a11c69df23e53eb281d003b9ff15a5bdfa43d8a2a53589be52104a1b4582f"}, + {file = "sentry-sdk-1.21.1.tar.gz", hash = "sha256:99c15556a23621be9f18c2955f7ce63321713bf1c0ad396b27b61399bac5f458"}, + {file = "sentry_sdk-1.21.1-py2.py3-none-any.whl", hash = "sha256:092888f3abf7a2ea78f0bfcefc3e0465caee2b6f0efb26f538ccc60f95dca179"}, ] [package.dependencies] @@ -1381,16 +1381,21 @@ files = [ [[package]] name = "sqlparse" -version = "0.4.3" +version = "0.4.4" description = "A non-validating SQL parser." category = "main" optional = false python-versions = ">=3.5" files = [ - {file = "sqlparse-0.4.3-py3-none-any.whl", hash = "sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34"}, - {file = "sqlparse-0.4.3.tar.gz", hash = "sha256:69ca804846bb114d2ec380e4360a8a340db83f0ccf3afceeb1404df028f57268"}, + {file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"}, + {file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"}, ] +[package.extras] +dev = ["build", "flake8"] +doc = ["sphinx"] +test = ["pytest", "pytest-cov"] + [[package]] name = "stevedore" version = "5.0.0" @@ -1504,4 +1509,4 @@ brotli = ["Brotli"] [metadata] lock-version = "2.0" python-versions = "3.10.*" -content-hash = "1acc2e05d9a07531fb787020c3810fef95d913741e576b7b70057c6c66ff83d4" +content-hash = "3b8b0374a795479fda682ff1e3cecb439719cff06b079b15c4bd152b48a21482" diff --git a/pydis_site/apps/api/tests/test_rules.py b/pydis_site/apps/api/tests/test_rules.py index d08c5fae..3ee2d4e0 100644 --- a/pydis_site/apps/api/tests/test_rules.py +++ b/pydis_site/apps/api/tests/test_rules.py @@ -1,3 +1,7 @@ +import itertools +import re +from pathlib import Path + from django.urls import reverse from .base import AuthenticatedAPITestCase @@ -33,3 +37,37 @@ class RuleAPITests(AuthenticatedAPITestCase): url = reverse('api:rules') response = self.client.get(url + '?link_format=unknown') self.assertEqual(response.status_code, 400) + + +class RuleCorrectnessTests(AuthenticatedAPITestCase): + """Verifies that the rules from the API and by the static rules in the content app match.""" + + @classmethod + def setUpTestData(cls): + cls.markdown_rule_re = re.compile(r'^> \d+\. (.*)$') + + def test_rules_in_markdown_file_roughly_equal_api_rules(self) -> None: + url = reverse('api:rules') + api_response = self.client.get(url + '?link_format=md') + api_rules = tuple(rule for (rule, _tags) in api_response.json()) + + markdown_rules_path = ( + Path(__file__).parent.parent.parent / 'content' / 'resources' / 'rules.md' + ) + + markdown_rules = [] + for line in markdown_rules_path.read_text().splitlines(): + matches = self.markdown_rule_re.match(line) + if matches is not None: + markdown_rules.append(matches.group(1)) + + zipper = itertools.zip_longest(api_rules, markdown_rules) + for idx, (api_rule, markdown_rule) in enumerate(zipper): + with self.subTest(f"Rule {idx}"): + self.assertIsNotNone( + markdown_rule, f"The API has more rules than {markdown_rules_path}" + ) + self.assertIsNotNone( + api_rule, f"{markdown_rules_path} has more rules than the API endpoint" + ) + self.assertEqual(markdown_rule, api_rule) diff --git a/pydis_site/apps/api/views.py b/pydis_site/apps/api/views.py index 20431a61..b1b7dc0f 100644 --- a/pydis_site/apps/api/views.py +++ b/pydis_site/apps/api/views.py @@ -120,7 +120,7 @@ class RulesView(APIView): link_format ) discord_tos = self._format_link( - 'Terms Of Service', + 'Terms of Service', 'https://discordapp.com/terms', link_format ) @@ -149,9 +149,9 @@ class RulesView(APIView): ["english", "language"] ), ( - "Do not provide or request help on projects that may break laws, " - "breach terms of services, or are malicious or inappropriate.", - ["infraction", "tos", "breach", "malicious", "inappropriate"] + "Do not provide or request help on projects that may violate terms of service, " + "or that may be deemed inappropriate, malicious, or illegal.", + ["infraction", "tos", "breach", "malicious", "inappropriate", "illegal"] ), ( "Do not post unapproved advertising.", diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md new file mode 100644 index 00000000..b031a668 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md @@ -0,0 +1,192 @@ +--- +title: Extended options for configuring Bot +description: A guide that lists all extended/optional options to configure the bot further. +icon: fab fa-github +toc: 3 +--- + +## Manual constants configuration + +Reading this means that you're ready for a bit of manual labour. +If for some reason you've missed the automatic server setup section, you can read about it in the bot contributing guide [here](../bot.md#envserver) + +To configure the bot manually, you will **only** need to set inside the `.env.server` file the values for the channels, roles, categories, etc. +that are used by the component you are developing. + +For example, if we're testing a feature that only needs the `announcements` channel: + +`constants.py` + +```py + +class EnvConfig: + # Defines from where & how Pydantic will be looking for env variables + ... + +class _Channels(EnvConfig): + + EnvConfig.Config.env_prefix = "channels_" + + announcements = 1079790565794779156 + changelog = 1077877318564991006 + +# Instantiate the class & load the configuration +Channels = _Channels() +``` + +`.env.server` file: + +```text +# .env.server + +channels_announcements=1077875228002234398 +``` + +When you launch your bot, `pydantic` will load up the server constants from the `.env.server` file if they exist. + +Each constants class will define its own prefix, which will make `pydantic` look for variables that will look like `{{env_prefix}}{{attribute_name}}` in the environment files + +In our example, this will imply that pydantic will look for both `channels_announcements` and `channels_changelog` in the `.env.server` file. + +As you can see here, only `channels_announcements` has been defined in the `.env.server` file since it's the only one needed, which will tell `pydantic` +to use the value **1077875228002234398** for the `announcements` attribute instead of the default **1079790565794779156**, and use the default value for the `changelog` attribute + +```python +>>> Channels.announcements +1077875228002234398 +>>> Channels.changelong +1077877318564991006 +``` + +See [here](../obtaining-discord-ids) for help with obtaining Discord IDs. + +If you wish to set all values in your `env.server` for your testing server, you need to set **all** the ones prefixed with: + +* `guild_` +* `categories_` +* `channels_` +* `roles_` +* `webhooks_` +* `emojis_` + +## Working with the help forum + +**Note**: This is only required when you're not configuring the bot [automatically](#automatic-configuration) + +If you will be working on a feature that includes the python help forum, you will need to use `Forum Channels`. + +Forum channels cannot be included in a template, which is why this needs to be done by hand for the time being. + +To activate forum channels, your Discord server needs to have the community feature. +If that's not the case already, here are the steps required to do it: + +1. Go to server settings +2. Scroll down to the `COMMUNITY` section and click on `Enable Community` +3. Click on `Get Started` and fill out the necessary info + +Once the previous steps are done, all that is left is to: + +1. Create a new channel +2. Choose the `Forum` type +3. [Copy its ID](../obtaining-discord-ids#channel-id) +4. Add the following line to the `.env.server` file: `channels_python_help={newly_created_forum_channel_id}` + +--- + +We understand this is tedious which is why we **heavily recommend** using the [automatic configuration setup](../bot.md#automatic-configuration) + +--- + +## Reloading parts of the bot +If you make changes to an extension, you might not need to restart the entire bot for the changes to take effect. The command `!ext reload <extension_name>` re-imports the files associated with the extension. +Invoke `!ext list` for a full list of the available extensions. In this bot in particular, cogs are defined inside extensions. + +Note that if you changed code that is not associated with a particular extension, such as utilities, converters, and constants, you will need to restart the bot. + +## Adding new statistics + +Details on how to add new statistics can be found on the [statistic infrastructure page](https://blog.pythondiscord.com/statistics-infrastructure). +We are always open to more statistics so add as many as you can! + +--- + +## With the Bot Running Locally +The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker. + +* Append the following line to your `.env` file: `API_KEYS_SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. +* In your `.env.server` file, set `urls_site_api="http://localhost:8000/api"`. If you wish to keep using `http://web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. +* To work with snekbox, set `urls_snekbox_eval_api="http://localhost:8060/eval"` and `urls_snekbox_311_eval_api="http://localhost:8065/eval"` + + +You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: + +* `docker compose up web` to start the site container. This is required. +* `docker compose up snekbox` to start the snekbox container. You only need this if you're planning on working on the snekbox cog. +* `docker compose up snekbox-311` to start the snekbox 3.11 container. You only need this if you're planning on working on the snekbox cog. +* `docker compose up redis` to start the Redis container. You only need this if you're not using fakeredis. For more info refer to [Working with Redis](#optional-working-with-redis). + +You can start several services together: `docker compose up web snekbox redis`. + +### Setting Up a Development Environment + +With at least the site running in Docker already (see the previous section on how to start services separately), you can now start the bot locally through the command line, or through your preferred IDE. +<div class="card"> + <button type="button" class="card-header collapsible"> + <span class="card-header-title subtitle is-6 my-2 ml-2">Ways to run code</span> + <span class="card-header-icon"> + <i class="fas fa-fw fa-angle-down title is-5" aria-hidden="true"></i> + </span> + </button> + <div class="collapsible-content collapsed"> + <div class="card-content"> + Notice that the bot is started as a module. There are several ways to do so: + <ul> + <li>Through the command line, inside the bot directory, with either <code>poetry run task start</code>, or directly <code>python -m bot</code>.</li> + <li>If using PyCharm, enter <code>Edit Configurations</code> and set everything according to this image: <img src="/static/images/content/contributing/pycharm_run_module.png"></li> + <li>If using Visual Studio Code, set the interpreter to the poetry environment you created. In <code>launch.json</code> create a new Python configuration, and set the name of the program to be run to <code>bot</code>. VSC will correctly run it as a module.</li> + </ul> + </div> + </div> +</div> +<br> + +### With More Things Running Locally +You can run additional services on the host, but this guide won't go over how to install and start them in this way. +If possible, prefer to start the services through Docker to replicate the production environment as much as possible. + +The site, however, is a mandatory service for the bot. +Refer to the [previous section](#with-the-bot-running-locally) and the [site contributing guide](../site) to learn how to start it on the host, in which case you will need to change `urls.site` in `.env.server` to wherever the site is being hosted. + +--- + +### Starting Redis Using Other Methods +You can run your own instance of Redis, but in that case you will need to correctly set `redis_host` and `redis_port` in your `.env.server` file and the `REDIS_PASSWORD` in the `.env` file. +**Note**: The previously mentioned variables **SHOULD NOT** be overriden or changed in `constants.py` + +--- + +## Working with Metricity +[Metricity](https://github.com/python-discord/metricity) is our home-grown bot for collecting metrics on activity within the server, such as what users are present, and IDs of the messages they've sent. +Certain features in the Python bot rely on querying the Metricity database for information such as the number of messages a user has sent, most notably the voice verification system. + +If you wish to work on a feature that relies on Metricity, for your convenience we've made the process of using it relatively painless with Docker: Enter the `.env` file you've written for the Python bot, and append the line `USE_METRICITY=true`. +Note that if you don't need Metricity, there's no reason to have it enabled as it is just unnecessary overhead. + +To make the Metricity bot work with your test server, you will need to override its configurations similarly to the Python bot. +You can see the various configurations in [the Metricity repo](https://github.com/python-discord/metricity), but the bare minimum is the guild ID setting. +In your local version of the Python bot repo, create a file called `metricity-config.toml` and insert the following lines: +```yaml +[bot] +guild_id = replace_with_your_guild_id +``` +To properly replicate production behavior, set the `staff_role_id`, `staff_categories`, and `ignore_categories` fields as well. + +Now, `docker compose up` will also start Metricity. + +If you want to run the bot locally, you can run `docker compose up metricity` instead. + +--- + +## Working with bot moderation logs +To be able to view moderation-related logs published by the bot to site, you will need to set `urls_site_logs_view=http://localhost:8000/staff/bot/logs` in your `.env.server`. +This will work in both Docker and locally. diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 769ea838..6639d92d 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -10,6 +10,35 @@ You should have already forked the repository and cloned it to your local machin This page will focus on the quickest steps one can take, with mentions of alternatives afterwards. --- +## Setting up the project + +### Setup Project Dependencies +Below are the dependencies you **must** have installed to get started with the bot. + +1. Make sure you have [Python 3.11](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. +1. [Install Poetry](https://github.com/python-poetry/poetry#installation). +1. [Install the project's dependencies](../installing-project-dependencies). +1. Docker. + +<div class="card"> + <button type="button" class="card-header collapsible"> + <span class="card-header-title subtitle is-6 my-2 ml-2">Getting started with Docker</span> + <span class="card-header-icon"> + <i class="fas fa-fw fa-angle-down title is-5" aria-hidden="true"></i> + </span> + </button> + <div class="collapsible-content collapsed"> + <div class="card-content"> + The requirements for Docker are: + <ul> + <li><a href="https://docs.docker.com/install">Docker CE</a></li> + <li>Docker Compose. If you're using macOS and Windows, this already comes bundled with the previous installation. Otherwise, you can download it either from the <a href="https://docs.docker.com/compose/install">website</a>, or by running <code>pip install docker-compose</code>.</li> + </ul> + <p class="notification is-warning">If you get any Docker related errors, reference the <a href="../docker#possible-issues">Possible Issue</a> section of the Docker page.</p> + </div> + </div> +</div> +<br> ### Set Up a Test Server The Python bot is tightly coupled with the Python Discord server, so to have a functional version of the bot you need a server with channels it can use. @@ -37,137 +66,45 @@ If your bot fails to start with a `PrivilegedIntentsRequired` exception, this in --- ### Configure the Bot -You now have both the bot's code and a server to run it on. It's time for you to connect the two by changing the bot's configurations. -This can be done either automatically or manually, and we'll be detailing the steps for both. - -One thing to know is that the bot relies on precisely **two** configuration files to work. +You now have both the bot's code and a server to run it on. It's time for you to connect the two by setting the bot's configuration. +Both `.env` and `.env.server` files we talk about below are ignored by git, so they do not get accidentally commit to the repository. #### .env -This file will mostly contain sensitive information such as your `BOT_TOKEN` and your `REDIS_PASSWORD`. -It will also contain configurations related to external services the bot might use such as `USE_METRICITY`, which are unrelated to your server, with the only exception being `GUILD_ID`. +This file will contain sensitive information such as your bot's token, do not share it with anybody! -This file will **always** need to have `BOT_TOKEN` and `GUILD_ID` values set: +To start, create a `.env` file in the project root with the below content. ```text BOT_TOKEN=YourDiscordBotTokenHere GUILD_ID=YourDiscordTestServerIdHere +BOT_PREFIX=YourDesiredPrefixHere ``` See [here](../creating-bot-account) for help with obtaining the bot token, and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's ID. +Other values will be added to your `.env` over time as you need to interact with other parts of the bot, but those are not needed for a basic setup. For a full list of support values see the ENV file option [appendix](#appendix-full-env-file-options) #### .env.server -All server configuration values are saved in this file, which needs to be at the root directory of the cloned code. -This file contains the various configurations we use to make the bot run on the Python Discord server, such as channel and role IDs, and the emojis it works with. -It also contains configurations such as how long it takes for a help channel to time out, and how many messages a user needs to voice-verify. - -This file will be created for you automatically if you decide to go with [automatic configuration](#automatic-configuration), -otherwise a lot of it has to be done by hand which will be detailed in the [manual configuration](#manual-configuration) section. - - -**Notes**: - -* Both `.env` and `.env.server` are and should remain ignored by git, otherwise you risk pushing sensitive information. -* Skip the following step if you would like to configure the bot manually, but that will require more work. - -#### Automatic configuration -To make setup much easier, the script in `botstrap.py` bootstraps the configuration for you and helps you get started immediately, -without having to spend much time copying IDs from your server into your configuration file. - -**Note**: The script will also work on existing servers as long as the channel names are the same as the one in Python Discord. +All server related configuration values are saved in this file, which also needs to be at the root directory of the project. -##### 1. Script setup -The bootstrapping script is a Python program so you will need a compatible Python version and the necessary dependencies installed, -which are all detailed here: +We provide a script to automatically generate a server config. +**Note**: The script **only** works with servers created with the template mentioned above. -1. Make sure you have [Python 3.11](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. -2. [Install Poetry](https://github.com/python-poetry/poetry#installation). -3. [Install the dependencies](../installing-project-dependencies). - -##### 2. Running the script +If you want to setup the bot from an existing guild read out [manual configuration guide](../bot-extended-configuration-options#manual-constants-configuration). This is far more complicated and time consuming. -Once the script setup phase is complete, all that is left is to run it. -To do this, you'll simply need to run the `configure` poetry task: +Running the below command will use the `BOT_TOKEN` and `GUILD_ID` from the `.env` file you created above to download all of the relevant IDs from the template guild into your `.env.server` +**Note**: This script will overwrite the `.env.server` file. We suggest you put any configuration not generated by this script in to `.env` instead ```shell $ poetry run task configure ``` -Once the script has finished running, you'll notice the creation of a new file called [`.env.server`](#envserver) at your project's root directory. +Once the script has finished running, you'll notice the creation of a new file called `.env.server` at your project's root directory. This file will contain the extracted IDs from your server which are necessary for your bot to run. **Congratulations**, you have finished the configuration and can now [run your bot](#run-it). -#### Manual configuration - -**Note**: Skip this part if you used the automatic configuration. - -Reading this means that you're ready for a bit of manual labour. -If for some reason you've missed the automatic server setup section, you can read about it [here](#automatic-configuration) - -To configure the bot manually, you will **only** need to set inside the `.env.server` file the values for the channels, roles, categories, etc. -that are used by the component you are developing. - -For example, if we're testing a feature that only needs the `announcements` channel: - -`constants.py` - -```py - -class EnvConfig: - # Defines from where & how Pydantic will be looking for env variables - ... - -class _Channels(EnvConfig): - - EnvConfig.Config.env_prefix = "channels_" - - announcements = 1079790565794779156 - changelog = 1077877318564991006 - -# Instantiate the class & load the configuration -Channels = _Channels() -``` - -`.env.server` file: - -```text -# .env.server - -channels_announcements=1077875228002234398 -``` - -When you launch your bot, `pydantic` will load up the server constants from the `.env.server` file if they exist. - -Each constants class will define its own prefix, which will make `pydantic` look for variables that will look like `{{env_prefix}}{{attribute_name}}` in the environment files - -In our example, this will imply that pydantic will look for both `channels_announcements` and `channels_changelog` in the `.env.server` file. - -As you can see here, only `channels_announcements` has been defined in the `.env.server` file since it's the only one needed, which will tell `pydantic` -to use the value **1077875228002234398** for the `announcements` attribute instead of the default **1079790565794779156**, and use the default value for the `changelog` attribute - -```python ->>> Channels.announcements -1077875228002234398 ->>> Channels.changelong -1077877318564991006 -``` - -See [here](../obtaining-discord-ids) for help with obtaining Discord IDs. - -If you wish to set all values in your `env.server` for your testing server, you need to set **all** the ones prefixed with: - -* `guild_` -* `categories_` -* `channels_` -* `roles_` -* `webhooks_` -* `emojis_` - - -We understand this is tedious which is why we **heavily recommend** using the [automatic configuration setup](#automatic-configuration) - <div class="card"> <button type="button" class="card-header collapsible"> <span class="card-header-title subtitle is-6 my-2 ml-2">Why do you need a separate config file?</span> @@ -186,216 +123,65 @@ We understand this is tedious which is why we **heavily recommend** using the [a <br> - ### Run it! #### With Docker You are now almost ready to run the Python bot. The simplest way to do so is with Docker. -<div class="card"> - <button type="button" class="card-header collapsible"> - <span class="card-header-title subtitle is-6 my-2 ml-2">Getting started with Docker</span> - <span class="card-header-icon"> - <i class="fas fa-fw fa-angle-down title is-5" aria-hidden="true"></i> - </span> - </button> - <div class="collapsible-content collapsed"> - <div class="card-content"> - The requirements for Docker are: - <ul> - <li><a href="https://docs.docker.com/install">Docker CE</a></li> - <li>Docker Compose. If you're using macOS and Windows, this already comes bundled with the previous installation. Otherwise, you can download it either from the <a href="https://docs.docker.com/compose/install">website</a>, or by running <code>pip install docker-compose</code>.</li> - </ul> - <p class="notification is-warning">If you get any Docker related errors, reference the <a href="../docker#possible-issues">Possible Issue</a> section of the Docker page.</p> - </div> - </div> -</div> -<br> - -In your `.env.server` file: - -* If you wish to work with snekbox, set the following: - * `urls_snekbox_eval_api` to `"http://snekbox:8060/eval"` - * `urls_snekbox_311_eval_api` to `"http://snekbox-311:8060/eval"`. - -* At this stage, set `redis_use_fakeredis` to `true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). - - -Assuming you have Docker installed **and running**, enter the cloned repo in the command line and type `docker compose up`. - -If working with snekbox you can run `docker compose --profile 3.10 up` to also start up a 3.10 snekbox container, in addition to the default 3.11 container! - -After pulling the images and building the containers, your bot will start. Enter your server and type `!help` (or whatever prefix you [chose](#optional--changing-your-command-prefix) instead of `!`). - -Your bot is now running, but this method makes debugging with an IDE a fairly involved process. For additional running methods, continue reading the following sections. -#### With the Bot Running Locally -The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker. +With all of the above setup, you can run The projec with `docker compose up`. This will start the bot an all required services! Enter your server and type `!help` (or whatever prefix you chose instead of `!`) to see the bot in action! -* Append the following line to your `.env` file: `API_KEYS_SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. -* In your `.env.server` file, set `urls_site_api="http://localhost:8000/api"`. If you wish to keep using `http://web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. -* To work with snekbox, set `urls_snekbox_eval_api="http://localhost:8060/eval"` and `urls_snekbox_311_eval_api="http://localhost:8065/eval"` +Some other useful docker commands are as follows: +1. `docker compose pull` this pulls updates for all non-bot services, such as psotgres, redis and our [site](../site) project! +1. `docker compose build` this rebuilds the bot's docker image, this is only needed if you need to make changes to the bot's dependencies, or the Dockerfile itself. +1. `docker compose --profile 3.10 up` this starts a 3.10 snekbox container, in addition to the default 3.11 container! -You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: - -* `docker compose up web` to start the site container. This is required. -* `docker compose up snekbox` to start the snekbox container. You only need this if you're planning on working on the snekbox cog. -* `docker compose up snekbox-311` to start the snekbox 3.11 container. You only need this if you're planning on working on the snekbox cog. -* `docker compose up redis` to start the Redis container. You only need this if you're not using fakeredis. For more info refer to [Working with Redis](#optional-working-with-redis). - -You can start several services together: `docker compose up web snekbox redis`. - -##### Setting Up a Development Environment -The bot's code is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed: - -1. Make sure you have [Python 3.11](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. -2. [Install Poetry](https://github.com/python-poetry/poetry#installation). -3. [Install the dependencies](../installing-project-dependencies). - -With at least the site running in Docker already (see the previous section on how to start services separately), you can now start the bot locally through the command line, or through your preferred IDE. -<div class="card"> - <button type="button" class="card-header collapsible"> - <span class="card-header-title subtitle is-6 my-2 ml-2">Ways to run code</span> - <span class="card-header-icon"> - <i class="fas fa-fw fa-angle-down title is-5" aria-hidden="true"></i> - </span> - </button> - <div class="collapsible-content collapsed"> - <div class="card-content"> - Notice that the bot is started as a module. There are several ways to do so: - <ul> - <li>Through the command line, inside the bot directory, with either <code>poetry run task start</code>, or directly <code>python -m bot</code>.</li> - <li>If using PyCharm, enter <code>Edit Configurations</code> and set everything according to this image: <img src="/static/images/content/contributing/pycharm_run_module.png"></li> - <li>If using Visual Studio Code, set the interpreter to the poetry environment you created. In <code>launch.json</code> create a new Python configuration, and set the name of the program to be run to <code>bot</code>. VSC will correctly run it as a module.</li> - </ul> - </div> - </div> -</div> -<br> - -#### With More Things Running Locally -You can run additional services on the host, but this guide won't go over how to install and start them in this way. -If possible, prefer to start the services through Docker to replicate the production environment as much as possible. +Your bot is now running, all inside Docker. -The site, however, is a mandatory service for the bot. -Refer to the [previous section](#with-the-bot-running-locally) and the [site contributing guide](../site) to learn how to start it on the host, in which case you will need to change `urls.site` in `.env.server` to wherever the site is being hosted. +**Note**: If you want to read about how to make debugging with an IDE a easier, or for additional running methods, check out our [extended configuration guide](../bot-extended-configuration-options). --- -### Development Tips + +## Development Tips Now that you have everything setup, it is finally time to make changes to the bot! -#### Working with Git +### Working with Git Version control of our projects is done using Git and Github. It can be intimidating at first, so feel free to ask for any help in the server. [**Click here to see the basic Git workflow when contributing to one of our projects.**](../working-with-git/) -#### Running tests +### Running tests [This section](https://github.com/python-discord/bot/blob/main/tests/README.md#tools) of the README in the `tests` repository will explain how to run tests. The whole document explains how unittesting works, and how it fits in the context of our project. Make sure to run tests *before* pushing code. -Even if you run the bot through Docker, you might want to [setup a development environment](#setting-up-a-development-environment) in order to run the tests locally. +Even if you run the bot through Docker, you might want to [setup a development environment](../bot-extended-configuration-options#setting-up-a-development-environment) in order to run the tests locally. -#### Lint before you push +### Lint before you push As mentioned in the [contributing guidelines](../contributing-guidelines), you should make sure your code passes linting for each commit you make. For ease of development, you can install the pre-commit hook with `poetry run task precommit`, which will check your code every time you try to commit it. -For that purpose, even if you run the bot through Docker, you might want to [setup a development environment](#setting-up-a-development-environment), as otherwise the hook installation will fail. - -#### Reloading parts of the bot -If you make changes to an extension, you might not need to restart the entire bot for the changes to take effect. The command `!ext reload <extension_name>` re-imports the files associated with the extension. -Invoke `!ext list` for a full list of the available extensions. In this bot in particular, cogs are defined inside extensions. - -Note that if you changed code that is not associated with a particular extension, such as utilities, converters, and constants, you will need to restart the bot. - -#### Adding new statistics - -Details on how to add new statistics can be found on the [statistic infrastructure page](https://blog.pythondiscord.com/statistics-infrastructure). -We are always open to more statistics so add as many as you can! - ---- - -### Optional: Working with the help forum - -**Note**: This is only required when you're not configuring the bot [automatically](#automatic-configuration) +For that purpose, even if you run the bot through Docker, you might want to [setup a development environment](../bot-extended-configuration-options#setting-up-a-development-environment), as otherwise the hook installation will fail. -If you will be working on a feature that includes the python help forum, you will need to use `Forum Channels`. - -Forum channels cannot be included in a template, which is why this needs to be done by hand for the time being. - -To activate forum channels, your Discord server needs to have the community feature. -If that's not the case already, here are the steps required to do it: -1. Go to server settings -2. Scroll down to the `COMMUNITY` section and click on `Enable Community` -3. Click on `Get Started` and fill out the necessary info - -Once the previous steps are done, all that is left is to: -1. Create a new channel -2. Choose the `Forum` type -3. [Copy its ID](../obtaining-discord-ids#channel-id) -4. Add the following line to the `.env.server` file: `channels_python_help={newly_created_forum_channel_id}` - ---- - -### Optional: Working with Redis -In [Configure the Bot](#envserver) you were asked to set `redis_use_fakeredis=true`. If you do not need to work on features that rely on Redis, this is enough. Fakeredis will give the illusion that features relying on Redis are saving information properly, but restarting the bot or the specific cog will wipe that information. - -If you are working on a feature that relies on Redis, you will need to enable Redis to make sure persistency is achieved for the feature across restarts. The first step towards that is going to `.env.server` and setting `redis.use_fakeredis` to `false`. - -#### Starting Redis in Docker (Recommended) -If you're using the Docker image provided in the project's Docker Compose, open your `.env.server` file. If you're running the bot in Docker, set `redis_host=redis`, and if you're running it on the host set it to `localhost`. Set `redis_password=""`. - -#### Starting Redis Using Other Methods -You can run your own instance of Redis, but in that case you will need to correctly set `redis_host` and `redis_port` in your `.env.server` file and the `REDIS_PASSWORD` in the `.env` file. -**Note**: The previously mentioned variables **SHOULD NOT** be overriden or changed in `constants.py` - ---- - -### Optional: Working with Metricity -[Metricity](https://github.com/python-discord/metricity) is our home-grown bot for collecting metrics on activity within the server, such as what users are present, and IDs of the messages they've sent. -Certain features in the Python bot rely on querying the Metricity database for information such as the number of messages a user has sent, most notably the voice verification system. - -If you wish to work on a feature that relies on Metricity, for your convenience we've made the process of using it relatively painless with Docker: Enter the `.env` file you've written for the Python bot, and append the line `USE_METRICITY=true`. -Note that if you don't need Metricity, there's no reason to have it enabled as it is just unnecessary overhead. - -To make the Metricity bot work with your test server, you will need to override its configurations similarly to the Python bot. -You can see the various configurations in [the Metricity repo](https://github.com/python-discord/metricity), but the bare minimum is the guild ID setting. -In your local version of the Python bot repo, create a file called `metricity-config.toml` and insert the following lines: -```yaml -[bot] -guild_id = replace_with_your_guild_id -``` -To properly replicate production behavior, set the `staff_role_id`, `staff_categories`, and `ignore_categories` fields as well. - -Now, `docker compose up` will also start Metricity. - -If you want to run the bot locally, you can run `docker compose up metricity` instead. - ---- - -### Optional: Working with bot moderation logs -To be able to view moderation-related logs published by the bot to site, you will need to set `urls_site_logs_view=http://localhost:8000/staff/bot/logs` in your `.env.server`. -This will work in both Docker and locally. - ---- +### Issues? +If you have any issues with setting up the bot, come discuss it with us on the [#dev-contrib](https://discord.gg/2h3qBv8Xaa) channel on our server. -### Optional: Changing your command prefix -If you would like a prefix other than the default `!`, set `BOT_PREFIX={{your_prefix}}` in `.env.server`. +If you find any bugs in the bot or would like to request a feature, feel free to [open an issue](https://github.com/python-discord/bot/issues/new/choose) on the repository. --- -### Issues? -If you have any issues with setting up the bot, come discuss it with us on the [#dev-contrib](https://discord.gg/2h3qBv8Xaa) channel on our server. +# Next steps +Now that you have everything setup, it is finally time to make changes to the bot! If you have not yet read the [contributing guidelines](../contributing-guidelines.md), now is a good time. Contributions that do not adhere to the guidelines may be rejected. -If you find any bugs in the bot or would like to request a feature, feel free to [open an issue](https://github.com/python-discord/bot/issues/new/choose) on the repository. +Have fun! --- -### Appendix: Full ENV File Options +# Appendix: Full ENV File Options The following is a list of all available environment variables used by the bot: | Variable | Required | Description | @@ -407,17 +193,8 @@ The following is a list of all available environment variables used by the bot: | `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | | `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | | `DEBUG` | In production | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default. | -| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)). | -| `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default. | +| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Staring Redis with other methods](../bot-extended-configuration-options#starting-redis-using-other-methods)). | +| `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Working with Metricity](../bot-extended-configuration-options#working-with-metricity)). `false` by default. | | `API_KEYS_GITHUB` | When you wish to interact with GitHub | The API key to interact with GitHub, for example to download files for the branding manager. | | `METABASE_USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. | | `METABASE_PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. | - ---- - -# Next steps -Now that you have everything setup, it is finally time to make changes to the bot! If you have not yet read the [contributing guidelines](../contributing-guidelines.md), now is a good time. Contributions that do not adhere to the guidelines may be rejected. - -If you're not sure where to go from here, our [detailed walkthrough](../#2-set-up-the-project) is for you. - -Have fun! diff --git a/pydis_site/apps/content/resources/rules.md b/pydis_site/apps/content/resources/rules.md index a0bdb38d..e55c6715 100644 --- a/pydis_site/apps/content/resources/rules.md +++ b/pydis_site/apps/content/resources/rules.md @@ -5,7 +5,7 @@ icon: fab fa-discord --- We have a small but strict set of rules on our server. Please read over them and take them on board. If you don't understand a rule or need to report an incident, please send a direct message to <code>@ModMail</code>! -> 1. Follow the [Python Discord Code of Conduct](/pages/code-of-conduct/). +> 1. Follow the [Python Discord Code of Conduct](https://pythondiscord.com/pages/code-of-conduct/). > 2. Follow the [Discord Community Guidelines](https://discordapp.com/guidelines) and [Terms of Service](https://discordapp.com/terms). > 3. Respect staff members and listen to their instructions. > 4. Use English to the best of your ability. Be polite if someone speaks English imperfectly. diff --git a/pydis_site/apps/content/templatetags/__init__.py b/pydis_site/apps/content/templatetags/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/pydis_site/apps/content/templatetags/__init__.py diff --git a/pydis_site/apps/content/templatetags/page_src.py b/pydis_site/apps/content/templatetags/page_src.py new file mode 100644 index 00000000..143c420c --- /dev/null +++ b/pydis_site/apps/content/templatetags/page_src.py @@ -0,0 +1,25 @@ +from django import template +from django.conf import settings + + +register = template.Library() + + +def page_src_url(request_path: str) -> str: + """ + Return the corresponding GitHub source URL for the current content article. + + request_path is the relative path of an article, as returned by `request.path` in templates. + + GitHub source URL is set in settings.py as CONTENT_SRC_URL, prefix for the + url which the request path would be appended to. + + Assumes '.md' file extension for the page source files. + + For example: /pages/rules/ would return: + https://github.com/python-discord/site/tree/main/pydis_site/apps/content/resources/rules.md + """ + src_url = request_path.replace("/pages/", settings.CONTENT_SRC_URL) + src_url = src_url[:-1] + ".md" + return src_url diff --git a/pydis_site/apps/content/tests/test_views.py b/pydis_site/apps/content/tests/test_views.py index 3ef9bcc4..e4f898ef 100644 --- a/pydis_site/apps/content/tests/test_views.py +++ b/pydis_site/apps/content/tests/test_views.py @@ -1,6 +1,6 @@ import textwrap from pathlib import Path -from unittest import TestCase +from unittest import TestCase, mock import django.test import markdown @@ -223,7 +223,8 @@ class TagViewTests(django.test.TestCase): def test_invalid_tag_404(self): """Test that a tag which doesn't exist raises a 404.""" - response = self.client.get("/pages/tags/non-existent/") + with mock.patch("pydis_site.apps.content.utils.fetch_tags", autospec=True): + response = self.client.get("/pages/tags/non-existent/") self.assertEqual(404, response.status_code) def test_context_tag(self): diff --git a/pydis_site/apps/home/tests/test_views.py b/pydis_site/apps/home/tests/test_views.py index b1215df4..379b984e 100644 --- a/pydis_site/apps/home/tests/test_views.py +++ b/pydis_site/apps/home/tests/test_views.py @@ -1,3 +1,5 @@ +from unittest import mock + from django.test import TestCase from django.urls import reverse @@ -6,5 +8,6 @@ class TestIndexReturns200(TestCase): def test_index_returns_200(self): """Check that the index page returns a HTTP 200 response.""" url = reverse('home:home') - resp = self.client.get(url) + with mock.patch("pydis_site.apps.home.views.HomeView._get_api_data", autospec=True): + resp = self.client.get(url) self.assertEqual(resp.status_code, 200) diff --git a/pydis_site/apps/resources/resources/python_graph_gallery.yaml b/pydis_site/apps/resources/resources/python_graph_gallery.yaml new file mode 100644 index 00000000..b8aaeb4d --- /dev/null +++ b/pydis_site/apps/resources/resources/python_graph_gallery.yaml @@ -0,0 +1,17 @@ +description: A collection of hundreds of charts made with Python with their associated reproducible code. +name: Python Graph Gallery +title_url: https://www.python-graph-gallery.com/ +urls: + - icon: branding/github + url: https://github.com/holtzy/The-Python-Graph-Gallery + color: black +tags: + topics: + - data science + payment_tiers: + - free + difficulty: + - beginner + - intermediate + type: + - tutorial diff --git a/pydis_site/apps/staff/README.md b/pydis_site/apps/staff/README.md new file mode 100644 index 00000000..6707bf26 --- /dev/null +++ b/pydis_site/apps/staff/README.md @@ -0,0 +1,19 @@ +# The "staff" app + +This Django application hosts any staff-internal tooling, which, at time of +writing, is only an endpoint to view logs uploaded by the Python bot. + +This app mainly interacts with a single model from the `api` app, and has no +models on its own. The following files and directories are of interest: + +- [`templatetags`](./templatetags) contains custom template tags that help with + formatting the HTML templates of this app (these can be found in the template + root direcetory). + +- [`tests`](./tests) contains standard Django unit tests that validate both the + template tags and functionality of the log viewer itself. + +- [`urls.py`](./urls.py) contains the regular Django URL routing logic. + +- [`views.py`](./views.py) contains standard Django views. In our case, the + main work happens in the template, so this is relatively straightforward. diff --git a/pydis_site/apps/staff/templatetags/deletedmessage_filters.py b/pydis_site/apps/staff/templatetags/deletedmessage_filters.py index 5026068e..9d8f1819 100644 --- a/pydis_site/apps/staff/templatetags/deletedmessage_filters.py +++ b/pydis_site/apps/staff/templatetags/deletedmessage_filters.py @@ -28,5 +28,5 @@ def footer_datetime(timestamp: str) -> datetime: @register.filter def visible_newlines(text: str) -> str: - """Takes an embed timestamp and returns a timezone-aware datetime object.""" + """Visualizes newlines in text by replacing them with a grey-ish `↵`.""" return text.replace("\n", " <span class='has-text-grey'>↵</span><br>") diff --git a/pydis_site/apps/staff/urls.py b/pydis_site/apps/staff/urls.py index ca8d1a0f..0565592b 100644 --- a/pydis_site/apps/staff/urls.py +++ b/pydis_site/apps/staff/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from .viewsets import LogView +from .views import LogView app_name = 'staff' urlpatterns = [ diff --git a/pydis_site/apps/staff/viewsets/logs.py b/pydis_site/apps/staff/views.py index 22dede95..22dede95 100644 --- a/pydis_site/apps/staff/viewsets/logs.py +++ b/pydis_site/apps/staff/views.py diff --git a/pydis_site/apps/staff/viewsets/__init__.py b/pydis_site/apps/staff/viewsets/__init__.py deleted file mode 100644 index 6b10eb83..00000000 --- a/pydis_site/apps/staff/viewsets/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .logs import LogView - -__all__ = ["LogView"] diff --git a/pydis_site/settings.py b/pydis_site/settings.py index e9e0ba67..9da9a156 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -332,3 +332,8 @@ REDIRECTIONS_PATH = Path(BASE_DIR, "pydis_site", "apps", "redirect", "redirects. # How long to wait for synchronous requests before timing out TIMEOUT_PERIOD = env("TIMEOUT_PERIOD") + +# Source files url for 'Edit on GitHub' link on content articles +CONTENT_SRC_URL = ( + "https://github.com/python-discord/site/tree/main/pydis_site/apps/content/resources/" +) diff --git a/pydis_site/static/css/content/page.css b/pydis_site/static/css/content/page.css index d831f86d..cabf6962 100644 --- a/pydis_site/static/css/content/page.css +++ b/pydis_site/static/css/content/page.css @@ -2,6 +2,16 @@ padding: 1rem; } +#edit-on-github { + margin-left: 1rem; +} + +@media (max-width: 600px) { + #edit-on-github { + display: none; + } +} + i.has-icon-padding { padding: 0 10px 25px 0; } diff --git a/pydis_site/templates/content/base.html b/pydis_site/templates/content/base.html index 2fd721a3..b04c7efa 100644 --- a/pydis_site/templates/content/base.html +++ b/pydis_site/templates/content/base.html @@ -1,5 +1,6 @@ {% extends 'base/base.html' %} {% load static %} +{% load page_src %} {% block title %}{{ page_title }}{% endblock %} {% block head %} @@ -29,10 +30,21 @@ <li class="is-active"><a href="#">{{ page_title }}</a></li> </ul> </nav> + </div> + <div class="is-flex is-pulled-right is-right"> {# Sub-Article dropdown for category pages #} {% if subarticles %} {% include "content/dropdown.html" %} {% endif %} + {# Edit on GitHub for content articles #} + {% if page %} + <div id="edit-on-github"> + <a href="{{ request.path | page_src_url }}"> + <i class="fa-solid fa-pencil"></i> + Edit on GitHub + </a> + </div> + {% endif %} </div> </section> diff --git a/pydis_site/templates/content/dropdown.html b/pydis_site/templates/content/dropdown.html index 13c89c68..60560547 100644 --- a/pydis_site/templates/content/dropdown.html +++ b/pydis_site/templates/content/dropdown.html @@ -1,4 +1,4 @@ -<div class="dropdown is-pulled-right is-right" id="dropdown" style="z-index: 1"> +<div class="dropdown" id="dropdown" style="z-index: 1"> <div class="dropdown-trigger"> <a aria-haspopup="true" aria-controls="subarticle-menu"> <span>Sub-Articles</span> diff --git a/pydis_site/templates/events/pages/code-jams/9/_index.html b/pydis_site/templates/events/pages/code-jams/9/_index.html index ca7c4f90..3e60c387 100644 --- a/pydis_site/templates/events/pages/code-jams/9/_index.html +++ b/pydis_site/templates/events/pages/code-jams/9/_index.html @@ -20,15 +20,56 @@ and walking through the program that your team has created. More details and specifics of this will be released within the next 2 weeks. </p> + <h3 id="winners"><a href="#winners">Code Jam Winners</a></h3> + <p>Congratulations to our winners and the two runner ups! Check out their projects below.</p> + + <h4 class="mt-5 mb-2"><i class="fa fa-trophy"></i> Cerebral Centaurs: Drawn</h4> + <p class="my-1"><em>Palmirka, Tu®tle, collerek, Rortox</em></p> + <p class="my-1"> + Drawn is based on old school Pictionary game, with additional surprises waiting for the drawer each turn. + </p> + <p> + <a href="https://github.com/collerek/cerebral-centaurs" title="Cerebral Centaurs GitHub Repository" target="_blank" rel="noopener"><i class="fa fa-github"></i> GitHub Repository</a> + <br/> + + </p> + + <h4 class="mt-5 mb-2"><i class="fa fa-medal"></i> Kingly Kelpies: for level_id in range(14)</h4> + <p class="my-1"><em>Kingu, Falkan, Bamboodja, Redriel, Vinyzu</em></p> + <p class="my-1"> + A simple multiplayer puzzle game, in which your aim is to reach the goal by pressing buttons, standing on plates and moving boxes. + </p> + <p> + <a href="https://www.youtube.com/watch?v=-VQ_ijuo-Mg" title="Kingly Kelpies Demo Video" target="_blank" rel="noopener"><i class="fa fa-video"> </i> Demo video</a> + <br/> + <a href="https://github.com/Kingly-elpies/KinglyKelpies" title="Kingly Kelpies GitHub Repository" target="_blank" rel="noopener"><i class="fa fa-github"></i> GitHub Repository</a> + <br/> + </p> + + <h4 class="mt-5 mb-2"><i class="fa fa-medal"></i> Logical Leprechauns: Curse of the Mites</h4> + <p class="my-1"><em>Fyx, Aboo Minister, A5rocks, Bautista, ~tylerr</em></p> + <p class="my-1"> + Curse of the Mites is a text based MUD (multi-user dungeon) in which you play as a caterpillar whose goal is to grow into a butterfly to escape the forest cursed by mites. + <p> + <a href="https://github.com/AbooMinister25/Curse-of-the-Mites" title="Logical Leprechauns GitHub Repository" target="_blank" rel="noopener"><i class="fa fa-github"></i> GitHub Repository</a> + <br/> + </p> + + <h3 id="submissions"><a href="#submissions">Submissions</a></h3> + <p> + By the end of the jam, 20+ teams made project submissions. Check them all out here: + <div class="has-text-centered"><a class="button is-link" href="submissions">View Submissions</a></div> + </p> + <h3 id="important-dates"><a href="#important-dates">Important Dates</a></h3> <ul> - <li><strike>Saturday, June 18 - Form to submit theme suggestions opens</strike></li> - <li><strike>Wednesday, June 29 - The Qualifier is released</strike></li> - <li><strike>Wednesday, July 6 - Voting for the theme opens</strike></li> - <li><strike>Wednesday, July 13 - The Qualifier closes</strike></li> - <li><strike>Thursday, July 21 - Code Jam Begins</strike></li> - <li><strike>Sunday, July 31 - Coding portion of the jam ends</strike></li> - <li><strike>Sunday, August 4 - Code Jam submissions are closed</strike></li> + <li>Saturday, June 18 - Form to submit theme suggestions opens</li> + <li>Wednesday, June 29 - The Qualifier is released</li> + <li>Wednesday, July 6 - Voting for the theme opens</li> + <li>Wednesday, July 13 - The Qualifier closes</li> + <li>Thursday, July 21 - Code Jam Begins</li> + <li>Sunday, July 31 - Coding portion of the jam ends</li> + <li>Sunday, August 4 - Code Jam submissions are closed</li> </ul> <h3 id="qualifier"><a href="#how-to-join">The Qualifier</a></h3> diff --git a/pydis_site/templates/events/pages/code-jams/9/submissions.html b/pydis_site/templates/events/pages/code-jams/9/submissions.html new file mode 100644 index 00000000..e0139ce8 --- /dev/null +++ b/pydis_site/templates/events/pages/code-jams/9/submissions.html @@ -0,0 +1,232 @@ +{% extends "events/base_sidebar.html" %} + +{% load static %} + +{% block title %}Summer Code Jam 2022{% endblock %} + +{% block breadcrumb %} + <li><a href="{% url "events:index" %}">Events</a></li> + <li><a href="{% url "events:page" path="code-jams" %}">Code Jams</a></li> + <li><a href="{% url "events:page" path="code-jams/9" %}">Summer Code Jam 2022</a></li> + <li class="is-active"><a href="#">Submissions</a></li> +{% endblock %} + +{% block event_content %} + <p> + Below is a list of all projects submitted by the end of Summer Code Jam 2022 + </p> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Artful Angels</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/Artful-Angels/code-jam" title="Artful Angels">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Burly Barghests</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/jasonho1308/summer-code-jam-2022" title="Burly Barghests">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Cerebral Centaurs</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/collerek/cerebral-centaurs" title="Cerebral Centaurs">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Dynamic Dryads</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/Kronifer/code-jam-9" title="Dynamic Dryads">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Generous Giants</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/bast0006/cj9-generous-giants/" title="Generous Giants">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Genuine Djinn</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/srijal30/genuine-djinn" title="Genuine Djinn">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Gorgeous Ghouls</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/Gorgeous-Ghouls/Blak" title="Gorgeous Ghouls">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Heroic Hydra</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/mkadiya20/heroic-hydra" title="Heroic Hydra">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Kindly Kappa</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/Vthechamp22/kindly-kappa" title="Kindly Kappa">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Kingly Kelpies</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/Kingly-elpies/KinglyKelpies" title="Kingly Kelpies">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Logical Leprechauns</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/AbooMinister25/Curse-of-the-Mites" title="Logical Leprechauns">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Lucky Leucrota</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/lucky-leucrota/cj9-lucky-leucrota" title="Lucky Leucrota">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Muscular Mermaids</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/vonvic/Python-CodeJam-2022-MM" title="Muscular Mermaids">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Old-Fashioned Orcs</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/smileyface12349/old-fashioned-orcs" title="Old-Fashioned Orcs">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Sassy Snallygasters</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/SFM61319/sassy-snallygasters_code-jam-9" title="Sassy Snallygasters">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Silly Selkies</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/kguzek/code-jam-2022" title="Silly Selkies">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Spiffy Sphinxes</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/Sanyok6/Chesstopia" title="Spiffy Sphinxes">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Stately Satyrs</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/Lime-Parallelogram/cj2022-stately-satyrs" title="Stately Satyrs">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Tireless Timingila</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/Ibrahim2750mi/tireless-timingila" title="Tireless Timingila">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Towering Tupilaqs</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/TheFactoryMustGrowLarger/towering-tupilaqs" title="Towering Tupilaqs">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Valiant Valkyries</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/legosiv/valiant-valkyries" title="Valiant Valkyries">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Wily Werewolves</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/HarshitJoshi9152/Codejam-2022-pythondiscord" title="Wily Werewolves">GitHub</a></p> + </div> + </div> + + <div class="columns is-mobile is-centered"> + <div class="column is-half"> + <p class="has-text-centered">Zesty Zombies</p> + </div> + <div class="column is-half"> + <p class="has-text-centered"><a href="https://github.com/nitinramvelraj/zesty-zombies-2.0" title="Zesty Zombies">GitHub</a></p> + </div> + </div> + +{% endblock %} + +{% block sidebar %} + + {% include "events/sidebar/code-jams/9.html" %} + +{% endblock %} diff --git a/pyproject.toml b/pyproject.toml index 8df11a99..315d72ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,10 +8,10 @@ license = "MIT" [tool.poetry.dependencies] python = "3.10.*" -django = "4.2" +django = "4.2.1" django-distill = "3.1.3" django-environ = "0.10.0" -django-filter = "23.1" +django-filter = "23.2" django-prometheus = "2.2.0" django-simple-bulma = "2.5.0" djangorestframework = "3.14.0" @@ -23,7 +23,7 @@ PyJWT = {version = "2.6.0", extras = ["crypto"]} pymdown-extensions = "9.11" python-frontmatter = "1.0.0" pyyaml = "6.0" -sentry-sdk = "1.19.1" +sentry-sdk = "1.21.1" whitenoise = "6.4.0" [tool.poetry.group.dev.dependencies] @@ -41,10 +41,10 @@ flake8-tidy-imports = "4.8.0" flake8-string-format = "0.3.0" flake8-todo = "0.7" pep8-naming = "0.13.3" -pre-commit = "3.2.2" +pre-commit = "3.3.0" [tool.poetry.group.test.dependencies] -coverage = "7.2.3" +coverage = "7.2.5" [build-system] requires = ["poetry-core>=1.2.0"] |