diff options
| author | 2019-01-06 00:27:00 -0500 | |
|---|---|---|
| committer | 2019-01-06 00:27:00 -0500 | |
| commit | 802489b0fceec0088c7eea56f39b00f74189a3e8 (patch) | |
| tree | 0f8c0bf847fac919445dafc18541cd49799ccd80 | |
| parent | Add infraction posting for AntiSpam mutes (diff) | |
| parent | Merge pull request #251 from python-discord/invite-filter-dm (diff) | |
Merge branch 'master' into antispam-mute-infr
| -rw-r--r-- | .pre-commit-config.yaml | 5 | ||||
| -rw-r--r-- | Pipfile | 7 | ||||
| -rw-r--r-- | Pipfile.lock | 419 | ||||
| -rw-r--r-- | bot/cogs/bot.py | 3 | ||||
| -rw-r--r-- | bot/cogs/defcon.py | 40 | ||||
| -rw-r--r-- | bot/cogs/eval.py | 2 | ||||
| -rw-r--r-- | bot/cogs/filtering.py | 66 | ||||
| -rw-r--r-- | bot/cogs/moderation.py | 133 | ||||
| -rw-r--r-- | bot/cogs/modlog.py | 16 | ||||
| -rw-r--r-- | bot/constants.py | 8 | ||||
| -rw-r--r-- | bot/pagination.py | 26 | ||||
| -rw-r--r-- | config-default.yml | 9 | 
12 files changed, 490 insertions, 244 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..1d75342a2 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: +-   repo: https://github.com/pre-commit/pre-commit-hooks +    rev: v2.0.0 +    hooks: +    - id: flake8
\ No newline at end of file @@ -4,7 +4,7 @@ verify_ssl = true  name = "pypi"  [packages] -discord-py = {git = "https://github.com/Rapptz/discord.py.git", extras = ["voice"], ref = "860d6a9ace8248dfeec18b8b159e7b757d9f56bb", editable = true} +discord-py = {git = "https://github.com/Rapptz/discord.py.git",extras = ["voice"],ref = "860d6a9ace8248dfeec18b8b159e7b757d9f56bb",editable = true}  dulwich = "*"  aiodns = "*"  logmatic-python = "*" @@ -29,6 +29,7 @@ requests = "*"  "flake8-string-format" = "*"  safety = "*"  dodgy = "*" +pre-commit = "*"  [requires]  python_version = "3.6" @@ -36,12 +37,10 @@ python_version = "3.6"  [scripts]  start = "python -m bot"  lint = "python -m flake8" - +precommit = "pre-commit install"  build = "docker build -t pythondiscord/bot:latest -f docker/bot.Dockerfile ."  push = "docker push pythondiscord/bot:latest" -  buildbase = "docker build -t pythondiscord/bot-base:latest -f docker/base.Dockerfile ."  pushbase = "docker push pythondiscord/bot-base:latest" -  buildci = "docker build -t pythondiscord/bot-ci:latest -f docker/ci.Dockerfile ."  pushci = "docker push pythondiscord/bot-ci:latest" diff --git a/Pipfile.lock b/Pipfile.lock index 506b17065..92566c3ed 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@  {      "_meta": {          "hash": { -            "sha256": "79a3c633f145dbf93ba5b2460d3f49346495328af7302e59be326e9324785cf3" +            "sha256": "d53f89c6d3b32ccbc2dadaff1a7e9ee1bdcbd1df9cddab35def36bcceec98b27"          },          "pipfile-spec": 6,          "requires": { @@ -18,11 +18,11 @@      "default": {          "aio-pika": {              "hashes": [ -                "sha256:6438e72963e459552f196a07a081a5f6dc54d42a474292b8497bd4a59554fc85", -                "sha256:dc15b451dca6d2b1c504ab353e3f2fe7e7e252fdb1c219261b5412e1cafbc72d" +                "sha256:c3eb639f7fc5c96355e7a227380989c9e0f342bb6612e6671ea76d188813ba45", +                "sha256:ea26efd262d7c4cd4ac00fb968ede89e82c00ad331b47415e3c2353a4b91cbe0"              ],              "index": "pypi", -            "version": "==4.6.3" +            "version": "==4.9.1"          },          "aiodns": {              "hashes": [ @@ -57,6 +57,7 @@                  "sha256:f1839db4c2b08a9c8f9788112644f8a8557e8e0ecc77b07091afabb941dc55d0",                  "sha256:f3df52362be39908f9c028a65490fae0475e4898b43a03d8aa29d1e765b45e07"              ], +            "index": "pypi",              "version": "==3.4.4"          },          "alabaster": { @@ -89,18 +90,18 @@          },          "beautifulsoup4": {              "hashes": [ -                "sha256:194ec62a25438adcb3fdb06378b26559eda1ea8a747367d34c33cef9c7f48d57", -                "sha256:90f8e61121d6ae58362ce3bed8cd997efb00c914eae0ff3d363c32f9a9822d10", -                "sha256:f0abd31228055d698bb392a826528ea08ebb9959e6bea17c606fd9c9009db938" +                "sha256:1ed70a0e99742653953d68462378a1a8eb65dca5f7c8fa44a05a2a0b3545df67", +                "sha256:6a7f5e0efc563cd1ffeefba6d528b97aa0d313c02dd126ba6c455e5fe5bd48eb", +                "sha256:e394827904cc4923f443e8dd2e9968343669c8e1ad7a8d62d7541e780884acb8"              ], -            "version": "==4.6.3" +            "version": "==4.7.0"          },          "certifi": {              "hashes": [ -                "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", -                "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" +                "sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7", +                "sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033"              ], -            "version": "==2018.10.15" +            "version": "==2018.11.29"          },          "cffi": {              "hashes": [ @@ -188,17 +189,10 @@          },          "idna": {              "hashes": [ -                "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", -                "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" -            ], -            "version": "==2.7" -        }, -        "idna-ssl": { -            "hashes": [ -                "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c" +                "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", +                "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"              ], -            "markers": "python_version < '3.7'", -            "version": "==1.1.0" +            "version": "==2.8"          },          "imagesize": {              "hashes": [ @@ -231,39 +225,39 @@          },          "lxml": {              "hashes": [ -                "sha256:02bc220d61f46e9b9d5a53c361ef95e9f5e1d27171cd461dddb17677ae2289a5", -                "sha256:22f253b542a342755f6cfc047fe4d3a296515cf9b542bc6e261af45a80b8caf6", -                "sha256:2f31145c7ff665b330919bfa44aacd3a0211a76ca7e7b441039d2a0b0451e415", -                "sha256:36720698c29e7a9626a0dc802ef8885f8f0239bfd1689628ecd459a061f2807f", -                "sha256:438a1b0203545521f6616132bfe0f4bca86f8a401364008b30e2b26ec408ce85", -                "sha256:4815892904c336bbaf73dafd54f45f69f4021c22b5bad7332176bbf4fb830568", -                "sha256:5be031b0f15ad63910d8e5038b489d95a79929513b3634ad4babf77100602588", -                "sha256:5c93ae37c3c588e829b037fdfbd64a6e40c901d3f93f7beed6d724c44829a3ad", -                "sha256:60842230678674cdac4a1cf0f707ef12d75b9a4fc4a565add4f710b5fcf185d5", -                "sha256:62939a8bb6758d1bf923aa1c13f0bcfa9bf5b2fc0f5fa917a6e25db5fe0cfa4e", -                "sha256:75830c06a62fe7b8fe3bbb5f269f0b308f19f3949ac81cfd40062f47c1455faf", -                "sha256:81992565b74332c7c1aff6a913a3e906771aa81c9d0c68c68113cffcae45bc53", -                "sha256:8c892fb0ee52c594d9a7751c7d7356056a9682674b92cc1c4dc968ff0f30c52f", -                "sha256:9d862e3cf4fc1f2837dedce9c42269c8c76d027e49820a548ac89fdcee1e361f", -                "sha256:a623965c086a6e91bb703d4da62dabe59fe88888e82c4117d544e11fd74835d6", -                "sha256:a7783ab7f6a508b0510490cef9f857b763d796ba7476d9703f89722928d1e113", -                "sha256:aab09fbe8abfa3b9ce62aaf45aca2d28726b1b9ee44871dbe644050a2fff4940", -                "sha256:abf181934ac3ef193832fb973fd7f6149b5c531903c2ec0f1220941d73eee601", -                "sha256:ae07fa0c115733fce1e9da96a3ac3fa24801742ca17e917e0c79d63a01eeb843", -                "sha256:b9c78242219f674ab645ec571c9a95d70f381319a23911941cd2358a8e0521cf", -                "sha256:bccb267678b870d9782c3b44d0cefe3ba0e329f9af8c946d32bf3778e7a4f271", -                "sha256:c4df4d27f4c93b2cef74579f00b1d3a31a929c7d8023f870c4b476f03a274db4", -                "sha256:caf0e50b546bb60dfa99bb18dfa6748458a83131ecdceaf5c071d74907e7e78a", -                "sha256:d3266bd3ac59ac4edcd5fa75165dee80b94a3e5c91049df5f7c057ccf097551c", -                "sha256:db0d213987bcd4e6d41710fb4532b22315b0d8fb439ff901782234456556aed1", -                "sha256:dbbd5cf7690a40a9f0a9325ab480d0fccf46d16b378eefc08e195d84299bfae1", -                "sha256:e16e07a0ec3a75b5ee61f2b1003c35696738f937dc8148fbda9fe2147ccb6e61", -                "sha256:e175a006725c7faadbe69e791877d09936c0ef2cf49d01b60a6c1efcb0e8be6f", -                "sha256:edd9c13a97f6550f9da2236126bb51c092b3b1ce6187f2bd966533ad794bbb5e", -                "sha256:fa39ea60d527fbdd94215b5e5552f1c6a912624521093f1384a491a8ad89ad8b" +                "sha256:16cf8bac33ec17049617186d63006ba49da7c5be417042877a49f0ef6d7a195d", +                "sha256:18f2d8f14cc61e66e8a45f740d15b6fc683c096f733db1f8d0ee15bcac9843de", +                "sha256:260868f69d14a64dd1de9cf92e133d2f71514d288de4906f109bdf48ca9b756a", +                "sha256:29b8acd8ecdf772266dbac491f203c71664b0b07ad4309ba2c3bb131306332fc", +                "sha256:2b05e5e06f8e8c63595472dc887d0d6e0250af754a35ba690f6a6abf2ef85691", +                "sha256:30d6ec05fb607a5b7345549f642c7c7a5b747b634f6d5e935596b910f243f96f", +                "sha256:3bf683f0237449ebc1851098f664410e3c99ba3faa8c9cc82c6acfe857df1767", +                "sha256:3ce5488121eb15513c4b239dadd67f9e7959511bd766aac6be0c35e80274f298", +                "sha256:48be0c375350a5519bb9474b42a9c0e7ab709fb45f11bfcd33de876791137896", +                "sha256:49bc343ca3b30cd860845433bb9f62448a54ff87b632175108bacbc5dc63e49e", +                "sha256:4cc7531e86a43ea66601763c5914c3d3adb297f32e4284957609b90d41825fca", +                "sha256:4e9822fad564d82035f0b6d701a890444560210f8a8648b8f15850f8fe883cd9", +                "sha256:51a9a441aefc8c93512bad5efe867d2ff086e7249ce0fc3b47c310644b352936", +                "sha256:5bbed9efc8aeb69929140f71a30e655bf496b45b766861513960e1b11168d475", +                "sha256:60a5323b2bc893ca1059d283d6695a172d51cc95a70c25b3e587e1aad5459c38", +                "sha256:7035d9361f3ceec9ccc1dd3482094d1174580e7e1bf6870b77ea758f7cad15d2", +                "sha256:76d62cc048bda0ebf476689ad3eb8e65e6827e43a7521be3b163071020667b8c", +                "sha256:78163b578e6d1836012febaa1865e095ccc7fc826964dd69a2dbfe401618a1f7", +                "sha256:83b58b2b5904d50de03a47e2f56d24e9da4cf7e3b0d66fb4510b18fca0faf910", +                "sha256:a07447e46fffa5bb4d7a0af0a6505c8517e9bd197cfd2aec79e499b6e86cde49", +                "sha256:a17d808b3edca4aaf6b295b5a388c844a0b7f79aca2d79eec5acc1461db739e3", +                "sha256:a378fd61022cf4d3b492134c3bc48204ac2ff19e0813b23e07c3dd95ae8df0bc", +                "sha256:aa7d096a44ae3d475c5ed763e24cf302d32462e78b61bba73ce1ad0efb8f522a", +                "sha256:ade8785c93a985956ba6499d5ea6d0a362e24b4a9ba07dd18920fd67cccf63ea", +                "sha256:cc039668f91d8af8c4094cfb5a67c7ae733967fdc84c0507fe271db81480d367", +                "sha256:d89f1ffe98744c4b5c11f00fb843a4e72f68a6279b5e38168167f1b3c0fdd84c", +                "sha256:e691b6ef6e27437860016bd6c32e481bdc2ed3af03289707a38b9ca422105f40", +                "sha256:e750da6ac3ca624ae3303df448664012f9b6f9dfbc5d50048ea8a12ce2f8bc29", +                "sha256:eca305b200549906ea25648463aeb1b3b220b716415183eaa99c998a846936d9", +                "sha256:f52fe795e08858192eea167290033b5ff24f50f51781cb78d989e8d63cfe73d1"              ],              "index": "pypi", -            "version": "==4.2.5" +            "version": "==4.2.6"          },          "markdownify": {              "hashes": [ @@ -307,37 +301,37 @@          },          "multidict": {              "hashes": [ -                "sha256:013eb6591ab95173fd3deb7667d80951abac80100335b3e97b5fa778c1bb4b91", -                "sha256:0bffbbbb48db35f57dfb4733e943ac8178efb31aab5601cb7b303ee228ce96af", -                "sha256:1a34aab1dfba492407c757532f665ba3282ec4a40b0d2f678bda828ef422ebb7", -                "sha256:1b4b46a33f459a2951b0fd26c2d80639810631eb99b3d846d298b02d28a3e31d", -                "sha256:1d616d80c37a388891bf760d64bc50cac7c61dbb7d7013f2373aa4b44936e9f0", -                "sha256:225aefa7befbe05bd0116ef87e8cd76cbf4ac39457a66faf7fb5f3c2d7bea19a", -                "sha256:2c9b28985ef7c830d5c7ea344d068bcdee22f8b6c251369dea98c3a814713d44", -                "sha256:39e0600f8dd72acb011d09960da560ba3451b1eca8de5557c15705afc9d35f0e", -                "sha256:3c642c40ea1ca074397698446893a45cd6059d5d071fc3ba3915c430c125320f", -                "sha256:42357c90b488fac38852bcd7b31dcd36b1e2325413960304c28b8d98e6ff5fd4", -                "sha256:6ac668f27dbdf8a69c31252f501e128a69a60b43a44e43d712fb58ce3e5dfcca", -                "sha256:713683da2e3f1dd81a920c995df5dda51f1fff2b3995f5864c3ee782fcdcb96c", -                "sha256:73b6e7853b6d3bc0eac795044e700467631dff37a5a33d3230122b03076ac2f9", -                "sha256:77534c1b9f4a5d0962392cad3f668d1a04036b807618e3357eb2c50d8b05f7f7", -                "sha256:77b579ef57e27457064bb6bb4c8e5ede866af071af60fe3576226136048c6dfa", -                "sha256:82cf28f18c935d66c15a6f82fda766a4138d21e78532a1946b8ec603019ba0b8", -                "sha256:937e8f12f9edc0d2e351c09fc3e7335a65eefb75406339d488ee46ef241f75d8", -                "sha256:985dbf59e92f475573a04598f9a00f92b4fdb64fc41f1df2ea6f33b689319537", -                "sha256:9c4fab7599ba8c0dbf829272c48c519625c2b7f5630b49925802f1af3a77f1f4", -                "sha256:9e8772be8455b49a85ad6dbf6ce433da7856ba481d6db36f53507ae540823b15", -                "sha256:a06d6d88ce3be4b54deabd078810e3c077a8b2e20f0ce541c979b5dd49337031", -                "sha256:a1da0cdc3bc45315d313af976dab900888dbb477d812997ee0e6e4ea43d325e5", -                "sha256:a6652466a4800e9fde04bf0252e914fff5f05e2a40ee1453db898149624dfe04", -                "sha256:a7f23523ea6a01f77e0c6da8aae37ab7943e35630a8d2eda7e49502f36b51b46", -                "sha256:a87429da49f4c9fb37a6a171fa38b59a99efdeabffb34b4255a7a849ffd74a20", -                "sha256:c26bb81d0d19619367a96593a097baec2d5a7b3a0cfd1e3a9470277505a465c2", -                "sha256:d4f4545edb4987f00fde44241cef436bf6471aaac7d21c6bbd497cca6049f613", -                "sha256:daabc2766a2b76b3bec2086954c48d5f215f75a335eaee1e89c8357922a3c4d5", -                "sha256:f08c1dcac70b558183b3b755b92f1135a76fd1caa04009b89ddea57a815599aa" -            ], -            "version": "==4.5.1" +                "sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f", +                "sha256:041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3", +                "sha256:045b4dd0e5f6121e6f314d81759abd2c257db4634260abcfe0d3f7083c4908ef", +                "sha256:047c0a04e382ef8bd74b0de01407e8d8632d7d1b4db6f2561106af812a68741b", +                "sha256:068167c2d7bbeebd359665ac4fff756be5ffac9cda02375b5c5a7c4777038e73", +                "sha256:148ff60e0fffa2f5fad2eb25aae7bef23d8f3b8bdaf947a65cdbe84a978092bc", +                "sha256:1d1c77013a259971a72ddaa83b9f42c80a93ff12df6a4723be99d858fa30bee3", +                "sha256:1d48bc124a6b7a55006d97917f695effa9725d05abe8ee78fd60d6588b8344cd", +                "sha256:31dfa2fc323097f8ad7acd41aa38d7c614dd1960ac6681745b6da124093dc351", +                "sha256:34f82db7f80c49f38b032c5abb605c458bac997a6c3142e0d6c130be6fb2b941", +                "sha256:3d5dd8e5998fb4ace04789d1d008e2bb532de501218519d70bb672c4c5a2fc5d", +                "sha256:4a6ae52bd3ee41ee0f3acf4c60ceb3f44e0e3bc52ab7da1c2b2aa6703363a3d1", +                "sha256:4b02a3b2a2f01d0490dd39321c74273fed0568568ea0e7ea23e02bd1fb10a10b", +                "sha256:4b843f8e1dd6a3195679d9838eb4670222e8b8d01bc36c9894d6c3538316fa0a", +                "sha256:5de53a28f40ef3c4fd57aeab6b590c2c663de87a5af76136ced519923d3efbb3", +                "sha256:61b2b33ede821b94fa99ce0b09c9ece049c7067a33b279f343adfe35108a4ea7", +                "sha256:6a3a9b0f45fd75dc05d8e93dc21b18fc1670135ec9544d1ad4acbcf6b86781d0", +                "sha256:76ad8e4c69dadbb31bad17c16baee61c0d1a4a73bed2590b741b2e1a46d3edd0", +                "sha256:7ba19b777dc00194d1b473180d4ca89a054dd18de27d0ee2e42a103ec9b7d014", +                "sha256:7c1b7eab7a49aa96f3db1f716f0113a8a2e93c7375dd3d5d21c4941f1405c9c5", +                "sha256:7fc0eee3046041387cbace9314926aa48b681202f8897f8bff3809967a049036", +                "sha256:8ccd1c5fff1aa1427100ce188557fc31f1e0a383ad8ec42c559aabd4ff08802d", +                "sha256:8e08dd76de80539d613654915a2f5196dbccc67448df291e69a88712ea21e24a", +                "sha256:c18498c50c59263841862ea0501da9f2b3659c00db54abfbf823a80787fde8ce", +                "sha256:c49db89d602c24928e68c0d510f4fcf8989d77defd01c973d6cbe27e684833b1", +                "sha256:ce20044d0317649ddbb4e54dab3c1bcc7483c78c27d3f58ab3d0c7e6bc60d26a", +                "sha256:d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9", +                "sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7", +                "sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b" +            ], +            "version": "==4.5.2"          },          "packaging": {              "hashes": [ @@ -348,78 +342,81 @@          },          "pillow": {              "hashes": [ -                "sha256:00203f406818c3f45d47bb8fe7e67d3feddb8dcbbd45a289a1de7dd789226360", -                "sha256:0616f800f348664e694dddb0b0c88d26761dd5e9f34e1ed7b7a7d2da14b40cb7", -                "sha256:1f7908aab90c92ad85af9d2fec5fc79456a89b3adcc26314d2cde0e238bd789e", -                "sha256:2ea3517cd5779843de8a759c2349a3cd8d3893e03ab47053b66d5ec6f8bc4f93", -                "sha256:48a9f0538c91fc136b3a576bee0e7cd174773dc9920b310c21dcb5519722e82c", -                "sha256:5280ebc42641a1283b7b1f2c20e5b936692198b9dd9995527c18b794850be1a8", -                "sha256:5e34e4b5764af65551647f5cc67cf5198c1d05621781d5173b342e5e55bf023b", -                "sha256:63b120421ab85cad909792583f83b6ca3584610c2fe70751e23f606a3c2e87f0", -                "sha256:696b5e0109fe368d0057f484e2e91717b49a03f1e310f857f133a4acec9f91dd", -                "sha256:870ed021a42b1b02b5fe4a739ea735f671a84128c0a666c705db2cb9abd528eb", -                "sha256:916da1c19e4012d06a372127d7140dae894806fad67ef44330e5600d77833581", -                "sha256:9303a289fa0811e1c6abd9ddebfc770556d7c3311cb2b32eff72164ddc49bc64", -                "sha256:9577888ecc0ad7d06c3746afaba339c94d62b59da16f7a5d1cff9e491f23dace", -                "sha256:987e1c94a33c93d9b209315bfda9faa54b8edfce6438a1e93ae866ba20de5956", -                "sha256:99a3bbdbb844f4fb5d6dd59fac836a40749781c1fa63c563bc216c27aef63f60", -                "sha256:99db8dc3097ceafbcff9cb2bff384b974795edeb11d167d391a02c7bfeeb6e16", -                "sha256:a5a96cf49eb580756a44ecf12949e52f211e20bffbf5a95760ac14b1e499cd37", -                "sha256:aa6ca3eb56704cdc0d876fc6047ffd5ee960caad52452fbee0f99908a141a0ae", -                "sha256:aade5e66795c94e4a2b2624affeea8979648d1b0ae3fcee17e74e2c647fc4a8a", -                "sha256:b78905860336c1d292409e3df6ad39cc1f1c7f0964e66844bbc2ebfca434d073", -                "sha256:b92f521cdc4e4a3041cc343625b699f20b0b5f976793fb45681aac1efda565f8", -                "sha256:bfde84bbd6ae5f782206d454b67b7ee8f7f818c29b99fd02bf022fd33bab14cb", -                "sha256:c2b62d3df80e694c0e4a0ed47754c9480521e25642251b3ab1dff050a4e60409", -                "sha256:c5e2be6c263b64f6f7656e23e18a4a9980cffc671442795682e8c4e4f815dd9f", -                "sha256:c99aa3c63104e0818ec566f8ff3942fb7c7a8f35f9912cb63fd8e12318b214b2", -                "sha256:dae06620d3978da346375ebf88b9e2dd7d151335ba668c995aea9ed07af7add4", -                "sha256:db5499d0710823fa4fb88206050d46544e8f0e0136a9a5f5570b026584c8fd74", -                "sha256:f36baafd82119c4a114b9518202f2a983819101dcc14b26e43fc12cbefdce00e", -                "sha256:f52b79c8796d81391ab295b04e520bda6feed54d54931708872e8f9ae9db0ea1", -                "sha256:ff8cff01582fa1a7e533cb97f628531c4014af4b5f38e33cdcfe5eec29b6d888" +                "sha256:0cd42fe2d99ec6ce23aaf00947a7b7956ad2ed4b1695fd37545c3b8eae06d95a", +                "sha256:137bed8972089d65da63fb79b4949b0f2b99e9a58f1b494e82be43ba8b0f4226", +                "sha256:14eb2b2e4f2a14f5c89fd0edf55c5af0bf1a40fdf3838d81867f26f131cd557d", +                "sha256:1fc43ce8c4fa3754222cd6831d599ad17ca2fc9868d2fb52f4e5362dfbfaf379", +                "sha256:26dfeee23a86dad6277a63d18f61f53b957cb2cd3506dbbd74b88ba2fa65b3b1", +                "sha256:2e0e582942e025cc58f669499a8e0bffde5bcc8d42b65729f294c1dac54e4672", +                "sha256:3bb8dd3ce101dd8b0b37eaae924a5bb93abb6ffdd034bf68a066a808e11768ab", +                "sha256:3f07da3874f0b085421f1d4f979785131aa9d497501d8610d82f7378b33858f8", +                "sha256:429b2b5ae5f57f8fd9ec2e012c1e7b342ff10f1a8977dc291976b9a3b4c096e1", +                "sha256:4a000fdd89d77b6b675de27e1ab91c6fba517c08f19ee83e6716b78930634e04", +                "sha256:4ccbe7cce6156391a3ecf447c79a7d4a1a0ecd3de79bdec9ca5e4f7242a306d1", +                "sha256:4d08034196db41acb7392e4fccfc0448e7a87192c41d3011ad4093eac2c31ffd", +                "sha256:6b202b1cb524bc76ed52a7eb0314f4b0a0497c7cceb9a93539b5a25800e1f2b6", +                "sha256:8563b56fa7c34f1606848c2143ea67d27cf225b9726a1b041c3d27cf85e46edc", +                "sha256:86d7421e8803d7bae2e594765c378a867b629d46b32fbfe5ed9fd95b30989feb", +                "sha256:8d4bddedcb4ab99131d9705a75720efc48b3d006122dae1a4cc329496ac47c9a", +                "sha256:a4929c6de9590635c34533609402c9da12b22bfc2feb8c0c4f38c39bab48a9ad", +                "sha256:b0736e21798448cee3e663c0df7a6dfa83d805b3f3a45e67f7457a2f019e5fca", +                "sha256:b669acba91d47395de84c9ca52a7ad393b487e5ae2e20b9b2790b22a57d479fa", +                "sha256:bba993443921f2d077195b425a3283357f52b07807d53704610c1249d20b183a", +                "sha256:bdf706a93d00547c9443b2654ae424fd54d5dece4bc4333e7035740aeb7a7cea", +                "sha256:c5aa93e55175b9cde95279ccd03c93d218976b376480222d37be41d2c9c54510", +                "sha256:cc11fd997d8ad71bb0412e983b711e49639c2ddba9b9dce04d4bdab575fe5f84", +                "sha256:d584f1c33995c3dc16a35e30ef43e0881fa0d085f0fef29cebf154ffb5643363", +                "sha256:d88f54bdefb7ddccb68efdd710d689aa6a09b875cc3e44b7e81ef54e0751e3a7", +                "sha256:de0d323072be72fa4d74f4e013cd594e3f8ee03b2e0eac5876a3249fa076ef7b", +                "sha256:f139c963c6679d236b2c45369524338eabd36a853fe23abd39ba246ab0a75aec", +                "sha256:f41c0bf667c4c1c30b873eaa8d6bb894f6d721b3e38e9c993bddd1263c02fb1f", +                "sha256:fbd0ea468b4ec04270533bf5206f1cd57746fcf226520bb133318fa276de2644", +                "sha256:fe2d2850521c467c915ff0a6e27dc64c3c04c2f66612e0072672bd1bd4854b61"              ],              "index": "pypi", -            "version": "==5.3.0" +            "version": "==5.4.0"          },          "pycares": {              "hashes": [ -                "sha256:0e81c971236bb0767354f1456e67ab6ae305f248565ce77cd413a311f9572bf5", -                "sha256:11c0ff3ccdb5a838cbd59a4e59df35d31355a80a61393bca786ca3b44569ba10", -                "sha256:170d62bd300999227e64da4fa85459728cc96e62e44780bbc86a915fdae01f78", -                "sha256:36f4c03df57c41a87eb3d642201684eb5a8bc194f4bafaa9f60ee6dc0aef8e40", -                "sha256:371ce688776da984c4105c8ca760cc60944b9b49ccf8335c71dc7669335e6173", -                "sha256:3a2234516f7db495083d8bba0ccdaabae587e62cfcd1b8154d5d0b09d3a48dfc", -                "sha256:3f288586592c697109b2b06e3988b7e17d9765887b5fc367010ee8500cbddc86", -                "sha256:40134cee03c8bbfbc644d4c0bc81796e12dd012a5257fb146c5a5417812ee5f7", -                "sha256:722f5d2c5f78d47b13b0112f6daff43ce4e08e8152319524d14f1f917cc5125e", -                "sha256:7b18fab0ed534a898552df91bc804bd62bb3a2646c11e054baca14d23663e1d6", -                "sha256:8a39d03bd99ea191f86b990ef67ecce878d6bf6518c5cde9173fb34fb36beb5e", -                "sha256:8ea263de8bf1a30b0d87150b4aa0e3203cf93bc1723ea3e7408a7d25e1299217", -                "sha256:943e2dc67ff45ab4c81d628c959837d01561d7e185080ab7a276b8ca67573fb5", -                "sha256:9d56a54c93e64b30c0d31f394d9890f175edec029cd846221728f99263cdee82", -                "sha256:b95b339c11d824f0bb789d31b91c8534916fcbdce248cccce216fa2630bb8a90", -                "sha256:bbfd9aba1e172cd2ab7b7142d49b28cf44d6451c4a66a870aff1dc3cb84849c7", -                "sha256:d8637bcc2f901aa61ec1d754abc862f9f145cb0346a0249360df4c159377018e", -                "sha256:e2446577eeea79d2179c9469d9d4ce3ab8a07d7985465c3cb91e7d74abc329b6", -                "sha256:e72fa163f37ae3b09f143cc6690a36f012d13e905d142e1beed4ec0e593ff657", -                "sha256:f32b7c63094749fbc0c1106c9a785666ec8afd49ecfe7002a30bb7c42e62b47c", -                "sha256:f50be4dd53f009cfb4b98c3c6b240e18ff9b17e3f1c320bd594bb83eddabfcb2" +                "sha256:080ae0f1b1b754be60b6ef31b9ab2915364c210eb1cb4d8e089357c89d7b9819", +                "sha256:0eccb76dff0155ddf793a589c6270e1bdbf6975b2824d18d1d23db2075d7fc96", +                "sha256:223a03d69e864a18d7bb2e0108bca5ba069ef91e5b048b953ed90ea9f50eb77f", +                "sha256:289e49f98adfd7a2ae3656df26e1d62cf49a06bbc03ced63f243c22cd8919adf", +                "sha256:292ac442a1d4ff27d41be748ec19f0c4ff47efebfb715064ba336564ea0f2071", +                "sha256:34771095123da0e54597fe3c5585a28d3799945257e51b378a20778bf33573b6", +                "sha256:34c8865f2d047be4c301ce90a916c7748be597e271c5c7932e8b9a6de85840f4", +                "sha256:36af260b215f86ebfe4a5e4aea82fd6036168a5710cbf8aad77019ab52156dda", +                "sha256:5e8e2a461717da40482b5fecf1119116234922d29660b3c3e01cbc5ba2cbf4bd", +                "sha256:61e77bd75542c56dff49434fedbafb25604997bc57dc0ebf791a5732503cb1bb", +                "sha256:691740c332f38a9035b4c6d1f0e6c8af239466ef2373a894d4393f0ea65c815d", +                "sha256:6bc0e0fdcb4cdc4ca06aa0b07e6e3560d62b2af79ef0ea4589835fcd2059012b", +                "sha256:96db5c93e2fe2e39f519efb7bb9d86aef56f5813fa0b032e47aba329fa925d57", +                "sha256:af701b22c91b3e36f65ee9f4b1bc2fe4800c8ed486eb6ef203624acbe53d026d", +                "sha256:b25bd21bba9c43d44320b719118c2ce35e4a78031f61d906caeb01316d49dafb", +                "sha256:c42f68319f8ea2322ed81c31a86c4e60547e6e90f3ebef479a7a7540bddbf268", +                "sha256:cc9a8d35af12bc5f484f3496f9cb3ab5bedfa4dcf3dfff953099453d88b659a7", +                "sha256:dfee9d198ba6d6f29aa5bf510bfb2c28a60c3f308116f114c9fd311980d3e870", +                "sha256:e1dd02e110a7a97582097ebba6713d9da28583b538c08e8a14bc82169c5d3e10", +                "sha256:e48c586c80a139c6c7fb0298b944d1c40752cf839bc8584cc793e42a8971ba6c", +                "sha256:f509762dec1a70eac32b86c098f37ac9c5d3d4a8a9098983328377c9e71543b2", +                "sha256:f8e0d61733843844f9019c911d5676818d99c4cd2c54b91de58384c7d962862b", +                "sha256:fe20280fed496deba60e0f6437b7672bdc83bf45e243bb546af47c60c85bcfbc"              ], -            "version": "==2.3.0" +            "version": "==2.4.0"          },          "pycparser": {              "hashes": [ -                "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3" +                "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3", +                "sha256:db32bd592ba104f8fbb8047c18cd897f0f20d0909ba0ec5dc72a3221f6a82e15"              ],              "version": "==2.19"          },          "pygments": {              "hashes": [ -                "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", -                "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" +                "sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", +                "sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d"              ], -            "version": "==2.2.0" +            "version": "==2.3.1"          },          "pynacl": {              "hashes": [ @@ -505,11 +502,11 @@          },          "requests": {              "hashes": [ -                "sha256:65b3a120e4329e33c9889db89c80976c5272f56ea92d3e74da8a463992e3ff54", -                "sha256:ea881206e59f41dbd0bd445437d792e43906703fff75ca8ff43ccdb11f33f263" +                "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", +                "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"              ],              "index": "pypi", -            "version": "==2.20.1" +            "version": "==2.21.0"          },          "shortuuid": {              "hashes": [ @@ -519,10 +516,10 @@          },          "six": {              "hashes": [ -                "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", -                "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" +                "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", +                "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"              ], -            "version": "==1.11.0" +            "version": "==1.12.0"          },          "snowballstemmer": {              "hashes": [ @@ -531,13 +528,20 @@              ],              "version": "==1.2.1"          }, +        "soupsieve": { +            "hashes": [ +                "sha256:057e08f362a255b457a5781675211556799ed3bb8807506eaac3809390bc304b", +                "sha256:f7d99b41637be2f249dfcc06ae93c13fcbbdfa7bb68b15308cdd0734e58146f1" +            ], +            "version": "==1.6.1" +        },          "sphinx": {              "hashes": [ -                "sha256:120732cbddb1b2364471c3d9f8bfd4b0c5b550862f99a65736c77f970b142aea", -                "sha256:b348790776490894e0424101af9c8413f2a86831524bd55c5f379d3e3e12ca64" +                "sha256:429e3172466df289f0f742471d7e30ba3ee11f3b5aecd9a840480d03f14bcfe5", +                "sha256:c4cb17ba44acffae3d3209646b6baec1e215cad3065e852c68cc569d4df1b9f8"              ],              "index": "pypi", -            "version": "==1.8.2" +            "version": "==1.8.3"          },          "sphinxcontrib-websupport": {              "hashes": [ @@ -581,20 +585,29 @@          },          "yarl": {              "hashes": [ -                "sha256:2556b779125621b311844a072e0ed367e8409a18fa12cbd68eb1258d187820f9", -                "sha256:4aec0769f1799a9d4496827292c02a7b1f75c0bab56ab2b60dd94ebb57cbd5ee", -                "sha256:55369d95afaacf2fa6b49c84d18b51f1704a6560c432a0f9a1aeb23f7b971308", -                "sha256:6c098b85442c8fe3303e708bbb775afd0f6b29f77612e8892627bcab4b939357", -                "sha256:9182cd6f93412d32e009020a44d6d170d2093646464a88aeec2aef50592f8c78", -                "sha256:c8cbc21bbfa1dd7d5386d48cc814fe3d35b80f60299cdde9279046f399c3b0d8", -                "sha256:db6f70a4b09cde813a4807843abaaa60f3b15fb4a2a06f9ae9c311472662daa1", -                "sha256:f17495e6fe3d377e3faac68121caef6f974fcb9e046bc075bcff40d8e5cc69a4", -                "sha256:f85900b9cca0c67767bb61b2b9bd53208aaa7373dae633dbe25d179b4bf38aa7" -            ], -            "version": "==1.2.6" +                "sha256:024ecdc12bc02b321bc66b41327f930d1c2c543fa9a561b39861da9388ba7aa9", +                "sha256:2f3010703295fbe1aec51023740871e64bb9664c789cba5a6bdf404e93f7568f", +                "sha256:3890ab952d508523ef4881457c4099056546593fa05e93da84c7250516e632eb", +                "sha256:3e2724eb9af5dc41648e5bb304fcf4891adc33258c6e14e2a7414ea32541e320", +                "sha256:5badb97dd0abf26623a9982cd448ff12cb39b8e4c94032ccdedf22ce01a64842", +                "sha256:73f447d11b530d860ca1e6b582f947688286ad16ca42256413083d13f260b7a0", +                "sha256:7ab825726f2940c16d92aaec7d204cfc34ac26c0040da727cf8ba87255a33829", +                "sha256:b25de84a8c20540531526dfbb0e2d2b648c13fd5dd126728c496d7c3fea33310", +                "sha256:c6e341f5a6562af74ba55205dbd56d248daf1b5748ec48a0200ba227bb9e33f4", +                "sha256:c9bb7c249c4432cd47e75af3864bc02d26c9594f49c82e2a28624417f0ae63b8", +                "sha256:e060906c0c585565c718d1c3841747b61c5439af2211e185f6739a9412dfbde1" +            ], +            "version": "==1.3.0"          }      },      "develop": { +        "aspy.yaml": { +            "hashes": [ +                "sha256:04d26279513618f1024e1aba46471db870b3b33aef204c2d09bcf93bea9ba13f", +                "sha256:0a77e23fafe7b242068ffc0252cee130d3e509040908fc678d9d1060e7494baa" +            ], +            "version": "==1.1.1" +        },          "attrs": {              "hashes": [                  "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", @@ -602,12 +615,26 @@              ],              "version": "==18.2.0"          }, +        "cached-property": { +            "hashes": [ +                "sha256:3a026f1a54135677e7da5ce819b0c690f156f37976f3e30c5430740725203d7f", +                "sha256:9217a59f14a5682da7c4b8829deadbfc194ac22e9908ccf7c8820234e80a1504" +            ], +            "version": "==1.5.1" +        },          "certifi": {              "hashes": [ -                "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", -                "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" +                "sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7", +                "sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033"              ], -            "version": "==2018.10.15" +            "version": "==2018.11.29" +        }, +        "cfgv": { +            "hashes": [ +                "sha256:73f48a752bd7aab103c4b882d6596c6360b7aa63b34073dd2c35c7b4b8f93010", +                "sha256:d1791caa9ff5c0c7bce80e7ecc1921752a2eb7c2463a08ed9b6c96b85a2f75aa" +            ], +            "version": "==1.1.0"          },          "chardet": {              "hashes": [ @@ -684,12 +711,26 @@              "index": "pypi",              "version": "==0.7"          }, +        "identify": { +            "hashes": [ +                "sha256:08826e68e39e7de53cc2ddd8f6228a4e463b4bacb20565e5301c3ec690e68d27", +                "sha256:2364e24a7699fea0dc910e90740adbab43eef3746eeea4e016029c34123ce66d" +            ], +            "version": "==1.1.8" +        },          "idna": {              "hashes": [ -                "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", -                "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" +                "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", +                "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" +            ], +            "version": "==2.8" +        }, +        "importlib-metadata": { +            "hashes": [ +                "sha256:a17ce1a8c7bff1e8674cb12c992375d8d0800c9190177ecf0ad93e0097224095", +                "sha256:b50191ead8c70adfa12495fba19ce6d75f2e0275c14c5a7beb653d6799b512bd"              ], -            "version": "==2.7" +            "version": "==0.8"          },          "mccabe": {              "hashes": [ @@ -698,6 +739,12 @@              ],              "version": "==0.6.1"          }, +        "nodeenv": { +            "hashes": [ +                "sha256:ad8259494cf1c9034539f6cced78a1da4840a4b157e23640bc4a0c0546b0cb7a" +            ], +            "version": "==1.3.3" +        },          "packaging": {              "hashes": [                  "sha256:0886227f54515e592aaa2e5a553332c73962917f2831f1b0f9b9f4380a4b9807", @@ -705,6 +752,14 @@              ],              "version": "==18.0"          }, +        "pre-commit": { +            "hashes": [ +                "sha256:33bb9bf599c334d458fa9e311bde54e0c306a651473b6a36fdb36a61c8605c89", +                "sha256:e233f5cf3230ae9ed9ada132e9cf6890e18cc937adc669353fb64394f6e80c17" +            ], +            "index": "pypi", +            "version": "==1.13.0" +        },          "pycodestyle": {              "hashes": [                  "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", @@ -745,11 +800,11 @@          },          "requests": {              "hashes": [ -                "sha256:65b3a120e4329e33c9889db89c80976c5272f56ea92d3e74da8a463992e3ff54", -                "sha256:ea881206e59f41dbd0bd445437d792e43906703fff75ca8ff43ccdb11f33f263" +                "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", +                "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"              ],              "index": "pypi", -            "version": "==2.20.1" +            "version": "==2.21.0"          },          "safety": {              "hashes": [ @@ -761,10 +816,17 @@          },          "six": {              "hashes": [ -                "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", -                "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" +                "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", +                "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"              ], -            "version": "==1.11.0" +            "version": "==1.12.0" +        }, +        "toml": { +            "hashes": [ +                "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", +                "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" +            ], +            "version": "==0.10.0"          },          "urllib3": {              "hashes": [ @@ -772,6 +834,19 @@                  "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"              ],              "version": "==1.24.1" +        }, +        "virtualenv": { +            "hashes": [ +                "sha256:34b9ae3742abed2f95d3970acf4d80533261d6061b51160b197f84e5b4c98b4c" +            ], +            "version": "==16.2.0" +        }, +        "zipp": { +            "hashes": [ +                "sha256:55ca87266c38af6658b84db8cfb7343cdb0bf275f93c7afaea0d8e7a209c7478", +                "sha256:682b3e1c62b7026afe24eadf6be579fb45fec54c07ea218bded8092af07a68c4" +            ], +            "version": "==0.3.3"          }      }  } diff --git a/bot/cogs/bot.py b/bot/cogs/bot.py index b684ad886..a6d9aa278 100644 --- a/bot/cogs/bot.py +++ b/bot/cogs/bot.py @@ -372,7 +372,7 @@ class Bot:              return          # Retrieve channel and message objects for use later -        channel = self.bot.get_channel(payload.data.get("channel_id")) +        channel = self.bot.get_channel(int(payload.data.get("channel_id")))          user_message = await channel.get_message(payload.message_id)          #  Checks to see if the user has corrected their codeblock.  If it's fixed, has_fixed_codeblock will be None @@ -383,6 +383,7 @@ class Bot:              bot_message = await channel.get_message(self.codeblock_message_ids[payload.message_id])              await bot_message.delete()              del self.codeblock_message_ids[payload.message_id] +            log.trace("User's incorrect code block has been fixed.  Removing bot formatting message.")  def setup(bot): diff --git a/bot/cogs/defcon.py b/bot/cogs/defcon.py index c432d377c..f07d9df9f 100644 --- a/bot/cogs/defcon.py +++ b/bot/cogs/defcon.py @@ -5,14 +5,11 @@ from discord import Colour, Embed, Member  from discord.ext.commands import Bot, Context, group  from bot.cogs.modlog import ModLog -from bot.constants import Channels, Emojis, Icons, Keys, Roles, URLs +from bot.constants import Channels, Colours, Emojis, Event, Icons, Keys, Roles, URLs  from bot.decorators import with_role  log = logging.getLogger(__name__) -COLOUR_RED = Colour(0xcd6d6d) -COLOUR_GREEN = Colour(0x68c290) -  REJECTION_MESSAGE = """  Hi, {user} - Thanks for your interest in our server! @@ -24,6 +21,8 @@ will be resolved soon. In the meantime, please feel free to peruse the resources  <https://pythondiscord.com/>, and have a nice day!  """ +BASE_CHANNEL_TOPIC = "Python Discord Defense Mechanism" +  class Defcon:      """Time-sensitive server defense mechanisms""" @@ -66,6 +65,8 @@ class Defcon:                  self.days = timedelta(days=0)                  log.warning(f"DEFCON disabled") +            await self.update_channel_topic() +      async def on_member_join(self, member: Member):          if self.enabled and self.days.days > 0:              now = datetime.utcnow() @@ -93,7 +94,7 @@ class Defcon:                      message = f"{message}\n\nUnable to send rejection message via DM; they probably have DMs disabled."                  await self.mod_log.send_log_message( -                    Icons.defcon_denied, COLOUR_RED, "Entry denied", +                    Icons.defcon_denied, Colours.soft_red, "Entry denied",                      message, member.avatar_url_as(static_format="png")                  ) @@ -134,7 +135,7 @@ class Defcon:              )              await self.mod_log.send_log_message( -                Icons.defcon_enabled, COLOUR_GREEN, "DEFCON enabled", +                Icons.defcon_enabled, Colours.soft_green, "DEFCON enabled",                  f"**Staffer:** {ctx.author.name}#{ctx.author.discriminator} (`{ctx.author.id}`)\n"                  f"**Days:** {self.days.days}\n\n"                  "**There was a problem updating the site** - This setting may be reverted when the bot is " @@ -145,11 +146,13 @@ class Defcon:              await ctx.send(f"{Emojis.defcon_enabled} DEFCON enabled.")              await self.mod_log.send_log_message( -                Icons.defcon_enabled, COLOUR_GREEN, "DEFCON enabled", +                Icons.defcon_enabled, Colours.soft_green, "DEFCON enabled",                  f"**Staffer:** {ctx.author.name}#{ctx.author.discriminator} (`{ctx.author.id}`)\n"                  f"**Days:** {self.days.days}\n\n"              ) +        await self.update_channel_topic() +      @defcon_group.command(name='disable', aliases=('off', 'd'))      @with_role(Roles.admin, Roles.owner)      async def disable_command(self, ctx: Context): @@ -177,7 +180,7 @@ class Defcon:              )              await self.mod_log.send_log_message( -                Icons.defcon_disabled, COLOUR_RED, "DEFCON disabled", +                Icons.defcon_disabled, Colours.soft_red, "DEFCON disabled",                  f"**Staffer:** {ctx.author.name}#{ctx.author.discriminator} (`{ctx.author.id}`)\n"                  "**There was a problem updating the site** - This setting may be reverted when the bot is "                  "restarted.\n\n" @@ -187,10 +190,12 @@ class Defcon:              await ctx.send(f"{Emojis.defcon_disabled} DEFCON disabled.")              await self.mod_log.send_log_message( -                Icons.defcon_disabled, COLOUR_RED, "DEFCON disabled", +                Icons.defcon_disabled, Colours.soft_red, "DEFCON disabled",                  f"**Staffer:** {ctx.author.name}#{ctx.author.discriminator} (`{ctx.author.id}`)"              ) +        await self.update_channel_topic() +      @defcon_group.command(name='status', aliases=('s',))      @with_role(Roles.admin, Roles.owner)      async def status_command(self, ctx: Context): @@ -252,6 +257,23 @@ class Defcon:                  f"**Days:** {self.days.days}"              ) +        await self.update_channel_topic() + +    async def update_channel_topic(self): +        """ +        Update the #defcon channel topic with the current DEFCON status +        """ + +        if self.enabled: +            day_str = "days" if self.days.days > 1 else "day" +            new_topic = f"{BASE_CHANNEL_TOPIC}\n(Status: Enabled, Threshold: {self.days.days} {day_str})" +        else: +            new_topic = f"{BASE_CHANNEL_TOPIC}\n(Status: Disabled)" + +        self.mod_log.ignore(Event.guild_channel_update, Channels.defcon) +        defcon_channel = self.bot.guilds[0].get_channel(Channels.defcon) +        await defcon_channel.edit(topic=new_topic) +  def setup(bot: Bot):      bot.add_cog(Defcon(bot)) diff --git a/bot/cogs/eval.py b/bot/cogs/eval.py index 9e09b3aa0..8e97a35a2 100644 --- a/bot/cogs/eval.py +++ b/bot/cogs/eval.py @@ -68,7 +68,7 @@ class CodeEval:                  # then we get the length                  # and use `str.rjust()`                  # to indent it. -                start = "...:".rjust(len(self.ln) + 2) +                start = "...: ".rjust(len(str(self.ln)) + 7)              if i == len(lines) - 2:                  if line.startswith("return"): diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 0ba1e49c5..247ee26b8 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -1,7 +1,8 @@  import logging  import re -from discord import Colour, Member, Message +import discord.errors +from discord import Colour, DMChannel, Member, Message, TextChannel  from discord.ext.commands import Bot  from bot.cogs.modlog import ModLog @@ -38,31 +39,46 @@ class Filtering:      def __init__(self, bot: Bot):          self.bot = bot +        _staff_mistake_str = "If you believe this was a mistake, please let staff know!"          self.filters = {              "filter_zalgo": {                  "enabled": Filter.filter_zalgo,                  "function": self._has_zalgo, -                "type": "filter" +                "type": "filter", +                "user_notification": Filter.notify_user_zalgo, +                "notification_msg": ( +                    "Your post has been removed for abusing Unicode character rendering (aka Zalgo text). " +                    f"{_staff_mistake_str}" +                )              },              "filter_invites": {                  "enabled": Filter.filter_invites,                  "function": self._has_invites, -                "type": "filter" +                "type": "filter", +                "user_notification": Filter.notify_user_invites, +                "notification_msg": ( +                    f"Per Rule 10, your invite link has been removed. {_staff_mistake_str}\n\n" +                    r"Our server rules can be found here: <https://pythondiscord.com/about/rules>" +                )              },              "filter_domains": {                  "enabled": Filter.filter_domains,                  "function": self._has_urls, -                "type": "filter" +                "type": "filter", +                "user_notification": Filter.notify_user_domains, +                "notification_msg": ( +                    f"Your URL has been removed because it matched a blacklisted domain. {_staff_mistake_str}" +                )              },              "watch_words": {                  "enabled": Filter.watch_words,                  "function": self._has_watchlist_words, -                "type": "watchlist" +                "type": "watchlist",              },              "watch_tokens": {                  "enabled": Filter.watch_tokens,                  "function": self._has_watchlist_tokens, -                "type": "watchlist" +                "type": "watchlist",              },          } @@ -111,10 +127,15 @@ class Filtering:                      triggered = await _filter["function"](msg.content)                      if triggered: +                        if isinstance(msg.channel, DMChannel): +                            channel_str = "via DM" +                        else: +                            channel_str = f"in {msg.channel.mention}" +                          message = (                              f"The {filter_name} {_filter['type']} was triggered "                              f"by **{msg.author.name}#{msg.author.discriminator}** " -                            f"(`{msg.author.id}`) in <#{msg.channel.id}> with [the " +                            f"(`{msg.author.id}`) {channel_str} with [the "                              f"following message]({msg.jump_url}):\n\n"                              f"{msg.content}"                          ) @@ -136,6 +157,10 @@ class Filtering:                          if _filter["type"] == "filter":                              await msg.delete() +                            # Notify the user if the filter specifies +                            if _filter["user_notification"]: +                                await self.notify_member(msg.author, _filter["notification_msg"], msg.channel) +                          break  # We don't want multiple filters to trigger      @staticmethod @@ -217,16 +242,12 @@ class Filtering:      async def _has_invites(self, text: str) -> bool:          """ -        Returns True if the text contains an invite which -        is not on the guild_invite_whitelist in config.yml. +        Returns True if the text contains an invite which is not on the guild_invite_whitelist in +        config.yml -        Also catches a lot of common ways to try to cheat the system. +        Attempts to catch some of common ways to try to cheat the system.          """ -        # Remove spaces to prevent cases like -        # d i s c o r d . c o m / i n v i t e / s e x y t e e n s -        text = text.replace(" ", "") -          # Remove backslashes to prevent escape character aroundfuckery like          # discord\.gg/gdudes-pony-farm          text = text.replace("\\", "") @@ -240,8 +261,9 @@ class Filtering:              response = await response.json()              guild = response.get("guild")              if guild is None: -                # We don't have whitelisted Group DMs so we can -                # go ahead and return a positive for any group DM +                # Lack of a "guild" key in the JSON response indicates either an group DM invite, an +                # expired invite, or an invalid invite. The API does not currently differentiate +                # between invalid and expired invites                  return True              guild_id = int(guild.get("id")) @@ -250,6 +272,18 @@ class Filtering:                  return True          return False +    async def notify_member(self, filtered_member: Member, reason: str, channel: TextChannel): +        """ +        Notify filtered_member about a moderation action with the reason str + +        First attempts to DM the user, fall back to in-channel notification if user has DMs disabled +        """ + +        try: +            await filtered_member.send(reason) +        except discord.errors.Forbidden: +            await channel.send(f"{filtered_member.mention} {reason}") +  def setup(bot: Bot):      bot.add_cog(Filtering(bot)) diff --git a/bot/cogs/moderation.py b/bot/cogs/moderation.py index 6e958b912..ac08d3dd4 100644 --- a/bot/cogs/moderation.py +++ b/bot/cogs/moderation.py @@ -82,7 +82,7 @@ class Moderation(Scheduler):          :param reason: The reason for the warning.          """ -        await self.notify_infraction( +        notified = await self.notify_infraction(              user=user,              infr_type="Warning",              reason=reason @@ -92,12 +92,29 @@ class Moderation(Scheduler):          if response_object is None:              return +        dm_result = ":incoming_envelope: " if notified else "" +        action = f"{dm_result}:ok_hand: warned {user.mention}" +          if reason is None: -            result_message = f":ok_hand: warned {user.mention}." +            await ctx.send(f"{action}.")          else: -            result_message = f":ok_hand: warned {user.mention} ({reason})." +            await ctx.send(f"{action} ({reason}).") -        await ctx.send(result_message) +        if not notified: +            await self.log_notify_failure(user, ctx.author, "warning") + +        # Send a message to the mod log +        await self.mod_log.send_log_message( +            icon_url=Icons.user_warn, +            colour=Colour(Colours.soft_red), +            title="Member warned", +            thumbnail=user.avatar_url_as(static_format="png"), +            text=textwrap.dedent(f""" +                Member: {user.mention} (`{user.id}`) +                Actor: {ctx.message.author} +                Reason: {reason} +            """) +        )      @with_role(*MODERATION_ROLES)      @command(name="kick") @@ -108,7 +125,7 @@ class Moderation(Scheduler):          :param reason: The reason for the kick.          """ -        await self.notify_infraction( +        notified = await self.notify_infraction(              user=user,              infr_type="Kick",              reason=reason @@ -121,12 +138,16 @@ class Moderation(Scheduler):          self.mod_log.ignore(Event.member_remove, user.id)          await user.kick(reason=reason) +        dm_result = ":incoming_envelope: " if notified else "" +        action = f"{dm_result}:ok_hand: kicked {user.mention}" +          if reason is None: -            result_message = f":ok_hand: kicked {user.mention}." +            await ctx.send(f"{action}.")          else: -            result_message = f":ok_hand: kicked {user.mention} ({reason})." +            await ctx.send(f"{action} ({reason}).") -        await ctx.send(result_message) +        if not notified: +            await self.log_notify_failure(user, ctx.author, "kick")          # Send a log message to the mod log          await self.mod_log.send_log_message( @@ -150,7 +171,7 @@ class Moderation(Scheduler):          :param reason: The reason for the ban.          """ -        await self.notify_infraction( +        notified = await self.notify_infraction(              user=user,              infr_type="Ban",              duration="Permanent", @@ -165,12 +186,16 @@ class Moderation(Scheduler):          self.mod_log.ignore(Event.member_remove, user.id)          await ctx.guild.ban(user, reason=reason, delete_message_days=0) +        dm_result = ":incoming_envelope: " if notified else "" +        action = f"{dm_result}:ok_hand: permanently banned {user.mention}" +          if reason is None: -            result_message = f":ok_hand: permanently banned {user.mention}." +            await ctx.send(f"{action}.")          else: -            result_message = f":ok_hand: permanently banned {user.mention} ({reason})." +            await ctx.send(f"{action} ({reason}).") -        await ctx.send(result_message) +        if not notified: +            await self.log_notify_failure(user, ctx.author, "ban")          # Send a log message to the mod log          await self.mod_log.send_log_message( @@ -194,7 +219,7 @@ class Moderation(Scheduler):          :param reason: The reason for the mute.          """ -        await self.notify_infraction( +        notified = await self.notify_infraction(              user=user,              infr_type="Mute",              duration="Permanent", @@ -209,12 +234,16 @@ class Moderation(Scheduler):          self.mod_log.ignore(Event.member_update, user.id)          await user.add_roles(self._muted_role, reason=reason) +        dm_result = ":incoming_envelope: " if notified else "" +        action = f"{dm_result}:ok_hand: permanently muted {user.mention}" +          if reason is None: -            result_message = f":ok_hand: permanently muted {user.mention}." +            await ctx.send(f"{action}.")          else: -            result_message = f":ok_hand: permanently muted {user.mention} ({reason})." +            await ctx.send(f"{action} ({reason}).") -        await ctx.send(result_message) +        if not notified: +            await self.log_notify_failure(user, ctx.author, "mute")          # Send a log message to the mod log          await self.mod_log.send_log_message( @@ -242,7 +271,7 @@ class Moderation(Scheduler):          :param reason: The reason for the temporary mute.          """ -        await self.notify_infraction( +        notified = await self.notify_infraction(              user=user,              infr_type="Mute",              duration=duration, @@ -262,12 +291,16 @@ class Moderation(Scheduler):          loop = asyncio.get_event_loop()          self.schedule_task(loop, infraction_object["id"], infraction_object) +        dm_result = ":incoming_envelope: " if notified else "" +        action = f"{dm_result}:ok_hand: muted {user.mention} until {infraction_expiration}" +          if reason is None: -            result_message = f":ok_hand: muted {user.mention} until {infraction_expiration}." +            await ctx.send(f"{action}.")          else: -            result_message = f":ok_hand: muted {user.mention} until {infraction_expiration} ({reason})." +            await ctx.send(f"{action} ({reason}).") -        await ctx.send(result_message) +        if not notified: +            await self.log_notify_failure(user, ctx.author, "mute")          # Send a log message to the mod log          await self.mod_log.send_log_message( @@ -294,7 +327,7 @@ class Moderation(Scheduler):          :param reason: The reason for the temporary ban.          """ -        await self.notify_infraction( +        notified = await self.notify_infraction(              user=user,              infr_type="Ban",              duration=duration, @@ -316,12 +349,16 @@ class Moderation(Scheduler):          loop = asyncio.get_event_loop()          self.schedule_task(loop, infraction_object["id"], infraction_object) +        dm_result = ":incoming_envelope: " if notified else "" +        action = f"{dm_result}:ok_hand: banned {user.mention} until {infraction_expiration}" +          if reason is None: -            result_message = f":ok_hand: banned {user.mention} until {infraction_expiration}." +            await ctx.send(f"{action}.")          else: -            result_message = f":ok_hand: banned {user.mention} until {infraction_expiration} ({reason})." +            await ctx.send(f"{action} ({reason}).") -        await ctx.send(result_message) +        if not notified: +            await self.log_notify_failure(user, ctx.author, "ban")          # Send a log message to the mod log          await self.mod_log.send_log_message( @@ -361,6 +398,19 @@ class Moderation(Scheduler):          await ctx.send(result_message) +        # Send a message to the mod log +        await self.mod_log.send_log_message( +            icon_url=Icons.user_warn, +            colour=Colour(Colours.soft_red), +            title="Member shadow warned", +            thumbnail=user.avatar_url_as(static_format="png"), +            text=textwrap.dedent(f""" +                Member: {user.mention} (`{user.id}`) +                Actor: {ctx.message.author} +                Reason: {reason} +            """) +        ) +      @with_role(*MODERATION_ROLES)      @command(name="shadow_kick", hidden=True, aliases=['shadowkick', 'skick'])      async def shadow_kick(self, ctx: Context, user: Member, *, reason: str = None): @@ -603,7 +653,18 @@ class Moderation(Scheduler):              if infraction_object["expires_at"] is not None:                  self.cancel_expiration(infraction_object["id"]) -            await ctx.send(f":ok_hand: Un-muted {user.mention}.") +            notified = await self.notify_pardon( +                user=user, +                title="You have been unmuted.", +                content="You may now send messages in the server.", +                icon_url=Icons.user_unmute +            ) + +            dm_result = ":incoming_envelope: " if notified else "" +            await ctx.send(f"{dm_result}:ok_hand: Un-muted {user.mention}.") + +            if not notified: +                await self.log_notify_failure(user, ctx.author, "unmute")              # Send a log message to the mod log              await self.mod_log.send_log_message( @@ -617,13 +678,6 @@ class Moderation(Scheduler):                      Intended expiry: {infraction_object['expires_at']}                  """)              ) - -            await self.notify_pardon( -                user=user, -                title="You have been unmuted.", -                content="You may now send messages in the server.", -                icon_url=Icons.user_unmute -            )          except Exception:              log.exception("There was an error removing an infraction.")              await ctx.send(":x: There was an error removing the infraction.") @@ -1093,7 +1147,7 @@ class Moderation(Scheduler):          embed.title = f"Please review our rules over at {RULES_URL}"          embed.url = RULES_URL -        await self.send_private_embed(user, embed) +        return await self.send_private_embed(user, embed)      async def notify_pardon(              self, user: Union[User, Member], title: str, content: str, icon_url: str = Icons.user_verified @@ -1114,7 +1168,7 @@ class Moderation(Scheduler):          embed.set_author(name=title, icon_url=icon_url) -        await self.send_private_embed(user, embed) +        return await self.send_private_embed(user, embed)      async def send_private_embed(self, user: Union[User, Member], embed: Embed):          """ @@ -1129,11 +1183,22 @@ class Moderation(Scheduler):          try:              await user.send(embed=embed) +            return True          except (HTTPException, Forbidden):              log.debug(                  f"Infraction-related information could not be sent to user {user} ({user.id}). "                  "They've probably just disabled private messages."              ) +            return False + +    async def log_notify_failure(self, target: str, actor: Member, infraction_type: str): +        await self.mod_log.send_log_message( +            icon_url=Icons.token_removed, +            content=actor.mention, +            colour=Colour(Colours.soft_red), +            title="Notification Failed", +            text=f"Direct message was unable to be sent.\nUser: {target.mention}\nType: {infraction_type}" +        )      # endregion diff --git a/bot/cogs/modlog.py b/bot/cogs/modlog.py index ef4544f81..f36c431e6 100644 --- a/bot/cogs/modlog.py +++ b/bot/cogs/modlog.py @@ -104,8 +104,9 @@ class ModLog:                  self._ignored[event].append(item)      async def send_log_message( -            self, icon_url: Optional[str], colour: Colour, title: Optional[str], text: str, thumbnail: str = None, -            channel_id: int = Channels.modlog, ping_everyone: bool = False, files: List[File] = None +            self, icon_url: Optional[str], colour: Colour, title: Optional[str], text: str, +            thumbnail: str = None, channel_id: int = Channels.modlog, ping_everyone: bool = False, +            files: List[File] = None, content: str = None      ):          embed = Embed(description=text) @@ -118,10 +119,11 @@ class ModLog:          if thumbnail is not None:              embed.set_thumbnail(url=thumbnail) -        content = None -          if ping_everyone: -            content = "@everyone" +            if content: +                content = f"@everyone\n{content}" +            else: +                content = "@everyone"          log_message = await self.bot.get_channel(channel_id).send(content=content, embed=embed, files=files)          return self.bot.get_context(log_message)  # Optionally return for use with antispam @@ -175,6 +177,10 @@ class ModLog:          if before.guild.id != GuildConstant.id:              return +        if before.id in self._ignored[Event.guild_channel_update]: +            self._ignored[Event.guild_channel_update].remove(before.id) +            return +          diff = DeepDiff(before, after)          changes = []          done = [] diff --git a/bot/constants.py b/bot/constants.py index 5e7927ed9..bbe6c1604 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -204,6 +204,11 @@ class Filter(metaclass=YAMLGetter):      watch_words: bool      watch_tokens: bool +    # Notifications are not expected for "watchlist" type filters +    notify_user_zalgo: bool +    notify_user_invites: bool +    notify_user_domains: bool +      ping_everyone: bool      guild_invite_whitelist: List[int]      domain_blacklist: List[str] @@ -292,6 +297,8 @@ class Icons(metaclass=YAMLGetter):      user_unmute: str      user_verified: str +    user_warn: str +      pencil: str      remind_blurple: str @@ -317,6 +324,7 @@ class Channels(metaclass=YAMLGetter):      big_brother_logs: int      bot: int      checkpoint_test: int +    defcon: int      devalerts: int      devlog: int      devtest: int diff --git a/bot/pagination.py b/bot/pagination.py index 0d8e8aaa3..72cfd83ef 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -17,6 +17,10 @@ PAGINATION_EMOJI = [FIRST_EMOJI, LEFT_EMOJI, RIGHT_EMOJI, LAST_EMOJI, DELETE_EMO  log = logging.getLogger(__name__) +class EmptyPaginatorEmbed(Exception): +    pass + +  class LinePaginator(Paginator):      """      A class that aids in paginating code blocks for Discord messages. @@ -96,7 +100,8 @@ class LinePaginator(Paginator):      async def paginate(cls, lines: Iterable[str], ctx: Context, embed: Embed,                         prefix: str = "", suffix: str = "", max_lines: Optional[int] = None, max_size: int = 500,                         empty: bool = True, restrict_to_user: User = None, timeout: int = 300, -                       footer_text: str = None): +                       footer_text: str = None, +                       exception_on_empty_embed: bool = False):          """          Use a paginator and set of reactions to provide pagination over a set of lines. The reactions are used to          switch page, or to finish with pagination. @@ -151,6 +156,14 @@ class LinePaginator(Paginator):          paginator = cls(prefix=prefix, suffix=suffix, max_size=max_size, max_lines=max_lines)          current_page = 0 +        if not lines: +            if exception_on_empty_embed: +                log.exception(f"Pagination asked for empty lines iterable") +                raise EmptyPaginatorEmbed("No lines to paginate") + +            log.debug("No lines to add to paginator, adding '(nothing to display)' message") +            lines.append("(nothing to display)") +          for line in lines:              try:                  paginator.add_line(line, empty=empty) @@ -315,7 +328,8 @@ class ImagePaginator(Paginator):      @classmethod      async def paginate(cls, pages: List[Tuple[str, str]], ctx: Context, embed: Embed, -                       prefix: str = "", suffix: str = "", timeout: int = 300): +                       prefix: str = "", suffix: str = "", timeout: int = 300, +                       exception_on_empty_embed: bool = False):          """          Use a paginator and set of reactions to provide          pagination over a set of title/image pairs.The reactions are @@ -361,6 +375,14 @@ class ImagePaginator(Paginator):          paginator = cls(prefix=prefix, suffix=suffix)          current_page = 0 +        if not pages: +            if exception_on_empty_embed: +                log.exception(f"Pagination asked for empty image list") +                raise EmptyPaginatorEmbed("No images to paginate") + +            log.debug("No images to add to paginator, adding '(no images to display)' message") +            pages.append(("(no images to display)", "")) +          for text, image_url in pages:              paginator.add_line(text)              paginator.add_image(image_url) diff --git a/config-default.yml b/config-default.yml index e7145289d..ad87e44ac 100644 --- a/config-default.yml +++ b/config-default.yml @@ -72,6 +72,8 @@ style:          user_unmute:   "https://cdn.discordapp.com/emojis/472472639206719508.png"          user_verified: "https://cdn.discordapp.com/emojis/470326274519334936.png" +        user_warn: "https://cdn.discordapp.com/emojis/470326274238447633.png" +          pencil: "https://cdn.discordapp.com/emojis/470326272401211415.png"          remind_blurple: "https://cdn.discordapp.com/emojis/477907609215827968.png" @@ -89,6 +91,7 @@ guild:          big_brother_logs:  &BBLOGS        468507907357409333          bot:                              267659945086812160          checkpoint_test:                  422077681434099723 +        defcon:                           464469101889454091          devalerts:                        460181980097675264          devlog:            &DEVLOG        409308876241108992          devtest:           &DEVTEST       414574275865870337 @@ -137,6 +140,12 @@ filter:      watch_words:    true      watch_tokens:   true +    # Notify user on filter? +    # Notifications are not expected for "watchlist" type filters +    notify_user_zalgo:   false +    notify_user_invites: true +    notify_user_domains: false +      # Filter configuration      ping_everyone: true  # Ping @everyone when we send a mod-alert?  |