From 1a40e4b17daa64179f14358b4f86f0602131d799 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Wed, 5 Dec 2018 00:49:44 +0100 Subject: Fixed the !user command so users can still use it if they target themselves. Also restricted it to #bot-commands for anyone except mods and up. --- bot/cogs/information.py | 32 +++++++++++++++++++++++++--- bot/cogs/tags.py | 2 +- bot/decorators.py | 46 +++++++++++++++++----------------------- bot/utils/checks.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 31 deletions(-) create mode 100644 bot/utils/checks.py diff --git a/bot/cogs/information.py b/bot/cogs/information.py index 0f1aa75c5..fa6f56b3e 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -1,11 +1,13 @@ import logging +import random import textwrap from discord import CategoryChannel, Colour, Embed, Member, TextChannel, VoiceChannel -from discord.ext.commands import Bot, Context, command +from discord.ext.commands import BadArgument, Bot, CommandError, Context, MissingPermissions, command -from bot.constants import Emojis, Keys, Roles, URLs +from bot.constants import Channels, Emojis, Keys, NEGATIVE_REPLIES, Roles, URLs from bot.decorators import with_role +from bot.utils.checks import with_role_check from bot.utils.time import time_since log = logging.getLogger(__name__) @@ -121,13 +123,23 @@ class Information: await ctx.send(embed=embed) - @with_role(*MODERATION_ROLES) @command(name="user", aliases=["user_info", "member", "member_info"]) async def user_info(self, ctx: Context, user: Member = None, hidden: bool = False): """ Returns info about a user. """ + # Do a role check if this is being executed on + # someone other than the caller + if user and user != ctx.author: + if not with_role_check(ctx, *MODERATION_ROLES): + raise BadArgument("Only mods can do target other users.") + + # Non-moderators may only do this in #bot-commands + if not with_role_check(ctx, *MODERATION_ROLES): + if not ctx.channel == Channels.bot: + raise MissingPermissions("You can't do that here!") + # Validates hidden input hidden = str(hidden) @@ -192,6 +204,20 @@ class Information: await ctx.send(embed=embed) + @user_info.error + async def eval_command_error(self, ctx: Context, error: CommandError): + embed = Embed(colour=Colour.red()) + + if isinstance(error, BadArgument): + embed.title = random.choice(NEGATIVE_REPLIES) + embed.description = "You do not have permission to use this command on users other than yourself." + await ctx.send(embed=embed) + + elif isinstance(error, MissingPermissions): + embed.title = random.choice(NEGATIVE_REPLIES) + embed.description = f"Sorry, but you may only use this command within <#{Channels.bot}>." + await ctx.send(embed=embed) + def setup(bot): bot.add_cog(Information(bot)) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index a0ba7fdd1..ba4edeef7 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -149,7 +149,7 @@ class Tags: tags = [] - embed = Embed() + embed: Embed = Embed() embed.colour = Colour.red() tag_data = await self.get_tag_data(tag_name) diff --git a/bot/decorators.py b/bot/decorators.py index fe974cbd3..630c2267f 100644 --- a/bot/decorators.py +++ b/bot/decorators.py @@ -9,49 +9,41 @@ from discord.ext import commands from discord.ext.commands import Context from bot.constants import ERROR_REPLIES +from bot.utils.checks import in_channel_check, with_role_check, without_role_check log = logging.getLogger(__name__) def with_role(*role_ids: int): + """ + Returns True if the user has any one + of the roles in role_ids. + """ + async def predicate(ctx: Context): - if not ctx.guild: # Return False in a DM - log.debug(f"{ctx.author} tried to use the '{ctx.command.name}'command from a DM. " - "This command is restricted by the with_role decorator. Rejecting request.") - return False - - for role in ctx.author.roles: - if role.id in role_ids: - log.debug(f"{ctx.author} has the '{role.name}' role, and passes the check.") - return True - - log.debug(f"{ctx.author} does not have the required role to use " - f"the '{ctx.command.name}' command, so the request is rejected.") - return False + return with_role_check(ctx, *role_ids) return commands.check(predicate) def without_role(*role_ids: int): + """ + Returns True if the user does not have any + of the roles in role_ids. + """ + async def predicate(ctx: Context): - if not ctx.guild: # Return False in a DM - log.debug(f"{ctx.author} tried to use the '{ctx.command.name}' command from a DM. " - "This command is restricted by the without_role decorator. Rejecting request.") - return False - - author_roles = [role.id for role in ctx.author.roles] - check = all(role not in author_roles for role in role_ids) - log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " - f"The result of the without_role check was {check}.") - return check + return without_role_check(ctx, *role_ids) return commands.check(predicate) def in_channel(channel_id): + """ + Checks if the command was executed + inside of the specified channel. + """ + async def predicate(ctx: Context): - check = ctx.channel.id == channel_id - log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " - f"The result of the in_channel check was {check}.") - return check + return in_channel_check(ctx, channel_id) return commands.check(predicate) diff --git a/bot/utils/checks.py b/bot/utils/checks.py new file mode 100644 index 000000000..d07b09fc8 --- /dev/null +++ b/bot/utils/checks.py @@ -0,0 +1,56 @@ +import logging + +from discord.ext.commands import Context + +log = logging.getLogger(__name__) + + +def with_role_check(ctx: Context, *role_ids: int) -> bool: + """ + Returns True if the user has any one + of the roles in role_ids. + """ + + if not ctx.guild: # Return False in a DM + log.debug(f"{ctx.author} tried to use the '{ctx.command.name}'command from a DM. " + "This command is restricted by the with_role decorator. Rejecting request.") + return False + + for role in ctx.author.roles: + if role.id in role_ids: + log.debug(f"{ctx.author} has the '{role.name}' role, and passes the check.") + return True + + log.debug(f"{ctx.author} does not have the required role to use " + f"the '{ctx.command.name}' command, so the request is rejected.") + return False + + +def without_role_check(ctx: Context, *role_ids: int) -> bool: + """ + Returns True if the user does not have any + of the roles in role_ids. + """ + + if not ctx.guild: # Return False in a DM + log.debug(f"{ctx.author} tried to use the '{ctx.command.name}' command from a DM. " + "This command is restricted by the without_role decorator. Rejecting request.") + return False + + author_roles = [role.id for role in ctx.author.roles] + check = all(role not in author_roles for role in role_ids) + log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " + f"The result of the without_role check was {check}.") + return check + + +def in_channel_check(ctx: Context, channel_id: int) -> bool: + """ + Checks if the command was executed + inside of the specified channel. + """ + + check = ctx.channel.id == channel_id + log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " + f"The result of the in_channel check was {check}.") + return check -- cgit v1.2.3 From 393455a1407ee822f28b48e56618030dd6274614 Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Tue, 18 Dec 2018 22:16:45 +0100 Subject: Update bot/cogs/information.py Co-Authored-By: heavysaturn --- bot/cogs/information.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index c3040d8e2..c0401fe19 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -133,7 +133,7 @@ class Information: # someone other than the caller if user and user != ctx.author: if not with_role_check(ctx, *MODERATION_ROLES): - raise BadArgument("Only mods can do target other users.") + raise BadArgument("Only mods can target other users.") # Non-moderators may only do this in #bot-commands if not with_role_check(ctx, *MODERATION_ROLES): -- cgit v1.2.3 From 03ee66a46e75613dd941a021e38460c7f012e486 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Thu, 27 Dec 2018 21:42:12 +0100 Subject: Addressing jchrists review comments. --- Pipfile.lock | 176 +++++++++++++++++++++++++++++----------------------- bot/utils/checks.py | 14 ++--- 2 files changed, 107 insertions(+), 83 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 506b17065..02b9d0359 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -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": { @@ -97,10 +98,10 @@ }, "certifi": { "hashes": [ - "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", - "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" + "sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7", + "sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033" ], - "version": "==2018.10.15" + "version": "==2018.11.29" }, "cffi": { "hashes": [ @@ -188,10 +189,10 @@ }, "idna": { "hashes": [ - "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", - "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" ], - "version": "==2.7" + "version": "==2.8" }, "idna-ssl": { "hashes": [ @@ -307,37 +308,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": [ @@ -350,13 +351,23 @@ "hashes": [ "sha256:00203f406818c3f45d47bb8fe7e67d3feddb8dcbbd45a289a1de7dd789226360", "sha256:0616f800f348664e694dddb0b0c88d26761dd5e9f34e1ed7b7a7d2da14b40cb7", + "sha256:091136f2a37e9ed6bd8ce96fbf5269199ba6edee490d64de7ac934316f31ecca", + "sha256:0d67ae9a5937b1348fa1d97c7dcb6b56aaef828ca6655298e96f2f3114ad829d", + "sha256:0e1aaddd00ee9014fe7a61b9da61427233fcd7c7f193b5efd6689e0ec36bc42f", "sha256:1f7908aab90c92ad85af9d2fec5fc79456a89b3adcc26314d2cde0e238bd789e", "sha256:2ea3517cd5779843de8a759c2349a3cd8d3893e03ab47053b66d5ec6f8bc4f93", + "sha256:39b662f65a067709a62943003c1e807d140e7fcf631fcfc66ebe905f8149b9f4", + "sha256:3ddc19447cf42ef3ec564ab7ebbd4f67838ba9816d739befe29dd70149c775bd", "sha256:48a9f0538c91fc136b3a576bee0e7cd174773dc9920b310c21dcb5519722e82c", "sha256:5280ebc42641a1283b7b1f2c20e5b936692198b9dd9995527c18b794850be1a8", + "sha256:576a8a7a57065dab968d9d18befa2594a7673dcdab78c9b1f34248410cc6118f", + "sha256:5e334a23c8f7cb6079987a2ed9978821a42b4323a3a3bdbc132945348737f9a9", "sha256:5e34e4b5764af65551647f5cc67cf5198c1d05621781d5173b342e5e55bf023b", "sha256:63b120421ab85cad909792583f83b6ca3584610c2fe70751e23f606a3c2e87f0", "sha256:696b5e0109fe368d0057f484e2e91717b49a03f1e310f857f133a4acec9f91dd", + "sha256:6cb528de694f503ea164541c151da6c18267727a7558e0c9716cc0383d89658a", + "sha256:7306d851d5a0cfac9ea07f1177783836f4b37292e5f224a534a52111cb6a6451", + "sha256:7e3e32346d991f1788026917d0a9c182d6d32dc757163eee7ca990f1f831499e", "sha256:870ed021a42b1b02b5fe4a739ea735f671a84128c0a666c705db2cb9abd528eb", "sha256:916da1c19e4012d06a372127d7140dae894806fad67ef44330e5600d77833581", "sha256:9303a289fa0811e1c6abd9ddebfc770556d7c3311cb2b32eff72164ddc49bc64", @@ -364,20 +375,30 @@ "sha256:987e1c94a33c93d9b209315bfda9faa54b8edfce6438a1e93ae866ba20de5956", "sha256:99a3bbdbb844f4fb5d6dd59fac836a40749781c1fa63c563bc216c27aef63f60", "sha256:99db8dc3097ceafbcff9cb2bff384b974795edeb11d167d391a02c7bfeeb6e16", + "sha256:a379526415f54f9462bc65a4da76fb0acc05e3b2a21717dde79621cf4377e0e6", "sha256:a5a96cf49eb580756a44ecf12949e52f211e20bffbf5a95760ac14b1e499cd37", + "sha256:a844b5d8120f99fb7cd276ff544ac5bd562b0c053760d59694e6bf747c6ca7f5", + "sha256:a9284368e81a67a7f47d5ef1ef7e4f11a4f688485879f44cf5f9090bba1f9d94", "sha256:aa6ca3eb56704cdc0d876fc6047ffd5ee960caad52452fbee0f99908a141a0ae", "sha256:aade5e66795c94e4a2b2624affeea8979648d1b0ae3fcee17e74e2c647fc4a8a", "sha256:b78905860336c1d292409e3df6ad39cc1f1c7f0964e66844bbc2ebfca434d073", "sha256:b92f521cdc4e4a3041cc343625b699f20b0b5f976793fb45681aac1efda565f8", + "sha256:bb2baf44e97811687893873eab8cf9f18b40321cc15d15ff9f91dc031e30631f", "sha256:bfde84bbd6ae5f782206d454b67b7ee8f7f818c29b99fd02bf022fd33bab14cb", "sha256:c2b62d3df80e694c0e4a0ed47754c9480521e25642251b3ab1dff050a4e60409", + "sha256:c55d348c1c65896c1bd804527de4880d251ae832acf90d74ad525bb79e77d55c", "sha256:c5e2be6c263b64f6f7656e23e18a4a9980cffc671442795682e8c4e4f815dd9f", "sha256:c99aa3c63104e0818ec566f8ff3942fb7c7a8f35f9912cb63fd8e12318b214b2", "sha256:dae06620d3978da346375ebf88b9e2dd7d151335ba668c995aea9ed07af7add4", "sha256:db5499d0710823fa4fb88206050d46544e8f0e0136a9a5f5570b026584c8fd74", + "sha256:dcd3cd17d291e01e47636101c4a6638ffb44c842d009973e3b5c1b67ff718c58", + "sha256:f12df6b45abc18f27f6e21ce26f7cbf7aa19820911462e46536e22085658ca1e", "sha256:f36baafd82119c4a114b9518202f2a983819101dcc14b26e43fc12cbefdce00e", "sha256:f52b79c8796d81391ab295b04e520bda6feed54d54931708872e8f9ae9db0ea1", - "sha256:ff8cff01582fa1a7e533cb97f628531c4014af4b5f38e33cdcfe5eec29b6d888" + "sha256:fa2a50f762d06d84125db0b95d0121e9c640afa7edc23fc0848896760a390f8e", + "sha256:fa49bb60792b542b95ca93a39041e7113843093ce3cfd216870118eb3798fcc9", + "sha256:ff8cff01582fa1a7e533cb97f628531c4014af4b5f38e33cdcfe5eec29b6d888", + "sha256:ffbccfe1c077b5f41738bd719518213c217be7a7a12a7e74113d05a0d6617390" ], "index": "pypi", "version": "==5.3.0" @@ -416,10 +437,10 @@ }, "pygments": { "hashes": [ - "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", - "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" + "sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", + "sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d" ], - "version": "==2.2.0" + "version": "==2.3.1" }, "pynacl": { "hashes": [ @@ -505,11 +526,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 +540,10 @@ }, "six": { "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" ], - "version": "==1.11.0" + "version": "==1.12.0" }, "snowballstemmer": { "hashes": [ @@ -533,11 +554,11 @@ }, "sphinx": { "hashes": [ - "sha256:120732cbddb1b2364471c3d9f8bfd4b0c5b550862f99a65736c77f970b142aea", - "sha256:b348790776490894e0424101af9c8413f2a86831524bd55c5f379d3e3e12ca64" + "sha256:429e3172466df289f0f742471d7e30ba3ee11f3b5aecd9a840480d03f14bcfe5", + "sha256:c4cb17ba44acffae3d3209646b6baec1e215cad3065e852c68cc569d4df1b9f8" ], "index": "pypi", - "version": "==1.8.2" + "version": "==1.8.3" }, "sphinxcontrib-websupport": { "hashes": [ @@ -581,17 +602,19 @@ }, "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": { @@ -604,10 +627,10 @@ }, "certifi": { "hashes": [ - "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", - "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" + "sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7", + "sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033" ], - "version": "==2018.10.15" + "version": "==2018.11.29" }, "chardet": { "hashes": [ @@ -686,10 +709,10 @@ }, "idna": { "hashes": [ - "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", - "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" ], - "version": "==2.7" + "version": "==2.8" }, "mccabe": { "hashes": [ @@ -707,6 +730,7 @@ }, "pycodestyle": { "hashes": [ + "sha256:74abc4e221d393ea5ce1f129ea6903209940c1ecd29e002e8c6933c2b21026e0", "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" ], @@ -745,11 +769,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 +785,10 @@ }, "six": { "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" ], - "version": "==1.11.0" + "version": "==1.12.0" }, "urllib3": { "hashes": [ diff --git a/bot/utils/checks.py b/bot/utils/checks.py index d07b09fc8..37dc657f7 100644 --- a/bot/utils/checks.py +++ b/bot/utils/checks.py @@ -12,16 +12,16 @@ def with_role_check(ctx: Context, *role_ids: int) -> bool: """ if not ctx.guild: # Return False in a DM - log.debug(f"{ctx.author} tried to use the '{ctx.command.name}'command from a DM. " + log.trace(f"{ctx.author} tried to use the '{ctx.command.name}'command from a DM. " "This command is restricted by the with_role decorator. Rejecting request.") return False for role in ctx.author.roles: if role.id in role_ids: - log.debug(f"{ctx.author} has the '{role.name}' role, and passes the check.") + log.trace(f"{ctx.author} has the '{role.name}' role, and passes the check.") return True - log.debug(f"{ctx.author} does not have the required role to use " + log.trace(f"{ctx.author} does not have the required role to use " f"the '{ctx.command.name}' command, so the request is rejected.") return False @@ -33,13 +33,13 @@ def without_role_check(ctx: Context, *role_ids: int) -> bool: """ if not ctx.guild: # Return False in a DM - log.debug(f"{ctx.author} tried to use the '{ctx.command.name}' command from a DM. " + log.trace(f"{ctx.author} tried to use the '{ctx.command.name}' command from a DM. " "This command is restricted by the without_role decorator. Rejecting request.") return False - author_roles = [role.id for role in ctx.author.roles] + author_roles = (role.id for role in ctx.author.roles) check = all(role not in author_roles for role in role_ids) - log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " + log.trace(f"{ctx.author} tried to call the '{ctx.command.name}' command. " f"The result of the without_role check was {check}.") return check @@ -51,6 +51,6 @@ def in_channel_check(ctx: Context, channel_id: int) -> bool: """ check = ctx.channel.id == channel_id - log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " + log.trace(f"{ctx.author} tried to call the '{ctx.command.name}' command. " f"The result of the in_channel check was {check}.") return check -- cgit v1.2.3 From 9bec011dee4ef3f0968aa44d2459a9367d25313c Mon Sep 17 00:00:00 2001 From: sco1 Date: Sat, 29 Dec 2018 13:10:38 -0500 Subject: Add optional return to modlog post coro Enables generation of a context for AntiSpam to reference for posting infractions --- bot/cogs/modlog.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bot/cogs/modlog.py b/bot/cogs/modlog.py index 1d1546d5b..ef4544f81 100644 --- a/bot/cogs/modlog.py +++ b/bot/cogs/modlog.py @@ -123,7 +123,8 @@ class ModLog: if ping_everyone: content = "@everyone" - await self.bot.get_channel(channel_id).send(content=content, embed=embed, files=files) + 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 async def on_guild_channel_create(self, channel: GUILD_CHANNEL): if channel.guild.id != GuildConstant.id: -- cgit v1.2.3 From 9698cf42a22e0637c1afc21dbf3c8282829ccff0 Mon Sep 17 00:00:00 2001 From: sco1 Date: Sat, 29 Dec 2018 13:58:03 -0500 Subject: Add infraction posting for AntiSpam mutes --- bot/cogs/antispam.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index d5b72718c..052fd48b2 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -15,6 +15,7 @@ from bot.constants import ( Colours, DEBUG_MODE, Event, Guild as GuildConfig, Icons, Roles, ) +from bot.utils.moderation import post_infraction from bot.utils.time import humanize_delta @@ -133,7 +134,8 @@ class AntiSpam: mod_alert_message += f"{content}" - await self.mod_log.send_log_message( + # Return the mod log message Context that we can use to post the infraction + mod_log_message = await self.mod_log.send_log_message( icon_url=Icons.filtering, colour=Colour(Colours.soft_red), title=f"Spam detected!", @@ -143,28 +145,30 @@ class AntiSpam: ping_everyone=AntiSpamConfig.ping_everyone ) - await member.add_roles(self.muted_role, reason=reason) + # Post AntiSpam mute as a regular infraction so it can be reversed + ctx = await self.bot.get_context(mod_log_message) + response_object = await post_infraction(ctx, member, type="mute", reason=reason, duration=remove_role_after) + if response_object is None: + return # Appropriate error(s) are already raised by post_infraction + + self.mod_log.ignore(Event.member_update, member.id) + await member.add_roles(self._muted_role, reason=reason) + + loop = asyncio.get_event_loop() + infraction_object = response_object["infraction"] + self.schedule_task(loop, infraction_object["id"], infraction_object) + description = textwrap.dedent(f""" **Channel**: {msg.channel.mention} **User**: {msg.author.mention} (`{msg.author.id}`) **Reason**: {reason} Role will be removed after {human_duration}. """) - await self.mod_log.send_log_message( icon_url=Icons.user_mute, colour=Colour(Colours.soft_red), title="User muted", text=description ) - await asyncio.sleep(remove_role_after) - await member.remove_roles(self.muted_role, reason="AntiSpam mute expired") - - await self.mod_log.send_log_message( - icon_url=Icons.user_mute, colour=Colour(Colours.soft_green), - title="User unmuted", - text=f"Was muted by `AntiSpam` cog for {human_duration}." - ) - async def maybe_delete_messages(self, channel: TextChannel, messages: List[Message]): # Is deletion of offending messages actually enabled? if AntiSpamConfig.clean_offending: -- cgit v1.2.3 From 9e379f23528bef0faf4ffafbdd2470526bd78773 Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Sun, 6 Jan 2019 02:14:04 +0100 Subject: Adding 'rich embed' filter to filtering, 'embed'-support to modlog, and 'rich embed' filtering options to config --- bot/cogs/filtering.py | 73 ++++++++++++++++++++++++++++++++++++++++++++------- bot/cogs/modlog.py | 17 ++++++++++++ config-default.yml | 18 +++++++------ 3 files changed, 91 insertions(+), 17 deletions(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 247ee26b8..f6a1e7b4d 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -45,6 +45,7 @@ class Filtering: "enabled": Filter.filter_zalgo, "function": self._has_zalgo, "type": "filter", + "content_only": True, "user_notification": Filter.notify_user_zalgo, "notification_msg": ( "Your post has been removed for abusing Unicode character rendering (aka Zalgo text). " @@ -55,6 +56,7 @@ class Filtering: "enabled": Filter.filter_invites, "function": self._has_invites, "type": "filter", + "content_only": True, "user_notification": Filter.notify_user_invites, "notification_msg": ( f"Per Rule 10, your invite link has been removed. {_staff_mistake_str}\n\n" @@ -65,20 +67,36 @@ class Filtering: "enabled": Filter.filter_domains, "function": self._has_urls, "type": "filter", + "content_only": True, "user_notification": Filter.notify_user_domains, "notification_msg": ( f"Your URL has been removed because it matched a blacklisted domain. {_staff_mistake_str}" ) }, + "filter_rich_embeds": { + "enabled": Filter.filter_rich_embeds, + "function": self._has_rich_embed, + "type": "filter", + "content_only": False, + "user_notification": Filter.notify_user_rich_embeds, + "notification_msg": ( + "Your post has been removed because it contained a rich embed. " + "This indicates that you're either using an unofficial discord client or are using a self-bot, " + "both of which violate Discord's Terms of Service.\n\n" + f"Please don't use a self-bot or an unofficial Discord client on our server. {_staff_mistake_str}" + ) + }, "watch_words": { "enabled": Filter.watch_words, "function": self._has_watchlist_words, "type": "watchlist", + "content_only": True, }, "watch_tokens": { "enabled": Filter.watch_tokens, "function": self._has_watchlist_tokens, "type": "watchlist", + "content_only": True, }, } @@ -115,18 +133,46 @@ class Filtering: ) # If we're running the bot locally, ignore role whitelist and only listen to #dev-test + # if DEBUG_MODE: + # filter_message = not msg.author.bot and msg.channel.id == Channels.devtest + if DEBUG_MODE: - filter_message = not msg.author.bot and msg.channel.id == Channels.devtest + filter_message = msg.author.id != 414020331980980234 and msg.channel.id == Channels.devtest # If none of the above, we can start filtering. if filter_message: + for filter_name, _filter in self.filters.items(): # Is this specific filter enabled in the config? if _filter["enabled"]: - triggered = await _filter["function"](msg.content) + # Does the filter only need the message content or the full message? + if _filter["content_only"]: + triggered = await _filter["function"](msg.content) + else: + triggered = await _filter["function"](msg) if triggered: + # If this is a filter (not a watchlist), we should delete the message. + if _filter["type"] == "filter": + try: + # Embeds (can) trigger both the `on_message` and `on_message_edit` + # event handlers, triggering filtering twice for the same message. + # + # If `on_message`-triggered filtering already deleted the message + # then `on_message_edit`-triggered filtering will raise exception + # since the message no longer exists. + # + # In addition, to avoid sending two notifications to the user, the + # logs, and mod_alert, we return if the message no longer exists. + await msg.delete() + except discord.errors.NotFound: + return + + # Notify the user if the filter specifies + if _filter["user_notification"]: + await self.notify_member(msg.author, _filter["notification_msg"], msg.channel) + if isinstance(msg.channel, DMChannel): channel_str = "via DM" else: @@ -153,13 +199,12 @@ class Filtering: ping_everyone=Filter.ping_everyone, ) - # If this is a filter (not a watchlist), we should delete the message. - 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) + if filter_name == "filter_rich_embeds": + await self.mod_log.send_log_embeds( + embeds=msg.embeds, + content="The message contained the following embed(s):\n", + channel_id=Channels.mod_alerts, + ) break # We don't want multiple filters to trigger @@ -272,6 +317,16 @@ class Filtering: return True return False + @staticmethod + async def _has_rich_embed(msg: Message): + """ + Returns True if any of the embeds in the message + are of type 'rich', returns False otherwise + """ + if msg.embeds: + return any(embed.type == "rich" for embed in msg.embeds) + 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 diff --git a/bot/cogs/modlog.py b/bot/cogs/modlog.py index 0561b5afb..a167ba9e8 100644 --- a/bot/cogs/modlog.py +++ b/bot/cogs/modlog.py @@ -127,6 +127,23 @@ class ModLog: await self.bot.get_channel(channel_id).send(content=content, embed=embed, files=files) + async def send_log_embeds( + self, embeds: List[Embed], content: Optional[str], + channel_id: int = Channels.modlog, ping_everyone: bool = False, + ): + + if ping_everyone: + if content: + content = f"@everyone\n{content}" + else: + content = "@everyone" + + if content: + await self.bot.get_channel(channel_id).send(content=content) + + for embed in embeds: + await self.bot.get_channel(channel_id).send(embed=embed) + async def on_guild_channel_create(self, channel: GUILD_CHANNEL): if channel.guild.id != GuildConstant.id: return diff --git a/config-default.yml b/config-default.yml index ad87e44ac..ad3487c78 100644 --- a/config-default.yml +++ b/config-default.yml @@ -134,17 +134,19 @@ guild: filter: # What do we filter? - filter_zalgo: false - filter_invites: true - filter_domains: true - watch_words: true - watch_tokens: true + filter_zalgo: false + filter_invites: true + filter_domains: true + filter_rich_embeds: true + 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 + notify_user_zalgo: false + notify_user_invites: true + notify_user_domains: false + notify_user_rich_embeds: true # Filter configuration ping_everyone: true # Ping @everyone when we send a mod-alert? -- cgit v1.2.3 From d9130047e7fcbedd0e033c23c6b82f608cd9039b Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Sun, 6 Jan 2019 02:38:17 +0100 Subject: Restoring DEBUG_MODE filtering condition and adding comment --- bot/cogs/filtering.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index f6a1e7b4d..9324314df 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -133,11 +133,8 @@ class Filtering: ) # If we're running the bot locally, ignore role whitelist and only listen to #dev-test - # if DEBUG_MODE: - # filter_message = not msg.author.bot and msg.channel.id == Channels.devtest - if DEBUG_MODE: - filter_message = msg.author.id != 414020331980980234 and msg.channel.id == Channels.devtest + filter_message = not msg.author.bot and msg.channel.id == Channels.devtest # If none of the above, we can start filtering. if filter_message: @@ -199,6 +196,7 @@ class Filtering: ping_everyone=Filter.ping_everyone, ) + # If filtering rich embeds, also send the removed embeds to mod_alerts if filter_name == "filter_rich_embeds": await self.mod_log.send_log_embeds( embeds=msg.embeds, -- cgit v1.2.3 From 9f8e4774ae6eeac8cbcece8c65c8de390c3300fd Mon Sep 17 00:00:00 2001 From: sco1 Date: Sun, 6 Jan 2019 00:27:49 -0500 Subject: Antispam Infraction Fixes Add muted role object to cog attributes Fix unawaited coroutine in modlog Adjust modlog message ctx variable to be more explicit Fix duration being sent to API as integer instead of string Fix temporary infraction being placed into a nonexistent schedule, now placed into the moderation cog's task schedule --- bot/cogs/antispam.py | 15 +++++++++------ bot/cogs/modlog.py | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 052fd48b2..cf52d30fa 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -45,7 +45,7 @@ WHITELISTED_ROLES = (Roles.owner, Roles.admin, Roles.moderator, Roles.helpers) class AntiSpam: def __init__(self, bot: Bot): self.bot = bot - self.muted_role = None + self._muted_role = Object(Roles.muted) @property def mod_log(self) -> ModLog: @@ -135,7 +135,7 @@ class AntiSpam: mod_alert_message += f"{content}" # Return the mod log message Context that we can use to post the infraction - mod_log_message = await self.mod_log.send_log_message( + mod_log_ctx = await self.mod_log.send_log_message( icon_url=Icons.filtering, colour=Colour(Colours.soft_red), title=f"Spam detected!", @@ -146,17 +146,20 @@ class AntiSpam: ) # Post AntiSpam mute as a regular infraction so it can be reversed - ctx = await self.bot.get_context(mod_log_message) - response_object = await post_infraction(ctx, member, type="mute", reason=reason, duration=remove_role_after) + response_object = await post_infraction( + mod_log_ctx, member, type="mute", reason=reason, duration=f"{remove_role_after}S" + ) if response_object is None: return # Appropriate error(s) are already raised by post_infraction self.mod_log.ignore(Event.member_update, member.id) await member.add_roles(self._muted_role, reason=reason) - loop = asyncio.get_event_loop() + # Insert ourselves into the moderation infraction loop infraction_object = response_object["infraction"] - self.schedule_task(loop, infraction_object["id"], infraction_object) + loop = asyncio.get_event_loop() + moderation_cog = self.bot.get_cog('Moderation') + moderation_cog.schedule_task(loop, infraction_object["id"], infraction_object) description = textwrap.dedent(f""" **Channel**: {msg.channel.mention} diff --git a/bot/cogs/modlog.py b/bot/cogs/modlog.py index f36c431e6..9d26fa925 100644 --- a/bot/cogs/modlog.py +++ b/bot/cogs/modlog.py @@ -126,7 +126,7 @@ class ModLog: 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 + return await self.bot.get_context(log_message) # Optionally return for use with antispam async def on_guild_channel_create(self, channel: GUILD_CHANNEL): if channel.guild.id != GuildConstant.id: -- cgit v1.2.3 From 76951b4f1b0ada06b45f38271e6eb8c93ce8e51e Mon Sep 17 00:00:00 2001 From: sco1 Date: Sun, 6 Jan 2019 00:54:27 -0500 Subject: Invoke Moderation tempmute directly --- bot/cogs/antispam.py | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index cf52d30fa..800700a50 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -1,22 +1,18 @@ -import asyncio import logging -import textwrap from datetime import datetime, timedelta from typing import List -from dateutil.relativedelta import relativedelta from discord import Colour, Member, Message, Object, TextChannel from discord.ext.commands import Bot from bot import rules +from bot.cogs.moderation import Moderation from bot.cogs.modlog import ModLog from bot.constants import ( AntiSpam as AntiSpamConfig, Channels, Colours, DEBUG_MODE, Event, Guild as GuildConfig, Icons, Roles, ) -from bot.utils.moderation import post_infraction -from bot.utils.time import humanize_delta log = logging.getLogger(__name__) @@ -111,8 +107,6 @@ class AntiSpam: # Sanity check to ensure we're not lagging behind if self.muted_role not in member.roles: remove_role_after = AntiSpamConfig.punishment['remove_after'] - duration_delta = relativedelta(seconds=remove_role_after) - human_duration = humanize_delta(duration_delta) mod_alert_message = ( f"**Triggered by:** {member.display_name}#{member.discriminator} (`{member.id}`)\n" @@ -145,32 +139,8 @@ class AntiSpam: ping_everyone=AntiSpamConfig.ping_everyone ) - # Post AntiSpam mute as a regular infraction so it can be reversed - response_object = await post_infraction( - mod_log_ctx, member, type="mute", reason=reason, duration=f"{remove_role_after}S" - ) - if response_object is None: - return # Appropriate error(s) are already raised by post_infraction - - self.mod_log.ignore(Event.member_update, member.id) - await member.add_roles(self._muted_role, reason=reason) - - # Insert ourselves into the moderation infraction loop - infraction_object = response_object["infraction"] - loop = asyncio.get_event_loop() - moderation_cog = self.bot.get_cog('Moderation') - moderation_cog.schedule_task(loop, infraction_object["id"], infraction_object) - - description = textwrap.dedent(f""" - **Channel**: {msg.channel.mention} - **User**: {msg.author.mention} (`{msg.author.id}`) - **Reason**: {reason} - Role will be removed after {human_duration}. - """) - await self.mod_log.send_log_message( - icon_url=Icons.user_mute, colour=Colour(Colours.soft_red), - title="User muted", text=description - ) + # Run a tempmute + await mod_log_ctx.invoke(Moderation.tempmute, member, f"{remove_role_after}S", reason=reason) async def maybe_delete_messages(self, channel: TextChannel, messages: List[Message]): # Is deletion of offending messages actually enabled? -- cgit v1.2.3 From 990a901d9a1d00340d401ea9f2c87f648056a144 Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Sun, 6 Jan 2019 20:48:20 +0100 Subject: Clarifying comment --- bot/cogs/filtering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 9324314df..67ff9d0bf 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -153,7 +153,7 @@ class Filtering: # If this is a filter (not a watchlist), we should delete the message. if _filter["type"] == "filter": try: - # Embeds (can) trigger both the `on_message` and `on_message_edit` + # Embeds (can?) trigger both the `on_message` and `on_message_edit` # event handlers, triggering filtering twice for the same message. # # If `on_message`-triggered filtering already deleted the message -- cgit v1.2.3 From 23af034e656a82d0d6fe6268a5c41d010cbfaf4c Mon Sep 17 00:00:00 2001 From: Derek Date: Sun, 6 Jan 2019 19:08:34 -0500 Subject: Add free command --- bot/__main__.py | 1 + bot/cogs/free.py | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 bot/cogs/free.py diff --git a/bot/__main__.py b/bot/__main__.py index 3c40a3243..581fa5c8e 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -75,6 +75,7 @@ bot.load_extension("bot.cogs.tags") bot.load_extension("bot.cogs.token_remover") bot.load_extension("bot.cogs.utils") bot.load_extension("bot.cogs.wolfram") +bot.load_extension("bot.cogs.free") if has_rmq: bot.load_extension("bot.cogs.rmq") diff --git a/bot/cogs/free.py b/bot/cogs/free.py new file mode 100644 index 000000000..e50058106 --- /dev/null +++ b/bot/cogs/free.py @@ -0,0 +1,90 @@ +import logging +from datetime import datetime + +from discord import Colour, Embed, Member, utils +from discord.ext.commands import BucketType, Context, command, cooldown + + +log = logging.getLogger(__name__) + + +class Free: + """Tries to figure out which help channels are free.""" + + PYTHON_HELP_ID = 356013061213126657 + TIME_INACTIVE = 300 + + @command(name="free", aliases=('f',)) + @cooldown(1, 60.0, BucketType.channel) + async def free(self, ctx: Context, user: Member = None, seek: int = 2): + """ + Lists free help channels by likeliness of availability. + :param user: accepts user mention, ID, etc. + :param seek: How far back to check the last active message. + + seek is used only when this command is invoked in a help channel. + + When seek is 2, we are avoiding considering the last active message + in a channel to be the one that invoked this command. + + When seek is 3 or more, a user has been mentioned on the assumption + that they asked if the channel is free or they asked their question + in an active channel, and we want the message before that happened. + """ + free_channels = [] + python_help = utils.get(ctx.guild.categories, id=self.PYTHON_HELP_ID) + + if user is not None and seek == 2: + seek = 3 + elif seek > 10: + seek = 3 + + for channel in python_help.channels: + if channel.id == ctx.channel.id: + messages = await channel.history(limit=seek).flatten() + msg = messages[seek-1] + else: + messages = await channel.history(limit=1).flatten() + msg = messages[0] + + inactive = (datetime.utcnow() - msg.created_at).seconds + if inactive > self.TIME_INACTIVE: + free_channels.append((inactive, channel.id)) + + embed = Embed() + embed.colour = Colour.gold() + embed.title = "**Looking for a free help channel?**" + + if user is not None: + embed.description = f"**Hey <@{user.id}>!**\n\n" + else: + embed.description = "" + + if free_channels: + embed.description += "**The following channel{0} look{1} free:**\n\n**".format( + 's' if len(free_channels) > 1 else '', + '' if len(free_channels) > 1 else 's') + + for i, channel in enumerate(sorted(free_channels, reverse=True), 1): + inactive, ID = channel + minutes, seconds = divmod(inactive, 60) + if minutes > 60: + hours, minutes = divmod(minutes, 60) + embed.description += f'{i}. <#{ID}> inactive for {hours}h{minutes}m{seconds}s\n\n' + else: + embed.description += f'{i}. <#{ID}> inactive for {minutes}m{seconds}s\n\n' + + embed.description += ("**\nThese channels aren't guaranteed to be free, " + "so use your best judgement and check for yourself.") + else: + embed.description = ("**Doesn't look like any channels are available to me. " + "You're welcome to check for yourself to be sure. " + "If all channels are truly busy, please be patient " + "as one will likely be available soon.**") + + return await ctx.send(embed=embed) + + +def setup(bot): + bot.add_cog(Free()) + log.info("Cog loaded: Free") -- cgit v1.2.3 From ebad04f068598ddce567c2f855172206d0bb4e21 Mon Sep 17 00:00:00 2001 From: Derek Date: Sun, 6 Jan 2019 19:16:15 -0500 Subject: Change single quotes to double quotes for the sake of consistency --- bot/cogs/free.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index e50058106..73946dec1 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -70,9 +70,9 @@ class Free: minutes, seconds = divmod(inactive, 60) if minutes > 60: hours, minutes = divmod(minutes, 60) - embed.description += f'{i}. <#{ID}> inactive for {hours}h{minutes}m{seconds}s\n\n' + embed.description += f"{i}. <#{ID}> inactive for {hours}h{minutes}m{seconds}s\n\n" else: - embed.description += f'{i}. <#{ID}> inactive for {minutes}m{seconds}s\n\n' + embed.description += f"{i}. <#{ID}> inactive for {minutes}m{seconds}s\n\n" embed.description += ("**\nThese channels aren't guaranteed to be free, " "so use your best judgement and check for yourself.") -- cgit v1.2.3 From f0f37e657c6ec3c28fcfbdcd1dfbfb7e8d0729f1 Mon Sep 17 00:00:00 2001 From: Derek Date: Sun, 6 Jan 2019 19:48:58 -0500 Subject: Update constraint on seek so it can't be less than 1 --- bot/cogs/free.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 73946dec1..697e15f4b 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -36,7 +36,7 @@ class Free: if user is not None and seek == 2: seek = 3 - elif seek > 10: + elif not 0 < seek < 10: seek = 3 for channel in python_help.channels: -- cgit v1.2.3 From 4a78dabeec56a07c4e48ce40bb6fdf09b32110b3 Mon Sep 17 00:00:00 2001 From: Derek Date: Mon, 7 Jan 2019 03:28:45 -0500 Subject: Remove unnecessary return statement --- bot/cogs/free.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 697e15f4b..00e5fb8bb 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -82,7 +82,7 @@ class Free: "If all channels are truly busy, please be patient " "as one will likely be available soon.**") - return await ctx.send(embed=embed) + await ctx.send(embed=embed) def setup(bot): -- cgit v1.2.3 From 5f4e617a98422a588e98e1e0d067e638877c5d65 Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Mon, 7 Jan 2019 19:45:57 +0100 Subject: Reverting modlog.py to original state --- bot/cogs/modlog.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/bot/cogs/modlog.py b/bot/cogs/modlog.py index a167ba9e8..0561b5afb 100644 --- a/bot/cogs/modlog.py +++ b/bot/cogs/modlog.py @@ -127,23 +127,6 @@ class ModLog: await self.bot.get_channel(channel_id).send(content=content, embed=embed, files=files) - async def send_log_embeds( - self, embeds: List[Embed], content: Optional[str], - channel_id: int = Channels.modlog, ping_everyone: bool = False, - ): - - if ping_everyone: - if content: - content = f"@everyone\n{content}" - else: - content = "@everyone" - - if content: - await self.bot.get_channel(channel_id).send(content=content) - - for embed in embeds: - await self.bot.get_channel(channel_id).send(embed=embed) - async def on_guild_channel_create(self, channel: GUILD_CHANNEL): if channel.guild.id != GuildConstant.id: return -- cgit v1.2.3 From fafa80ebcb29e4de5986a276ff85fb84e1d267be Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Mon, 7 Jan 2019 19:47:22 +0100 Subject: Modifying 'send_log_message' so it supports sending additional embeds to the specified (log) channel --- bot/cogs/modlog.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bot/cogs/modlog.py b/bot/cogs/modlog.py index 0561b5afb..c96838a54 100644 --- a/bot/cogs/modlog.py +++ b/bot/cogs/modlog.py @@ -106,7 +106,7 @@ class ModLog: 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, content: str = None + files: List[File] = None, content: str = None, additional_embeds: List[Embed] = None, ): embed = Embed(description=text) @@ -125,7 +125,14 @@ class ModLog: else: content = "@everyone" - await self.bot.get_channel(channel_id).send(content=content, embed=embed, files=files) + channel = self.bot.get_channel(channel_id) + + await channel.send(content=content, embed=embed, files=files) + + if additional_embeds: + await channel.send("With the following embed(s):") + for additional_embed in additional_embeds: + await channel.send(embed=additional_embed) async def on_guild_channel_create(self, channel: GUILD_CHANNEL): if channel.guild.id != GuildConstant.id: -- cgit v1.2.3 From e3ace591d9dca2d4ab95c7b07d6af3e6fc84b7c3 Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Mon, 7 Jan 2019 19:51:16 +0100 Subject: Changing the way in which the filter_rich_embed sends the embeds to mod_log.send_log_message --- bot/cogs/filtering.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 67ff9d0bf..5c6ed9c26 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -185,6 +185,8 @@ class Filtering: log.debug(message) + additional_embeds = msg.embeds if filter_name == "filter_rich_embeds" else None + # Send pretty mod log embed to mod-alerts await self.mod_log.send_log_message( icon_url=Icons.filtering, @@ -194,16 +196,10 @@ class Filtering: thumbnail=msg.author.avatar_url_as(static_format="png"), channel_id=Channels.mod_alerts, ping_everyone=Filter.ping_everyone, + additional_embeds=additional_embeds, ) # If filtering rich embeds, also send the removed embeds to mod_alerts - if filter_name == "filter_rich_embeds": - await self.mod_log.send_log_embeds( - embeds=msg.embeds, - content="The message contained the following embed(s):\n", - channel_id=Channels.mod_alerts, - ) - break # We don't want multiple filters to trigger @staticmethod -- cgit v1.2.3 From a78ac6d6e1661d2647dd61ca114ab695b5aa72af Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Mon, 7 Jan 2019 20:00:37 +0100 Subject: Including the filter_rich_embeds constants in bot/constants.py --- bot/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bot/constants.py b/bot/constants.py index bbe6c1604..c1375bb13 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -201,6 +201,7 @@ class Filter(metaclass=YAMLGetter): filter_zalgo: bool filter_invites: bool filter_domains: bool + filter_rich_embeds: bool watch_words: bool watch_tokens: bool @@ -208,6 +209,7 @@ class Filter(metaclass=YAMLGetter): notify_user_zalgo: bool notify_user_invites: bool notify_user_domains: bool + notify_user_rich_embeds: bool ping_everyone: bool guild_invite_whitelist: List[int] -- cgit v1.2.3 From 543b2ae88c82fd5558785cee224680ff0285c7ad Mon Sep 17 00:00:00 2001 From: Daniel Brown Date: Mon, 7 Jan 2019 13:04:09 -0600 Subject: Corrected the delete_reminder() method to use the correct _delete_reminder method(). Signed-off-by: Daniel Brown --- bot/cogs/reminders.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/reminders.py b/bot/cogs/reminders.py index f6ed111dc..ddf5cc1f3 100644 --- a/bot/cogs/reminders.py +++ b/bot/cogs/reminders.py @@ -398,7 +398,7 @@ class Reminders(Scheduler): ) if not failed: - self.cancel_reminder(response_data["reminder_id"]) + await self._delete_reminder(response_data["reminder_id"]) def setup(bot: Bot): -- cgit v1.2.3 From 16afa8d6cfa7ff70d73639ea3665bb47c5814586 Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Mon, 7 Jan 2019 20:44:00 +0100 Subject: Removing orphaned comment and restructuring user notification for filter_rich_embed --- bot/cogs/filtering.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 5c6ed9c26..42424cd05 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -82,8 +82,8 @@ class Filtering: "notification_msg": ( "Your post has been removed because it contained a rich embed. " "This indicates that you're either using an unofficial discord client or are using a self-bot, " - "both of which violate Discord's Terms of Service.\n\n" - f"Please don't use a self-bot or an unofficial Discord client on our server. {_staff_mistake_str}" + f"both of which violate Discord's Terms of Service. {_staff_mistake_str}\n\n" + "Please don't use a self-bot or an unofficial Discord client on our server." ) }, "watch_words": { @@ -140,7 +140,6 @@ class Filtering: if filter_message: for filter_name, _filter in self.filters.items(): - # Is this specific filter enabled in the config? if _filter["enabled"]: # Does the filter only need the message content or the full message? @@ -199,7 +198,6 @@ class Filtering: additional_embeds=additional_embeds, ) - # If filtering rich embeds, also send the removed embeds to mod_alerts break # We don't want multiple filters to trigger @staticmethod -- cgit v1.2.3 From 84437e0ddfed04b87c4d98d47f432e5f7d2e136f Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Mon, 7 Jan 2019 20:45:37 +0100 Subject: Deleting unnecessary additional line --- bot/cogs/filtering.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 42424cd05..570d6549f 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -138,7 +138,6 @@ class Filtering: # If none of the above, we can start filtering. if filter_message: - for filter_name, _filter in self.filters.items(): # Is this specific filter enabled in the config? if _filter["enabled"]: -- cgit v1.2.3 From 71eac59a69b36e21efb0bcf165ad8cd41ccaa1fb Mon Sep 17 00:00:00 2001 From: sco1 Date: Mon, 7 Jan 2019 17:51:00 -0500 Subject: Add mute infraction check to role restoration --- bot/cogs/events.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/bot/cogs/events.py b/bot/cogs/events.py index edfc6e579..c604169c0 100644 --- a/bot/cogs/events.py +++ b/bot/cogs/events.py @@ -25,6 +25,7 @@ class Events: def __init__(self, bot: Bot): self.bot = bot + self.headers = {"X-API-KEY": Keys.site_api} @property def mod_log(self) -> ModLog: @@ -103,6 +104,29 @@ class Events: resp = await response.json() return resp["data"] + async def has_active_mute(self, user_id: str) -> bool: + """ + Check whether a user has any active mute infractions + """ + response = await self.bot.http_session.get( + URLs.site_infractions_user.format( + user_id=user_id + ), + params={"hidden": "True"}, + headers=self.headers + ) + infraction_list = await response.json() + + # Check for active mute infractions + if len(infraction_list) == 0: + # Short circuit + return False + + muted_check = any( + [infraction["active"] for infraction in infraction_list if infraction["type"].lower() == "mute"] + ) + return muted_check + async def on_command_error(self, ctx: Context, e: CommandError): command = ctx.command parent = None @@ -236,6 +260,10 @@ class Events: for role in RESTORE_ROLES: if role in old_roles: + # Check for mute roles that were not able to be removed and skip if present + if role == str(Roles.muted) and not await self.has_active_mute(str(member.id)): + continue + new_roles.append(Object(int(role))) for role in new_roles: -- cgit v1.2.3 From d5cb479be6925a10cf0c46e3088518f56a5a91b3 Mon Sep 17 00:00:00 2001 From: sco1 Date: Mon, 7 Jan 2019 19:16:03 -0500 Subject: Add line after docstring --- bot/cogs/events.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bot/cogs/events.py b/bot/cogs/events.py index c604169c0..77a15733d 100644 --- a/bot/cogs/events.py +++ b/bot/cogs/events.py @@ -108,6 +108,7 @@ class Events: """ Check whether a user has any active mute infractions """ + response = await self.bot.http_session.get( URLs.site_infractions_user.format( user_id=user_id -- cgit v1.2.3 From 72150b77659dd130ff80e3797179e75943f5c4a2 Mon Sep 17 00:00:00 2001 From: Derek Date: Mon, 7 Jan 2019 20:02:35 -0500 Subject: Add category constant --- bot/cogs/free.py | 4 +++- bot/constants.py | 7 +++++++ config-default.yml | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 00e5fb8bb..4566ade5f 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -4,6 +4,8 @@ from datetime import datetime from discord import Colour, Embed, Member, utils from discord.ext.commands import BucketType, Context, command, cooldown +from bot.constants import Categories + log = logging.getLogger(__name__) @@ -11,7 +13,7 @@ log = logging.getLogger(__name__) class Free: """Tries to figure out which help channels are free.""" - PYTHON_HELP_ID = 356013061213126657 + PYTHON_HELP_ID = Categories.python_help TIME_INACTIVE = 300 @command(name="free", aliases=('f',)) diff --git a/bot/constants.py b/bot/constants.py index bbe6c1604..aae9b05e5 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -315,6 +315,13 @@ class CleanMessages(metaclass=YAMLGetter): message_limit: int +class Categories(metaclass=YAMLGetter): + section = "guild" + subsection = "categories" + + python_help: int + + class Channels(metaclass=YAMLGetter): section = "guild" subsection = "channels" diff --git a/config-default.yml b/config-default.yml index ad87e44ac..7e2a22cc9 100644 --- a/config-default.yml +++ b/config-default.yml @@ -85,6 +85,9 @@ style: guild: id: 267624335836053506 + categories: + python_help: 356013061213126657 + channels: admins: &ADMINS 365960823622991872 announcements: 354619224620138496 -- cgit v1.2.3 From 5e794a0a7ab732ff2ac2ba37473ecd87413603d4 Mon Sep 17 00:00:00 2001 From: Derek Date: Mon, 7 Jan 2019 20:12:16 -0500 Subject: Update method for mentioning users and channels to be more idiomatic --- bot/cogs/free.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 4566ade5f..71ee18032 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -51,14 +51,14 @@ class Free: inactive = (datetime.utcnow() - msg.created_at).seconds if inactive > self.TIME_INACTIVE: - free_channels.append((inactive, channel.id)) + free_channels.append((inactive, channel)) embed = Embed() embed.colour = Colour.gold() embed.title = "**Looking for a free help channel?**" if user is not None: - embed.description = f"**Hey <@{user.id}>!**\n\n" + embed.description = f"**Hey {user.mention}!**\n\n" else: embed.description = "" @@ -67,14 +67,13 @@ class Free: 's' if len(free_channels) > 1 else '', '' if len(free_channels) > 1 else 's') - for i, channel in enumerate(sorted(free_channels, reverse=True), 1): - inactive, ID = channel + for i, (inactive, channel) in enumerate(sorted(free_channels, reverse=True), 1): minutes, seconds = divmod(inactive, 60) if minutes > 60: hours, minutes = divmod(minutes, 60) - embed.description += f"{i}. <#{ID}> inactive for {hours}h{minutes}m{seconds}s\n\n" + embed.description += f"{i}. {channel.mention} inactive for {hours}h{minutes}m{seconds}s\n\n" else: - embed.description += f"{i}. <#{ID}> inactive for {minutes}m{seconds}s\n\n" + embed.description += f"{i}. {channel.mention} inactive for {minutes}m{seconds}s\n\n" embed.description += ("**\nThese channels aren't guaranteed to be free, " "so use your best judgement and check for yourself.") -- cgit v1.2.3 From ffbfd4b3467af2becb62f7b7639678136c1b4c1a Mon Sep 17 00:00:00 2001 From: Derek Date: Mon, 7 Jan 2019 20:15:07 -0500 Subject: Fix off by one --- bot/cogs/free.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 71ee18032..90caad7ae 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -69,7 +69,7 @@ class Free: for i, (inactive, channel) in enumerate(sorted(free_channels, reverse=True), 1): minutes, seconds = divmod(inactive, 60) - if minutes > 60: + if minutes > 59: hours, minutes = divmod(minutes, 60) embed.description += f"{i}. {channel.mention} inactive for {hours}h{minutes}m{seconds}s\n\n" else: -- cgit v1.2.3 From 3b3f8794cca30b152a7747e3ae7e061328a38ba6 Mon Sep 17 00:00:00 2001 From: Derek Date: Mon, 7 Jan 2019 20:30:30 -0500 Subject: Update method of obtaining last message to be simpler --- bot/cogs/free.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 90caad7ae..cd04275e2 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -46,8 +46,7 @@ class Free: messages = await channel.history(limit=seek).flatten() msg = messages[seek-1] else: - messages = await channel.history(limit=1).flatten() - msg = messages[0] + msg = await channel.history(limit=1).next() inactive = (datetime.utcnow() - msg.created_at).seconds if inactive > self.TIME_INACTIVE: -- cgit v1.2.3 From 623923780bd5bb2aa1c9624e27faa20229c150a7 Mon Sep 17 00:00:00 2001 From: sco1 Date: Tue, 8 Jan 2019 13:40:04 -0500 Subject: Add RLBot to server whitelist Yay partners! --- config-default.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config-default.yml b/config-default.yml index ad87e44ac..4f4c79fa1 100644 --- a/config-default.yml +++ b/config-default.yml @@ -154,6 +154,7 @@ filter: - 267624335836053506 # Python Discord - 440186186024222721 # Python Discord: ModLog Emojis - 273944235143593984 # STEM + - 348658686962696195 # RLBot domain_blacklist: - pornhub.com -- cgit v1.2.3 From e9134a769b39e2cad58d03193d139760d3840bd7 Mon Sep 17 00:00:00 2001 From: sco1 Date: Tue, 8 Jan 2019 13:59:41 -0500 Subject: Add Pallets to server whitelist Yay partners! --- config-default.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config-default.yml b/config-default.yml index 4f4c79fa1..a51d00778 100644 --- a/config-default.yml +++ b/config-default.yml @@ -155,6 +155,7 @@ filter: - 440186186024222721 # Python Discord: ModLog Emojis - 273944235143593984 # STEM - 348658686962696195 # RLBot + - 531221516914917387 # Pallets domain_blacklist: - pornhub.com -- cgit v1.2.3 From 0b8c5f074c725d739fffabb18076519d33a033a7 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Tue, 8 Jan 2019 16:18:43 -0500 Subject: Remove list comprehension since any() works on generators Co-Authored-By: sco1 --- bot/cogs/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/events.py b/bot/cogs/events.py index 77a15733d..b44e5871e 100644 --- a/bot/cogs/events.py +++ b/bot/cogs/events.py @@ -124,7 +124,7 @@ class Events: return False muted_check = any( - [infraction["active"] for infraction in infraction_list if infraction["type"].lower() == "mute"] + infraction["active"] for infraction in infraction_list if infraction["type"].lower() == "mute" ) return muted_check -- cgit v1.2.3 From e8a5db64dc70270488a6b9a43e21470c11936878 Mon Sep 17 00:00:00 2001 From: sco1 Date: Tue, 8 Jan 2019 16:36:54 -0500 Subject: Switch short-circuit logic, add logging --- bot/cogs/events.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bot/cogs/events.py b/bot/cogs/events.py index b44e5871e..78878dcb9 100644 --- a/bot/cogs/events.py +++ b/bot/cogs/events.py @@ -119,7 +119,7 @@ class Events: infraction_list = await response.json() # Check for active mute infractions - if len(infraction_list) == 0: + if not infraction_list: # Short circuit return False @@ -263,6 +263,10 @@ class Events: if role in old_roles: # Check for mute roles that were not able to be removed and skip if present if role == str(Roles.muted) and not await self.has_active_mute(str(member.id)): + log.debug( + f"User {member.id} has no active mute infraction, " + "their leftover muted role will not be persisted" + ) continue new_roles.append(Object(int(role))) -- cgit v1.2.3 From 01a069c26fa2f45e2ad20ab9fc4c612a503b4d73 Mon Sep 17 00:00:00 2001 From: Derek Date: Tue, 8 Jan 2019 16:45:22 -0500 Subject: Add linter exception --- bot/cogs/free.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index cd04275e2..076415ded 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -46,7 +46,7 @@ class Free: messages = await channel.history(limit=seek).flatten() msg = messages[seek-1] else: - msg = await channel.history(limit=1).next() + msg = await channel.history(limit=1).next() # noqa (False positive) inactive = (datetime.utcnow() - msg.created_at).seconds if inactive > self.TIME_INACTIVE: -- cgit v1.2.3 From 25d9b1ea36b03ed431d7262d373124e3f788d408 Mon Sep 17 00:00:00 2001 From: sco1 Date: Tue, 8 Jan 2019 17:34:51 -0500 Subject: From review --- bot/cogs/events.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bot/cogs/events.py b/bot/cogs/events.py index 78878dcb9..f0baecd4b 100644 --- a/bot/cogs/events.py +++ b/bot/cogs/events.py @@ -123,10 +123,9 @@ class Events: # Short circuit return False - muted_check = any( + return any( infraction["active"] for infraction in infraction_list if infraction["type"].lower() == "mute" ) - return muted_check async def on_command_error(self, ctx: Context, e: CommandError): command = ctx.command -- cgit v1.2.3 From 3a209226e76b2ef1e542cd5a35e2571b3a1cc418 Mon Sep 17 00:00:00 2001 From: Derek Date: Wed, 9 Jan 2019 01:45:01 -0500 Subject: Add activity timeout constant --- bot/cogs/free.py | 13 ++++++------- bot/constants.py | 6 ++++++ config-default.yml | 6 ++++++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 076415ded..7447fd941 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -4,18 +4,17 @@ from datetime import datetime from discord import Colour, Embed, Member, utils from discord.ext.commands import BucketType, Context, command, cooldown -from bot.constants import Categories +from bot.constants import Categories, Free log = logging.getLogger(__name__) +PYTHON_HELP_ID = Categories.python_help +TIMEOUT = Free.activity_timeout + class Free: """Tries to figure out which help channels are free.""" - - PYTHON_HELP_ID = Categories.python_help - TIME_INACTIVE = 300 - @command(name="free", aliases=('f',)) @cooldown(1, 60.0, BucketType.channel) async def free(self, ctx: Context, user: Member = None, seek: int = 2): @@ -34,7 +33,7 @@ class Free: in an active channel, and we want the message before that happened. """ free_channels = [] - python_help = utils.get(ctx.guild.categories, id=self.PYTHON_HELP_ID) + python_help = utils.get(ctx.guild.categories, id=PYTHON_HELP_ID) if user is not None and seek == 2: seek = 3 @@ -49,7 +48,7 @@ class Free: msg = await channel.history(limit=1).next() # noqa (False positive) inactive = (datetime.utcnow() - msg.created_at).seconds - if inactive > self.TIME_INACTIVE: + if inactive > TIMEOUT: free_channels.append((inactive, channel)) embed = Embed() diff --git a/bot/constants.py b/bot/constants.py index aae9b05e5..689590c0c 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -471,6 +471,12 @@ class BigBrother(metaclass=YAMLGetter): header_message_limit: int +class Free(metaclass=YAMLGetter): + section = 'free' + + activity_timeout: int + + # Debug mode DEBUG_MODE = True if 'local' in os.environ.get("SITE_URL", "local") else False diff --git a/config-default.yml b/config-default.yml index 1b4e6f412..504d40ed7 100644 --- a/config-default.yml +++ b/config-default.yml @@ -337,5 +337,11 @@ big_brother: header_message_limit: 15 +free: + # Seconds to elapse for a channel + # to be considered inactive. + activity_timeout: 300 + + config: required_keys: ['bot.token'] -- cgit v1.2.3 From e61a818b394a40185b934d67fe7a2a943edf81fc Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Wed, 9 Jan 2019 19:05:06 +0100 Subject: Patch to make \!help work outside of #bot-commands again. We should look into a proper rewrite later. --- bot/cogs/help.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/bot/cogs/help.py b/bot/cogs/help.py index d30ff0dfb..c82a25417 100644 --- a/bot/cogs/help.py +++ b/bot/cogs/help.py @@ -9,11 +9,13 @@ from discord.ext import commands from fuzzywuzzy import fuzz, process from bot import constants +from bot.decorators import InChannelCheckFailure from bot.pagination import ( DELETE_EMOJI, FIRST_EMOJI, LAST_EMOJI, LEFT_EMOJI, LinePaginator, RIGHT_EMOJI, ) + REACTIONS = { FIRST_EMOJI: 'first', LEFT_EMOJI: 'back', @@ -427,7 +429,15 @@ class HelpSession: # see if the user can run the command strikeout = '' - can_run = await command.can_run(self._ctx) + + # Patch to make the !help command work outside of #bot-commands again + # This probably needs a proper rewrite, but this will make it work in + # the mean time. + try: + can_run = await command.can_run(self._ctx) + except InChannelCheckFailure: + can_run = False + if not can_run: # skip if we don't show commands they can't run if self._only_can_run: -- cgit v1.2.3 From 2340509a482d2ed3fce2e3ede456ac49b2a97c43 Mon Sep 17 00:00:00 2001 From: Derek Date: Wed, 9 Jan 2019 17:55:40 -0500 Subject: Add exemption from cooldown for helpers --- bot/cogs/free.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 7447fd941..6b06eaa4c 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -2,9 +2,10 @@ import logging from datetime import datetime from discord import Colour, Embed, Member, utils +from discord.ext import commands from discord.ext.commands import BucketType, Context, command, cooldown -from bot.constants import Categories, Free +from bot.constants import Categories, Free, Roles log = logging.getLogger(__name__) @@ -83,6 +84,26 @@ class Free: await ctx.send(embed=embed) + @free.error + async def free_error(self, ctx: Context, error): + """ + Runs if any error is raised during invocation + of !free command. Any error aside from + CommandOnCooldown is ignored. + + If error raised is CommandOnCooldown, and the + user who invoked has the helper role, reset + the cooldown and reinvoke the command. + """ + helpers = ctx.guild.get_role(Roles.helpers) + + if isinstance(error, commands.CommandOnCooldown): + if helpers in ctx.author.roles: + # reset cooldown so second invocation + # doesn't bring us back here. + ctx.command.reset_cooldown(ctx) + await ctx.invoke(ctx.command) + def setup(bot): bot.add_cog(Free()) -- cgit v1.2.3 From 0f85110040e70376838b380579cac2ccad007914 Mon Sep 17 00:00:00 2001 From: Derek Date: Wed, 9 Jan 2019 18:10:03 -0500 Subject: Put channel category id constant back in class --- bot/cogs/free.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 6b06eaa4c..a66a37f1b 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -10,12 +10,14 @@ from bot.constants import Categories, Free, Roles log = logging.getLogger(__name__) -PYTHON_HELP_ID = Categories.python_help TIMEOUT = Free.activity_timeout class Free: """Tries to figure out which help channels are free.""" + + PYTHON_HELP_ID = Categories.python_help + @command(name="free", aliases=('f',)) @cooldown(1, 60.0, BucketType.channel) async def free(self, ctx: Context, user: Member = None, seek: int = 2): @@ -34,7 +36,7 @@ class Free: in an active channel, and we want the message before that happened. """ free_channels = [] - python_help = utils.get(ctx.guild.categories, id=PYTHON_HELP_ID) + python_help = utils.get(ctx.guild.categories, id=self.PYTHON_HELP_ID) if user is not None and seek == 2: seek = 3 -- cgit v1.2.3 From ee0a38a5671597d200c4927d9e900481727cecf1 Mon Sep 17 00:00:00 2001 From: Derek Date: Wed, 9 Jan 2019 18:11:39 -0500 Subject: Change awkward wording --- bot/cogs/free.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index a66a37f1b..e9c0386fd 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -79,7 +79,7 @@ class Free: embed.description += ("**\nThese channels aren't guaranteed to be free, " "so use your best judgement and check for yourself.") else: - embed.description = ("**Doesn't look like any channels are available to me. " + embed.description = ("**Doesn't look like any channels are available right now. " "You're welcome to check for yourself to be sure. " "If all channels are truly busy, please be patient " "as one will likely be available soon.**") -- cgit v1.2.3 From 61c7b27b3453120771764fbdd8b43fbc504a8882 Mon Sep 17 00:00:00 2001 From: Derek Date: Wed, 9 Jan 2019 18:13:19 -0500 Subject: Change embed color to blurple --- bot/cogs/free.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index e9c0386fd..4b5f3b3bb 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -55,7 +55,7 @@ class Free: free_channels.append((inactive, channel)) embed = Embed() - embed.colour = Colour.gold() + embed.colour = Colour.blurple() embed.title = "**Looking for a free help channel?**" if user is not None: -- cgit v1.2.3 From 5868516da942e6df4f5caa1fa24b5af13e1f3555 Mon Sep 17 00:00:00 2001 From: Derek Date: Wed, 9 Jan 2019 18:19:14 -0500 Subject: Change line to fit prevailing style --- bot/cogs/free.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 4b5f3b3bb..6f0e86330 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -66,7 +66,8 @@ class Free: if free_channels: embed.description += "**The following channel{0} look{1} free:**\n\n**".format( 's' if len(free_channels) > 1 else '', - '' if len(free_channels) > 1 else 's') + '' if len(free_channels) > 1 else 's' + ) for i, (inactive, channel) in enumerate(sorted(free_channels, reverse=True), 1): minutes, seconds = divmod(inactive, 60) -- cgit v1.2.3 From 4313a9c5ed6b052d46f00350b10a8c3d62136c48 Mon Sep 17 00:00:00 2001 From: Derek Date: Wed, 9 Jan 2019 18:36:57 -0500 Subject: Add all the block comments! --- bot/cogs/free.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 6f0e86330..0880cdd25 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -43,10 +43,15 @@ class Free: elif not 0 < seek < 10: seek = 3 + # Iterate through all the help channels + # to check latest activity for channel in python_help.channels: + # Seek further back in the help channel + # the command was invoked in if channel.id == ctx.channel.id: messages = await channel.history(limit=seek).flatten() msg = messages[seek-1] + # Otherwise get last message else: msg = await channel.history(limit=1).next() # noqa (False positive) @@ -63,12 +68,17 @@ class Free: else: embed.description = "" + # Display all potentially inactive channels + # in descending order of inactivity if free_channels: embed.description += "**The following channel{0} look{1} free:**\n\n**".format( 's' if len(free_channels) > 1 else '', '' if len(free_channels) > 1 else 's' ) + # Sort channels in descending order by seconds + # Get position in list, inactivity, and channel object + # For each channel, add to embed.description for i, (inactive, channel) in enumerate(sorted(free_channels, reverse=True), 1): minutes, seconds = divmod(inactive, 60) if minutes > 59: -- cgit v1.2.3 From 40d9ba8a08f6ba6586aea331f8574e2aa3dd03b9 Mon Sep 17 00:00:00 2001 From: Derek Date: Wed, 9 Jan 2019 18:38:41 -0500 Subject: Change activity timeout to 10 minutes --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-default.yml b/config-default.yml index 504d40ed7..7b0468643 100644 --- a/config-default.yml +++ b/config-default.yml @@ -340,7 +340,7 @@ big_brother: free: # Seconds to elapse for a channel # to be considered inactive. - activity_timeout: 300 + activity_timeout: 600 config: -- cgit v1.2.3 From b2929ef2e72d42950169db4a46c064eedc228c4e Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Thu, 10 Jan 2019 16:55:55 +0100 Subject: Adding watch reason to the big-brother header embeds --- bot/cogs/bigbrother.py | 65 +++++++++++++++++++++++++++++++++++++++++++------- config-default.yml | 1 + 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/bot/cogs/bigbrother.py b/bot/cogs/bigbrother.py index 29b13f038..26d35a97c 100644 --- a/bot/cogs/bigbrother.py +++ b/bot/cogs/bigbrother.py @@ -2,8 +2,10 @@ import asyncio import logging import re from collections import defaultdict, deque +from time import strptime from typing import List, Union +from aiohttp import ClientError from discord import Color, Embed, Guild, Member, Message, TextChannel, User from discord.ext.commands import Bot, Context, group @@ -26,13 +28,15 @@ class BigBrother: def __init__(self, bot: Bot): self.bot = bot self.watched_users = {} # { user_id: log_channel_id } + self.watch_reasons = {} # { user_id: watch_reason } self.channel_queues = defaultdict(lambda: defaultdict(deque)) # { user_id: { channel_id: queue(messages) } self.last_log = [None, None, 0] # [user_id, channel_id, message_count] self.consuming = False + self.infraction_watch_prefix = "bb watch: " # Please do not change or we won't be able to find old reasons self.bot.loop.create_task(self.get_watched_users()) - def update_cache(self, api_response: List[dict]): + async def update_cache(self, api_response: List[dict]): """ Updates the internal cache of watched users from the given `api_response`. This function will only add (or update) existing keys, it will not delete @@ -54,13 +58,52 @@ class BigBrother: "but the given channel could not be found. Ignoring." ) + watch_reason = await self.get_watch_reason(user_id) + self.watch_reasons[user_id] = watch_reason + async def get_watched_users(self): """Retrieves watched users from the API.""" await self.bot.wait_until_ready() async with self.bot.http_session.get(URLs.site_bigbrother_api, headers=self.HEADERS) as response: data = await response.json() - self.update_cache(data) + await self.update_cache(data) + + async def get_watch_reason(self, user_id: int) -> str: + """ Fetches and returns the latest watch reason for a user using the infraction API """ + + re_bb_watch = rf"^{self.infraction_watch_prefix}" + user_id = str(user_id) + + try: + response = await self.bot.http_session.get( + URLs.site_infractions_user_type.format( + user_id=user_id, + infraction_type="note", + ), + params={"search": re_bb_watch, "hidden": "True", "active": "False"}, + headers=self.HEADERS + ) + infraction_list = await response.json() + except ClientError: + log.exception(f"Failed to retrieve bb watch reason for {user_id}.") + return "(error retrieving bb reason)" + + if infraction_list: + latest_reason_infraction = max(infraction_list, key=self._parse_time) + latest_reason = latest_reason_infraction['reason'][10:] + log.trace(f"The latest bb watch reason for {user_id}: {latest_reason}") + return latest_reason + + log.trace(f"No bb watch reason found for {user_id}; returning default string") + return "(no reason specified)" + + @staticmethod + def _parse_time(infraction): + """Takes RFC1123 date_time string and returns time object for sorting purposes""" + + date_string = infraction["inserted_at"] + return strptime(date_string, "%a, %d %b %Y %H:%M:%S %Z") async def on_member_ban(self, guild: Guild, user: Union[User, Member]): if guild.id == GuildConfig.id and user.id in self.watched_users: @@ -70,6 +113,7 @@ class BigBrother: async with self.bot.http_session.delete(url, headers=self.HEADERS) as response: del self.watched_users[user.id] del self.channel_queues[user.id] + del self.watch_reasons[user.id] if response.status == 204: await channel.send( f"{Emojis.bb_message}:hammer: {user} got banned, so " @@ -143,6 +187,7 @@ class BigBrother: embed = Embed(description=f"{message.author.mention} in [#{message.channel.name}]({message.jump_url})") embed.set_author(name=message.author.nick or message.author.name, icon_url=message.author.avatar_url) + embed.set_footer(text=f"Watch reason: {self.watch_reasons[message.author.id]}") await destination.send(embed=embed) @staticmethod @@ -201,7 +246,7 @@ class BigBrother: async with self.bot.http_session.get(URLs.site_bigbrother_api, headers=self.HEADERS) as response: if response.status == 200: data = await response.json() - self.update_cache(data) + await self.update_cache(data) lines = tuple(f"• <@{entry['user_id']}> in <#{entry['channel_id']}>" for entry in data) await LinePaginator.paginate( @@ -246,15 +291,15 @@ class BigBrother: ) else: self.watched_users[user.id] = channel + self.watch_reasons[user.id] = reason + # Add a note (shadow warning) with the reason for watching + reason = f"{self.infraction_watch_prefix}{reason}" + await post_infraction(ctx, user, type="warning", reason=reason, hidden=True) else: data = await response.json() - reason = data.get('error_message', "no message provided") - await ctx.send(f":x: the API returned an error: {reason}") - - # Add a note (shadow warning) with the reason for watching - reason = "bb watch: " + reason # Prepend for situational awareness - await post_infraction(ctx, user, type="warning", reason=reason, hidden=True) + error_reason = data.get('error_message', "no message provided") + await ctx.send(f":x: the API returned an error: {error_reason}") @bigbrother_group.command(name='unwatch', aliases=('uw',)) @with_role(Roles.owner, Roles.admin, Roles.moderator) @@ -270,6 +315,8 @@ class BigBrother: del self.watched_users[user.id] if user.id in self.channel_queues: del self.channel_queues[user.id] + if user.id in self.watch_reasons: + del self.watch_reasons[user.id] else: log.warning(f"user {user.id} was unwatched but was not found in the cache") diff --git a/config-default.yml b/config-default.yml index 21d7f20b9..1a5a63c6a 100644 --- a/config-default.yml +++ b/config-default.yml @@ -240,6 +240,7 @@ urls: site_infractions_type: !JOIN [*SCHEMA, *API, "/bot/infractions/type/{infraction_type}"] site_infractions_by_id: !JOIN [*SCHEMA, *API, "/bot/infractions/id/{infraction_id}"] site_infractions_user_type_current: !JOIN [*SCHEMA, *API, "/bot/infractions/user/{user_id}/{infraction_type}/current"] + site_infractions_user_type: !JOIN [*SCHEMA, *API, "/bot/infractions/user/{user_id}/{infraction_type}"] site_logs_api: !JOIN [*SCHEMA, *API, "/bot/logs"] site_logs_view: !JOIN [*SCHEMA, *DOMAIN, "/bot/logs"] site_names_api: !JOIN [*SCHEMA, *API, "/bot/snake_names"] -- cgit v1.2.3 From f113c2bed932f52439b1185b96a03c6e3ae03c8e Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Thu, 10 Jan 2019 17:03:45 +0100 Subject: Adding type annotations --- bot/cogs/bigbrother.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/cogs/bigbrother.py b/bot/cogs/bigbrother.py index 26d35a97c..b325fa5fe 100644 --- a/bot/cogs/bigbrother.py +++ b/bot/cogs/bigbrother.py @@ -2,7 +2,7 @@ import asyncio import logging import re from collections import defaultdict, deque -from time import strptime +from time import strptime, struct_time from typing import List, Union from aiohttp import ClientError @@ -99,7 +99,7 @@ class BigBrother: return "(no reason specified)" @staticmethod - def _parse_time(infraction): + def _parse_time(infraction: str) -> struct_time: """Takes RFC1123 date_time string and returns time object for sorting purposes""" date_string = infraction["inserted_at"] -- cgit v1.2.3 From 66e476f9ca024c5e6e2917679aaa4da03ef69acd Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Thu, 10 Jan 2019 17:37:20 +0100 Subject: Removing default argument for the alias watch to require a reason via the alias as well --- bot/cogs/alias.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/alias.py b/bot/cogs/alias.py index 2ce4a51e3..0b848c773 100644 --- a/bot/cogs/alias.py +++ b/bot/cogs/alias.py @@ -71,7 +71,7 @@ class Alias: @command(name="watch", hidden=True) async def bigbrother_watch_alias( - self, ctx, user: User, *, reason: str = None + self, ctx, user: User, *, reason: str ): """ Alias for invoking bigbrother watch user [text_channel]. -- cgit v1.2.3 From 86440dd8ad355d157a0ebf8250d7abe7d56c5982 Mon Sep 17 00:00:00 2001 From: Derek Date: Thu, 10 Jan 2019 17:21:43 -0500 Subject: Update error handler to log errors instead of ignore them --- bot/cogs/free.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 0880cdd25..b8e9f65d0 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -115,7 +115,10 @@ class Free: # reset cooldown so second invocation # doesn't bring us back here. ctx.command.reset_cooldown(ctx) - await ctx.invoke(ctx.command) + # return to avoid needlessly logging the error + return await ctx.invoke(ctx.command) + + log.error(error) # Don't ignore other errors def setup(bot): -- cgit v1.2.3 From d46fed40b335060f7d1652cff6eb58912b824e0b Mon Sep 17 00:00:00 2001 From: Derek Date: Thu, 10 Jan 2019 17:27:57 -0500 Subject: Add 2nd space to inline comment to obey allmighty linter --- bot/cogs/free.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index b8e9f65d0..acd1dc108 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -118,7 +118,7 @@ class Free: # return to avoid needlessly logging the error return await ctx.invoke(ctx.command) - log.error(error) # Don't ignore other errors + log.error(error) # Don't ignore other errors def setup(bot): -- cgit v1.2.3 From c55fa67e21a6a10feb0738b3bacd6b0dba1d4de9 Mon Sep 17 00:00:00 2001 From: Derek Date: Thu, 10 Jan 2019 17:58:19 -0500 Subject: Add cooldown constants to config --- bot/cogs/free.py | 4 +++- bot/constants.py | 2 ++ config-default.yml | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index acd1dc108..8d413a69b 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -11,6 +11,8 @@ from bot.constants import Categories, Free, Roles log = logging.getLogger(__name__) TIMEOUT = Free.activity_timeout +RATE = Free.cooldown_rate +PER = Free.cooldown_per class Free: @@ -19,7 +21,7 @@ class Free: PYTHON_HELP_ID = Categories.python_help @command(name="free", aliases=('f',)) - @cooldown(1, 60.0, BucketType.channel) + @cooldown(RATE, PER, BucketType.channel) async def free(self, ctx: Context, user: Member = None, seek: int = 2): """ Lists free help channels by likeliness of availability. diff --git a/bot/constants.py b/bot/constants.py index 1bb602eb2..be713cef2 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -477,6 +477,8 @@ class Free(metaclass=YAMLGetter): section = 'free' activity_timeout: int + cooldown_rate: int + cooldown_per: float # Debug mode diff --git a/config-default.yml b/config-default.yml index 3db7b2025..f462b8199 100644 --- a/config-default.yml +++ b/config-default.yml @@ -343,6 +343,8 @@ free: # Seconds to elapse for a channel # to be considered inactive. activity_timeout: 600 + cooldown_rate: 1 + cooldown_per: 60.0 config: -- cgit v1.2.3 From e1bd2c37693e863738fb5eddcd0f46ae9e484f1f Mon Sep 17 00:00:00 2001 From: Derek Date: Thu, 10 Jan 2019 18:04:06 -0500 Subject: Put extra sentence in docstring clarifying arg usage --- bot/cogs/free.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 8d413a69b..0010b4a90 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -29,6 +29,7 @@ class Free: :param seek: How far back to check the last active message. seek is used only when this command is invoked in a help channel. + You cannot override seek without mentioning a user first. When seek is 2, we are avoiding considering the last active message in a channel to be the one that invoked this command. -- cgit v1.2.3 From d8db79581a84c1d8adf0a297d5390c4c3f519aba Mon Sep 17 00:00:00 2001 From: Derek Date: Thu, 10 Jan 2019 18:09:14 -0500 Subject: Update error handler docstring to be more accurate --- bot/cogs/free.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 0010b4a90..4be804881 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -103,13 +103,11 @@ class Free: @free.error async def free_error(self, ctx: Context, error): """ - Runs if any error is raised during invocation - of !free command. Any error aside from - CommandOnCooldown is ignored. - If error raised is CommandOnCooldown, and the user who invoked has the helper role, reset the cooldown and reinvoke the command. + + Otherwise log the error. """ helpers = ctx.guild.get_role(Roles.helpers) -- cgit v1.2.3 From a2f8b21adf7880a116ae9f80e95cd7e696e7e135 Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Fri, 11 Jan 2019 09:24:57 +0100 Subject: Only retrieve/cache watch reason when user becomes active; restore update_cache to synchronous as it was before --- bot/cogs/bigbrother.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/bot/cogs/bigbrother.py b/bot/cogs/bigbrother.py index b325fa5fe..70916cd7b 100644 --- a/bot/cogs/bigbrother.py +++ b/bot/cogs/bigbrother.py @@ -36,7 +36,7 @@ class BigBrother: self.bot.loop.create_task(self.get_watched_users()) - async def update_cache(self, api_response: List[dict]): + def update_cache(self, api_response: List[dict]): """ Updates the internal cache of watched users from the given `api_response`. This function will only add (or update) existing keys, it will not delete @@ -58,16 +58,13 @@ class BigBrother: "but the given channel could not be found. Ignoring." ) - watch_reason = await self.get_watch_reason(user_id) - self.watch_reasons[user_id] = watch_reason - async def get_watched_users(self): """Retrieves watched users from the API.""" await self.bot.wait_until_ready() async with self.bot.http_session.get(URLs.site_bigbrother_api, headers=self.HEADERS) as response: data = await response.json() - await self.update_cache(data) + self.update_cache(data) async def get_watch_reason(self, user_id: int) -> str: """ Fetches and returns the latest watch reason for a user using the infraction API """ @@ -90,8 +87,8 @@ class BigBrother: return "(error retrieving bb reason)" if infraction_list: - latest_reason_infraction = max(infraction_list, key=self._parse_time) - latest_reason = latest_reason_infraction['reason'][10:] + latest_reason_infraction = max(infraction_list, key=self._parse_infraction_time) + latest_reason = latest_reason_infraction['reason'][len(self.infraction_watch_prefix):] log.trace(f"The latest bb watch reason for {user_id}: {latest_reason}") return latest_reason @@ -99,7 +96,7 @@ class BigBrother: return "(no reason specified)" @staticmethod - def _parse_time(infraction: str) -> struct_time: + def _parse_infraction_time(infraction: str) -> struct_time: """Takes RFC1123 date_time string and returns time object for sorting purposes""" date_string = infraction["inserted_at"] @@ -183,6 +180,12 @@ class BigBrother: # Send header if user/channel are different or if message limit exceeded. if message.author.id != last_user or message.channel.id != last_channel or msg_count > limit: + # Retrieve watch reason from API if it's not already in the cache + if message.author.id not in self.watch_reasons: + log.trace(f"No watch reason for {message.author.id} found in cache; retrieving from API") + user_watch_reason = await self.get_watch_reason(message.author.id) + self.watch_reasons[message.author.id] = user_watch_reason + self.last_log = [message.author.id, message.channel.id, 0] embed = Embed(description=f"{message.author.mention} in [#{message.channel.name}]({message.jump_url})") @@ -246,7 +249,7 @@ class BigBrother: async with self.bot.http_session.get(URLs.site_bigbrother_api, headers=self.HEADERS) as response: if response.status == 200: data = await response.json() - await self.update_cache(data) + self.update_cache(data) lines = tuple(f"• <@{entry['user_id']}> in <#{entry['channel_id']}>" for entry in data) await LinePaginator.paginate( -- cgit v1.2.3 From 5dd611793c598508c5be8868725ca5400ad0c304 Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Fri, 11 Jan 2019 11:01:53 +0100 Subject: Using stronger language in the message and emphazising the 'strongly recommend' with bold --- bot/cogs/token_remover.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bot/cogs/token_remover.py b/bot/cogs/token_remover.py index 8277513a7..c1a0e18ba 100644 --- a/bot/cogs/token_remover.py +++ b/bot/cogs/token_remover.py @@ -16,8 +16,9 @@ log = logging.getLogger(__name__) DELETION_MESSAGE_TEMPLATE = ( "Hey {mention}! I noticed you posted a seemingly valid Discord API " - "token in your message and have removed your message to prevent abuse. " - "We recommend regenerating your token regardless, which you can do here: " + "token in your message and have removed your message. " + "We **strongly recommend** regenerating your token as it's probably " + "been compromised. You can do that here: " "\n" "Feel free to re-post it with the token removed. " "If you believe this was a mistake, please let us know!" -- cgit v1.2.3 From 8f30b52fd378bb3546c84d0fdb945a4b492236b8 Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Fri, 11 Jan 2019 15:06:12 +0100 Subject: Catching the superclass CheckFailure instead of the subclass --- bot/cogs/help.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/cogs/help.py b/bot/cogs/help.py index c82a25417..ded068123 100644 --- a/bot/cogs/help.py +++ b/bot/cogs/help.py @@ -6,10 +6,10 @@ from contextlib import suppress from discord import Colour, Embed, HTTPException from discord.ext import commands +from discord.ext.commands import CheckFailure from fuzzywuzzy import fuzz, process from bot import constants -from bot.decorators import InChannelCheckFailure from bot.pagination import ( DELETE_EMOJI, FIRST_EMOJI, LAST_EMOJI, LEFT_EMOJI, LinePaginator, RIGHT_EMOJI, @@ -435,7 +435,7 @@ class HelpSession: # the mean time. try: can_run = await command.can_run(self._ctx) - except InChannelCheckFailure: + except CheckFailure: can_run = False if not can_run: -- cgit v1.2.3 From 0651779383423ad08b860cde79d29c3e00dca677 Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Fri, 11 Jan 2019 15:14:43 +0100 Subject: Revert "Catching the superclass CheckFailure instead of the subclass" This reverts commit 8f30b52fd378bb3546c84d0fdb945a4b492236b8. Accidentally pushed to master when I thought I was at a branch --- bot/cogs/help.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/cogs/help.py b/bot/cogs/help.py index ded068123..c82a25417 100644 --- a/bot/cogs/help.py +++ b/bot/cogs/help.py @@ -6,10 +6,10 @@ from contextlib import suppress from discord import Colour, Embed, HTTPException from discord.ext import commands -from discord.ext.commands import CheckFailure from fuzzywuzzy import fuzz, process from bot import constants +from bot.decorators import InChannelCheckFailure from bot.pagination import ( DELETE_EMOJI, FIRST_EMOJI, LAST_EMOJI, LEFT_EMOJI, LinePaginator, RIGHT_EMOJI, @@ -435,7 +435,7 @@ class HelpSession: # the mean time. try: can_run = await command.can_run(self._ctx) - except CheckFailure: + except InChannelCheckFailure: can_run = False if not can_run: -- cgit v1.2.3 From 3905e8ff52ae652c94a1ff0372aa044709060774 Mon Sep 17 00:00:00 2001 From: sco1 Date: Fri, 11 Jan 2019 09:48:50 -0500 Subject: Disable rich embed filter Discord adding the embeds is causing it to trigger. --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-default.yml b/config-default.yml index 21d7f20b9..866a5b5ab 100644 --- a/config-default.yml +++ b/config-default.yml @@ -137,7 +137,7 @@ filter: filter_zalgo: false filter_invites: true filter_domains: true - filter_rich_embeds: true + filter_rich_embeds: false watch_words: true watch_tokens: true -- cgit v1.2.3 From 4bc92be7c4831fa3b714d7091700d587f8f62373 Mon Sep 17 00:00:00 2001 From: sco1 Date: Fri, 11 Jan 2019 22:39:15 -0500 Subject: Add edit delta to modlog for multi-edit messages To help with self-bot detection, if a message has been previously edited, generate a human-readable delta between the last edit and the new one Use message timestamp for modlog embeds generated during on_message event Visually separate send_log_message kwargs to make them easier to read --- bot/cogs/modlog.py | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/bot/cogs/modlog.py b/bot/cogs/modlog.py index 06f81cb36..bded3baa0 100644 --- a/bot/cogs/modlog.py +++ b/bot/cogs/modlog.py @@ -104,9 +104,19 @@ 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, content: str = None, additional_embeds: List[Embed] = 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, + additional_embeds: List[Embed] = None, + timestamp_override: datetime.datetime = None, + footer_override: str = None, ): embed = Embed(description=text) @@ -114,7 +124,14 @@ class ModLog: embed.set_author(name=title, icon_url=icon_url) embed.colour = colour - embed.timestamp = datetime.datetime.utcnow() + + if timestamp_override: + embed.timestamp = timestamp_override + else: + embed.timestamp = datetime.datetime.utcnow() + + if footer_override: + embed.set_footer(text=footer_override) if thumbnail is not None: embed.set_thumbnail(url=thumbnail) @@ -676,14 +693,28 @@ class ModLog: f"{after.clean_content}" ) + if before.edited_at: + # Message was previously edited, to assist with self-bot detection, use the edited_at + # datetime as the baseline and create a human-readable delta between this edit event + # and the last time the message was edited + timestamp = before.edited_at + delta = humanize_delta(relativedelta(after.edited_at, before.edited_at)) + footer = f"Last edited {delta} ago" + else: + # Message was not previously edited, use the created_at datetime as the baseline, no + # delta calculation needed + timestamp = before.created_at + footer = None + + print(timestamp, footer) await self.send_log_message( - Icons.message_edit, Colour.blurple(), "Message edited (Before)", - before_response, channel_id=Channels.message_log + Icons.message_edit, Colour.blurple(), "Message edited (Before)", before_response, + channel_id=Channels.message_log, timestamp_override=timestamp, footer_override=footer ) await self.send_log_message( - Icons.message_edit, Colour.blurple(), "Message edited (After)", - after_response, channel_id=Channels.message_log + Icons.message_edit, Colour.blurple(), "Message edited (After)", after_response, + channel_id=Channels.message_log, timestamp_override=after.edited_at ) async def on_raw_message_edit(self, event: RawMessageUpdateEvent): -- cgit v1.2.3 From ddfb1f4689c54a8f7adccd90bd9038e69ff67168 Mon Sep 17 00:00:00 2001 From: sco1 Date: Fri, 11 Jan 2019 23:12:07 -0500 Subject: Remove debug print statement --- bot/cogs/modlog.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bot/cogs/modlog.py b/bot/cogs/modlog.py index bded3baa0..76a5eff58 100644 --- a/bot/cogs/modlog.py +++ b/bot/cogs/modlog.py @@ -706,7 +706,6 @@ class ModLog: timestamp = before.created_at footer = None - print(timestamp, footer) await self.send_log_message( Icons.message_edit, Colour.blurple(), "Message edited (Before)", before_response, channel_id=Channels.message_log, timestamp_override=timestamp, footer_override=footer -- cgit v1.2.3 From 4dc7ba5b54ab8de7f86f5239b956d94d80146c85 Mon Sep 17 00:00:00 2001 From: SebastiaanZ <33516116+SebastiaanZ@users.noreply.github.com> Date: Sat, 12 Jan 2019 15:04:17 +0100 Subject: Changing check-specific exception to superclass exception so help doesn't break when new check exceptions are added --- bot/cogs/help.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/cogs/help.py b/bot/cogs/help.py index c82a25417..ded068123 100644 --- a/bot/cogs/help.py +++ b/bot/cogs/help.py @@ -6,10 +6,10 @@ from contextlib import suppress from discord import Colour, Embed, HTTPException from discord.ext import commands +from discord.ext.commands import CheckFailure from fuzzywuzzy import fuzz, process from bot import constants -from bot.decorators import InChannelCheckFailure from bot.pagination import ( DELETE_EMOJI, FIRST_EMOJI, LAST_EMOJI, LEFT_EMOJI, LinePaginator, RIGHT_EMOJI, @@ -435,7 +435,7 @@ class HelpSession: # the mean time. try: can_run = await command.can_run(self._ctx) - except InChannelCheckFailure: + except CheckFailure: can_run = False if not can_run: -- cgit v1.2.3 From e4a707157fe9cadef5debef67779a5443b48d11e Mon Sep 17 00:00:00 2001 From: sco1 Date: Sat, 12 Jan 2019 13:16:58 -0500 Subject: Add Optional type hints where appropriate --- bot/cogs/modlog.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bot/cogs/modlog.py b/bot/cogs/modlog.py index 76a5eff58..589052b1e 100644 --- a/bot/cogs/modlog.py +++ b/bot/cogs/modlog.py @@ -109,14 +109,14 @@ class ModLog: colour: Colour, title: Optional[str], text: str, - thumbnail: str = None, + thumbnail: Optional[str] = None, channel_id: int = Channels.modlog, ping_everyone: bool = False, - files: List[File] = None, - content: str = None, - additional_embeds: List[Embed] = None, - timestamp_override: datetime.datetime = None, - footer_override: str = None, + files: Optional[List[File]] = None, + content: Optional[str] = None, + additional_embeds: Optional[List[Embed]] = None, + timestamp_override: Optional[datetime.datetime] = None, + footer_override: Optional[str] = None, ): embed = Embed(description=text) -- cgit v1.2.3 From 3fc94a97dc88504c29985fff735b346e2122c4a2 Mon Sep 17 00:00:00 2001 From: sco1 Date: Sat, 12 Jan 2019 13:22:11 -0500 Subject: Condense logic --- bot/cogs/modlog.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/bot/cogs/modlog.py b/bot/cogs/modlog.py index 589052b1e..55611c5e4 100644 --- a/bot/cogs/modlog.py +++ b/bot/cogs/modlog.py @@ -125,15 +125,12 @@ class ModLog: embed.colour = colour - if timestamp_override: - embed.timestamp = timestamp_override - else: - embed.timestamp = datetime.datetime.utcnow() + embed.timestamp = timestamp_override or datetime.datetime.utcnow() if footer_override: embed.set_footer(text=footer_override) - if thumbnail is not None: + if thumbnail: embed.set_thumbnail(url=thumbnail) if ping_everyone: -- cgit v1.2.3 From c94189cbfae4b1788773af3bb7ec32ba32caeb12 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Sat, 12 Jan 2019 16:36:04 -0500 Subject: Change ctx.invoke to ctx.reinvoke to conserve passed arguments Co-Authored-By: fiskenslakt --- bot/cogs/free.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 4be804881..e310d9cc7 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -117,7 +117,7 @@ class Free: # doesn't bring us back here. ctx.command.reset_cooldown(ctx) # return to avoid needlessly logging the error - return await ctx.invoke(ctx.command) + return await ctx.reinvoke() log.error(error) # Don't ignore other errors -- cgit v1.2.3 From 240b33719d48716762461ee8eddbeb28ff460a03 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Sat, 12 Jan 2019 16:46:14 -0500 Subject: Change log.error to log.exception to avoid hiding traceback Co-Authored-By: fiskenslakt --- bot/cogs/free.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index e310d9cc7..620449f7e 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -119,7 +119,7 @@ class Free: # return to avoid needlessly logging the error return await ctx.reinvoke() - log.error(error) # Don't ignore other errors + log.exception(error) # Don't ignore other errors def setup(bot): -- cgit v1.2.3 From 3d1d5e692655a50d0f5e88f440ddb056d4426b3b Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 13 Jan 2019 00:03:31 +0100 Subject: Adressing jchrists review comments --- Pipfile.lock | 228 +++++++++++++++++++++++++----------------------- bot/cogs/information.py | 7 +- 2 files changed, 122 insertions(+), 113 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 02b9d0359..8dea91451 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -90,11 +90,11 @@ }, "beautifulsoup4": { "hashes": [ - "sha256:194ec62a25438adcb3fdb06378b26559eda1ea8a747367d34c33cef9c7f48d57", - "sha256:90f8e61121d6ae58362ce3bed8cd997efb00c914eae0ff3d363c32f9a9822d10", - "sha256:f0abd31228055d698bb392a826528ea08ebb9959e6bea17c606fd9c9009db938" + "sha256:034740f6cb549b4e932ae1ab975581e6103ac8f942200a0e9759065984391858", + "sha256:945065979fb8529dd2f37dbb58f00b661bdbcbebf954f93b32fdf5263ef35348", + "sha256:ba6d5c59906a85ac23dadfe5c88deaf3e179ef565f4898671253e50a78680718" ], - "version": "==4.6.3" + "version": "==4.7.1" }, "certifi": { "hashes": [ @@ -232,39 +232,35 @@ }, "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:0dd6589fa75d369ba06d2b5f38dae107f76ea127f212f6a7bee134f6df2d1d21", + "sha256:1afbac344aa68c29e81ab56c1a9411c3663157b5aee5065b7fa030b398d4f7e0", + "sha256:1baad9d073692421ad5dbbd81430aba6c7f5fdc347f03537ae046ddf2c9b2297", + "sha256:1d8736421a2358becd3edf20260e41a06a0bf08a560480d3a5734a6bcbacf591", + "sha256:1e1d9bddc5afaddf0de76246d3f2152f961697ad7439c559f179002682c45801", + "sha256:1f179dc8b2643715f020f4d119d5529b02cd794c1c8f305868b73b8674d2a03f", + "sha256:241fb7bdf97cb1df1edfa8f0bcdfd80525d4023dac4523a241907c8b2f44e541", + "sha256:2f9765ee5acd3dbdcdc0d0c79309e01f7c16bc8d39b49250bf88de7b46daaf58", + "sha256:312e1e1b1c3ce0c67e0b8105317323e12807955e8186872affb667dbd67971f6", + "sha256:3273db1a8055ca70257fd3691c6d2c216544e1a70b673543e15cc077d8e9c730", + "sha256:34dfaa8c02891f9a246b17a732ca3e99c5e42802416628e740a5d1cb2f50ff49", + "sha256:3aa3f5288af349a0f3a96448ebf2e57e17332d99f4f30b02093b7948bd9f94cc", + "sha256:51102e160b9d83c1cc435162d90b8e3c8c93b28d18d87b60c56522d332d26879", + "sha256:56115fc2e2a4140e8994eb9585119a1ae9223b506826089a3ba753a62bd194a6", + "sha256:69d83de14dbe8fe51dccfd36f88bf0b40f5debeac763edf9f8325180190eba6e", + "sha256:99fdce94aeaa3ccbdfcb1e23b34273605c5853aa92ec23d84c84765178662c6c", + "sha256:a7c0cd5b8a20f3093ee4a67374ccb3b8a126743b15a4d759e2a1bf098faac2b2", + "sha256:abe12886554634ed95416a46701a917784cb2b4c77bfacac6916681d49bbf83d", + "sha256:b4f67b5183bd5f9bafaeb76ad119e977ba570d2b0e61202f534ac9b5c33b4485", + "sha256:bdd7c1658475cc1b867b36d5c4ed4bc316be8d3368abe03d348ba906a1f83b0e", + "sha256:c6f24149a19f611a415a51b9bc5f17b6c2f698e0d6b41ffb3fa9f24d35d05d73", + "sha256:d1e111b3ab98613115a208c1017f266478b0ab224a67bc8eac670fa0bad7d488", + "sha256:d6520aa965773bbab6cb7a791d5895b00d02cf9adc93ac2bf4edb9ac1a6addc5", + "sha256:dd185cde2ccad7b649593b0cda72021bc8a91667417001dbaf24cd746ecb7c11", + "sha256:de2e5b0828a9d285f909b5d2e9d43f1cf6cf21fe65bc7660bdaa1780c7b58298", + "sha256:f726444b8e909c4f41b4fde416e1071cf28fa84634bfb4befdf400933b6463af" ], "index": "pypi", - "version": "==4.2.5" + "version": "==4.3.0" }, "markdownify": { "hashes": [ @@ -349,85 +345,88 @@ }, "pillow": { "hashes": [ - "sha256:00203f406818c3f45d47bb8fe7e67d3feddb8dcbbd45a289a1de7dd789226360", - "sha256:0616f800f348664e694dddb0b0c88d26761dd5e9f34e1ed7b7a7d2da14b40cb7", - "sha256:091136f2a37e9ed6bd8ce96fbf5269199ba6edee490d64de7ac934316f31ecca", - "sha256:0d67ae9a5937b1348fa1d97c7dcb6b56aaef828ca6655298e96f2f3114ad829d", - "sha256:0e1aaddd00ee9014fe7a61b9da61427233fcd7c7f193b5efd6689e0ec36bc42f", - "sha256:1f7908aab90c92ad85af9d2fec5fc79456a89b3adcc26314d2cde0e238bd789e", - "sha256:2ea3517cd5779843de8a759c2349a3cd8d3893e03ab47053b66d5ec6f8bc4f93", - "sha256:39b662f65a067709a62943003c1e807d140e7fcf631fcfc66ebe905f8149b9f4", - "sha256:3ddc19447cf42ef3ec564ab7ebbd4f67838ba9816d739befe29dd70149c775bd", - "sha256:48a9f0538c91fc136b3a576bee0e7cd174773dc9920b310c21dcb5519722e82c", - "sha256:5280ebc42641a1283b7b1f2c20e5b936692198b9dd9995527c18b794850be1a8", - "sha256:576a8a7a57065dab968d9d18befa2594a7673dcdab78c9b1f34248410cc6118f", - "sha256:5e334a23c8f7cb6079987a2ed9978821a42b4323a3a3bdbc132945348737f9a9", - "sha256:5e34e4b5764af65551647f5cc67cf5198c1d05621781d5173b342e5e55bf023b", - "sha256:63b120421ab85cad909792583f83b6ca3584610c2fe70751e23f606a3c2e87f0", - "sha256:696b5e0109fe368d0057f484e2e91717b49a03f1e310f857f133a4acec9f91dd", - "sha256:6cb528de694f503ea164541c151da6c18267727a7558e0c9716cc0383d89658a", - "sha256:7306d851d5a0cfac9ea07f1177783836f4b37292e5f224a534a52111cb6a6451", - "sha256:7e3e32346d991f1788026917d0a9c182d6d32dc757163eee7ca990f1f831499e", - "sha256:870ed021a42b1b02b5fe4a739ea735f671a84128c0a666c705db2cb9abd528eb", - "sha256:916da1c19e4012d06a372127d7140dae894806fad67ef44330e5600d77833581", - "sha256:9303a289fa0811e1c6abd9ddebfc770556d7c3311cb2b32eff72164ddc49bc64", - "sha256:9577888ecc0ad7d06c3746afaba339c94d62b59da16f7a5d1cff9e491f23dace", - "sha256:987e1c94a33c93d9b209315bfda9faa54b8edfce6438a1e93ae866ba20de5956", - "sha256:99a3bbdbb844f4fb5d6dd59fac836a40749781c1fa63c563bc216c27aef63f60", - "sha256:99db8dc3097ceafbcff9cb2bff384b974795edeb11d167d391a02c7bfeeb6e16", - "sha256:a379526415f54f9462bc65a4da76fb0acc05e3b2a21717dde79621cf4377e0e6", - "sha256:a5a96cf49eb580756a44ecf12949e52f211e20bffbf5a95760ac14b1e499cd37", - "sha256:a844b5d8120f99fb7cd276ff544ac5bd562b0c053760d59694e6bf747c6ca7f5", - "sha256:a9284368e81a67a7f47d5ef1ef7e4f11a4f688485879f44cf5f9090bba1f9d94", - "sha256:aa6ca3eb56704cdc0d876fc6047ffd5ee960caad52452fbee0f99908a141a0ae", - "sha256:aade5e66795c94e4a2b2624affeea8979648d1b0ae3fcee17e74e2c647fc4a8a", - "sha256:b78905860336c1d292409e3df6ad39cc1f1c7f0964e66844bbc2ebfca434d073", - "sha256:b92f521cdc4e4a3041cc343625b699f20b0b5f976793fb45681aac1efda565f8", - "sha256:bb2baf44e97811687893873eab8cf9f18b40321cc15d15ff9f91dc031e30631f", - "sha256:bfde84bbd6ae5f782206d454b67b7ee8f7f818c29b99fd02bf022fd33bab14cb", - "sha256:c2b62d3df80e694c0e4a0ed47754c9480521e25642251b3ab1dff050a4e60409", - "sha256:c55d348c1c65896c1bd804527de4880d251ae832acf90d74ad525bb79e77d55c", - "sha256:c5e2be6c263b64f6f7656e23e18a4a9980cffc671442795682e8c4e4f815dd9f", - "sha256:c99aa3c63104e0818ec566f8ff3942fb7c7a8f35f9912cb63fd8e12318b214b2", - "sha256:dae06620d3978da346375ebf88b9e2dd7d151335ba668c995aea9ed07af7add4", - "sha256:db5499d0710823fa4fb88206050d46544e8f0e0136a9a5f5570b026584c8fd74", - "sha256:dcd3cd17d291e01e47636101c4a6638ffb44c842d009973e3b5c1b67ff718c58", - "sha256:f12df6b45abc18f27f6e21ce26f7cbf7aa19820911462e46536e22085658ca1e", - "sha256:f36baafd82119c4a114b9518202f2a983819101dcc14b26e43fc12cbefdce00e", - "sha256:f52b79c8796d81391ab295b04e520bda6feed54d54931708872e8f9ae9db0ea1", - "sha256:fa2a50f762d06d84125db0b95d0121e9c640afa7edc23fc0848896760a390f8e", - "sha256:fa49bb60792b542b95ca93a39041e7113843093ce3cfd216870118eb3798fcc9", - "sha256:ff8cff01582fa1a7e533cb97f628531c4014af4b5f38e33cdcfe5eec29b6d888", - "sha256:ffbccfe1c077b5f41738bd719518213c217be7a7a12a7e74113d05a0d6617390" + "sha256:01a501be4ae05fd714d269cb9c9f145518e58e73faa3f140ddb67fae0c2607b1", + "sha256:051de330a06c99d6f84bcf582960487835bcae3fc99365185dc2d4f65a390c0e", + "sha256:07c35919f983c2c593498edcc126ad3a94154184899297cc9d27a6587672cbaa", + "sha256:0ae5289948c5e0a16574750021bd8be921c27d4e3527800dc9c2c1d2abc81bf7", + "sha256:0b1efce03619cdbf8bcc61cfae81fcda59249a469f31c6735ea59badd4a6f58a", + "sha256:0cf0208500df8d0c3cad6383cd98a2d038b0678fd4f777a8f7e442c5faeee81d", + "sha256:163136e09bd1d6c6c6026b0a662976e86c58b932b964f255ff384ecc8c3cefa3", + "sha256:18e912a6ccddf28defa196bd2021fe33600cbe5da1aa2f2e2c6df15f720b73d1", + "sha256:24ec3dea52339a610d34401d2d53d0fb3c7fd08e34b20c95d2ad3973193591f1", + "sha256:267f8e4c0a1d7e36e97c6a604f5b03ef58e2b81c1becb4fccecddcb37e063cc7", + "sha256:3273a28734175feebbe4d0a4cde04d4ed20f620b9b506d26f44379d3c72304e1", + "sha256:39fbd5d62167197318a0371b2a9c699ce261b6800bb493eadde2ba30d868fe8c", + "sha256:4132c78200372045bb348fcad8d52518c8f5cfc077b1089949381ee4a61f1c6d", + "sha256:4baab2d2da57b0d9d544a2ce0f461374dd90ccbcf723fe46689aff906d43a964", + "sha256:4c678e23006798fc8b6f4cef2eaad267d53ff4c1779bd1af8725cc11b72a63f3", + "sha256:4d4bc2e6bb6861103ea4655d6b6f67af8e5336e7216e20fff3e18ffa95d7a055", + "sha256:505738076350a337c1740a31646e1de09a164c62c07db3b996abdc0f9d2e50cf", + "sha256:5233664eadfa342c639b9b9977190d64ad7aca4edc51a966394d7e08e7f38a9f", + "sha256:52e2e56fc3706d8791761a157115dc8391319720ad60cc32992350fda74b6be2", + "sha256:5337ac3280312aa065ed0a8ec1e4b6142e9f15c31baed36b5cd964745853243f", + "sha256:5ccd97e0f01f42b7e35907272f0f8ad2c3660a482d799a0c564c7d50e83604d4", + "sha256:5d95cb9f6cced2628f3e4de7e795e98b2659dfcc7176ab4a01a8b48c2c2f488f", + "sha256:634209852cc06c0c1243cc74f8fdc8f7444d866221de51125f7b696d775ec5ca", + "sha256:75d1f20bd8072eff92c5f457c266a61619a02d03ece56544195c56d41a1a0522", + "sha256:7eda4c737637af74bac4b23aa82ea6fbb19002552be85f0b89bc27e3a762d239", + "sha256:801ddaa69659b36abf4694fed5aa9f61d1ecf2daaa6c92541bbbbb775d97b9fe", + "sha256:825aa6d222ce2c2b90d34a0ea31914e141a85edefc07e17342f1d2fdf121c07c", + "sha256:87fe838f9dac0597f05f2605c0700b1926f9390c95df6af45d83141e0c514bd9", + "sha256:9c215442ff8249d41ff58700e91ef61d74f47dfd431a50253e1a1ca9436b0697", + "sha256:a3d90022f2202bbb14da991f26ca7a30b7e4c62bf0f8bf9825603b22d7e87494", + "sha256:a631fd36a9823638fe700d9225f9698fb59d049c942d322d4c09544dc2115356", + "sha256:a6523a23a205be0fe664b6b8747a5c86d55da960d9586db039eec9f5c269c0e6", + "sha256:a756ecf9f4b9b3ed49a680a649af45a8767ad038de39e6c030919c2f443eb000", + "sha256:ac036b6a6bac7010c58e643d78c234c2f7dc8bb7e591bd8bc3555cf4b1527c28", + "sha256:b117287a5bdc81f1bac891187275ec7e829e961b8032c9e5ff38b70fd036c78f", + "sha256:ba04f57d1715ca5ff74bb7f8a818bf929a204b3b3c2c2826d1e1cc3b1c13398c", + "sha256:ba6ef2bd62671c7fb9cdb3277414e87a5cd38b86721039ada1464f7452ad30b2", + "sha256:c8939dba1a37960a502b1a030a4465c46dd2c2bca7adf05fa3af6bea594e720e", + "sha256:cd878195166723f30865e05d87cbaf9421614501a4bd48792c5ed28f90fd36ca", + "sha256:cee815cc62d136e96cf76771b9d3eb58e0777ec18ea50de5cfcede8a7c429aa8", + "sha256:d1722b7aa4b40cf93ac3c80d3edd48bf93b9208241d166a14ad8e7a20ee1d4f3", + "sha256:d7c1c06246b05529f9984435fc4fa5a545ea26606e7f450bdbe00c153f5aeaad", + "sha256:db418635ea20528f247203bf131b40636f77c8209a045b89fa3badb89e1fcea0", + "sha256:e1555d4fda1db8005de72acf2ded1af660febad09b4708430091159e8ae1963e", + "sha256:e9c8066249c040efdda84793a2a669076f92a301ceabe69202446abb4c5c5ef9", + "sha256:e9f13711780c981d6eadd6042af40e172548c54b06266a1aabda7de192db0838", + "sha256:f0e3288b92ca5dbb1649bd00e80ef652a72b657dc94989fa9c348253d179054b", + "sha256:f227d7e574d050ff3996049e086e1f18c7bd2d067ef24131e50a1d3fe5831fbc", + "sha256:f62b1aeb5c2ced8babd4fbba9c74cbef9de309f5ed106184b12d9778a3971f15", + "sha256:f71ff657e63a9b24cac254bb8c9bd3c89c7a1b5e00ee4b3997ca1c18100dac28", + "sha256:fc9a12aad714af36cf3ad0275a96a733526571e52710319855628f476dcb144e" ], "index": "pypi", - "version": "==5.3.0" + "version": "==5.4.1" }, "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": [ @@ -502,10 +501,10 @@ }, "pytz": { "hashes": [ - "sha256:31cb35c89bd7d333cd32c5f278fca91b523b0834369e757f4c5641ea252236ca", - "sha256:8e0f8568c118d3077b46be7d654cc8167fa916092e28320cde048e54bfc9f1e6" + "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", + "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" ], - "version": "==2018.7" + "version": "==2018.9" }, "pyyaml": { "hashes": [ @@ -552,6 +551,13 @@ ], "version": "==1.2.1" }, + "soupsieve": { + "hashes": [ + "sha256:1d6ca207e67765d5297a59d1b5a18344a84587674d8c002cea72081c01a7f638", + "sha256:dff67354bff219f169ee634173c0148fcb0f7b23304ffddcfa2bb2f07accf30a" + ], + "version": "==1.7" + }, "sphinx": { "hashes": [ "sha256:429e3172466df289f0f742471d7e30ba3ee11f3b5aecd9a840480d03f14bcfe5", diff --git a/bot/cogs/information.py b/bot/cogs/information.py index c0401fe19..12970bd0e 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -137,7 +137,7 @@ class Information: # Non-moderators may only do this in #bot-commands if not with_role_check(ctx, *MODERATION_ROLES): - if not ctx.channel == Channels.bot: + if not ctx.channel.id == Channels.bot: raise MissingPermissions("You can't do that here!") # Validates hidden input @@ -205,7 +205,7 @@ class Information: await ctx.send(embed=embed) @user_info.error - async def eval_command_error(self, ctx: Context, error: CommandError): + async def user_info_command_error(self, ctx: Context, error: CommandError): embed = Embed(colour=Colour.red()) if isinstance(error, BadArgument): @@ -218,6 +218,9 @@ class Information: embed.description = f"Sorry, but you may only use this command within <#{Channels.bot}>." await ctx.send(embed=embed) + else: + log.exception(f"Unhandled error: {error}") + def setup(bot): bot.add_cog(Information(bot)) -- cgit v1.2.3 From da798da7ea4117204bd7eb1ac0d8f9c8ae7891d3 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 13 Jan 2019 00:05:59 +0100 Subject: reverting the lockfile, no changes needed --- Pipfile.lock | 362 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 166 insertions(+), 196 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 8dea91451..506b17065 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -18,11 +18,11 @@ "default": { "aio-pika": { "hashes": [ - "sha256:c3eb639f7fc5c96355e7a227380989c9e0f342bb6612e6671ea76d188813ba45", - "sha256:ea26efd262d7c4cd4ac00fb968ede89e82c00ad331b47415e3c2353a4b91cbe0" + "sha256:6438e72963e459552f196a07a081a5f6dc54d42a474292b8497bd4a59554fc85", + "sha256:dc15b451dca6d2b1c504ab353e3f2fe7e7e252fdb1c219261b5412e1cafbc72d" ], "index": "pypi", - "version": "==4.9.1" + "version": "==4.6.3" }, "aiodns": { "hashes": [ @@ -57,7 +57,6 @@ "sha256:f1839db4c2b08a9c8f9788112644f8a8557e8e0ecc77b07091afabb941dc55d0", "sha256:f3df52362be39908f9c028a65490fae0475e4898b43a03d8aa29d1e765b45e07" ], - "index": "pypi", "version": "==3.4.4" }, "alabaster": { @@ -90,18 +89,18 @@ }, "beautifulsoup4": { "hashes": [ - "sha256:034740f6cb549b4e932ae1ab975581e6103ac8f942200a0e9759065984391858", - "sha256:945065979fb8529dd2f37dbb58f00b661bdbcbebf954f93b32fdf5263ef35348", - "sha256:ba6d5c59906a85ac23dadfe5c88deaf3e179ef565f4898671253e50a78680718" + "sha256:194ec62a25438adcb3fdb06378b26559eda1ea8a747367d34c33cef9c7f48d57", + "sha256:90f8e61121d6ae58362ce3bed8cd997efb00c914eae0ff3d363c32f9a9822d10", + "sha256:f0abd31228055d698bb392a826528ea08ebb9959e6bea17c606fd9c9009db938" ], - "version": "==4.7.1" + "version": "==4.6.3" }, "certifi": { "hashes": [ - "sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7", - "sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033" + "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", + "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" ], - "version": "==2018.11.29" + "version": "==2018.10.15" }, "cffi": { "hashes": [ @@ -189,10 +188,10 @@ }, "idna": { "hashes": [ - "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", - "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", + "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" ], - "version": "==2.8" + "version": "==2.7" }, "idna-ssl": { "hashes": [ @@ -232,35 +231,39 @@ }, "lxml": { "hashes": [ - "sha256:0dd6589fa75d369ba06d2b5f38dae107f76ea127f212f6a7bee134f6df2d1d21", - "sha256:1afbac344aa68c29e81ab56c1a9411c3663157b5aee5065b7fa030b398d4f7e0", - "sha256:1baad9d073692421ad5dbbd81430aba6c7f5fdc347f03537ae046ddf2c9b2297", - "sha256:1d8736421a2358becd3edf20260e41a06a0bf08a560480d3a5734a6bcbacf591", - "sha256:1e1d9bddc5afaddf0de76246d3f2152f961697ad7439c559f179002682c45801", - "sha256:1f179dc8b2643715f020f4d119d5529b02cd794c1c8f305868b73b8674d2a03f", - "sha256:241fb7bdf97cb1df1edfa8f0bcdfd80525d4023dac4523a241907c8b2f44e541", - "sha256:2f9765ee5acd3dbdcdc0d0c79309e01f7c16bc8d39b49250bf88de7b46daaf58", - "sha256:312e1e1b1c3ce0c67e0b8105317323e12807955e8186872affb667dbd67971f6", - "sha256:3273db1a8055ca70257fd3691c6d2c216544e1a70b673543e15cc077d8e9c730", - "sha256:34dfaa8c02891f9a246b17a732ca3e99c5e42802416628e740a5d1cb2f50ff49", - "sha256:3aa3f5288af349a0f3a96448ebf2e57e17332d99f4f30b02093b7948bd9f94cc", - "sha256:51102e160b9d83c1cc435162d90b8e3c8c93b28d18d87b60c56522d332d26879", - "sha256:56115fc2e2a4140e8994eb9585119a1ae9223b506826089a3ba753a62bd194a6", - "sha256:69d83de14dbe8fe51dccfd36f88bf0b40f5debeac763edf9f8325180190eba6e", - "sha256:99fdce94aeaa3ccbdfcb1e23b34273605c5853aa92ec23d84c84765178662c6c", - "sha256:a7c0cd5b8a20f3093ee4a67374ccb3b8a126743b15a4d759e2a1bf098faac2b2", - "sha256:abe12886554634ed95416a46701a917784cb2b4c77bfacac6916681d49bbf83d", - "sha256:b4f67b5183bd5f9bafaeb76ad119e977ba570d2b0e61202f534ac9b5c33b4485", - "sha256:bdd7c1658475cc1b867b36d5c4ed4bc316be8d3368abe03d348ba906a1f83b0e", - "sha256:c6f24149a19f611a415a51b9bc5f17b6c2f698e0d6b41ffb3fa9f24d35d05d73", - "sha256:d1e111b3ab98613115a208c1017f266478b0ab224a67bc8eac670fa0bad7d488", - "sha256:d6520aa965773bbab6cb7a791d5895b00d02cf9adc93ac2bf4edb9ac1a6addc5", - "sha256:dd185cde2ccad7b649593b0cda72021bc8a91667417001dbaf24cd746ecb7c11", - "sha256:de2e5b0828a9d285f909b5d2e9d43f1cf6cf21fe65bc7660bdaa1780c7b58298", - "sha256:f726444b8e909c4f41b4fde416e1071cf28fa84634bfb4befdf400933b6463af" + "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" ], "index": "pypi", - "version": "==4.3.0" + "version": "==4.2.5" }, "markdownify": { "hashes": [ @@ -304,37 +307,37 @@ }, "multidict": { "hashes": [ - "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" + "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" }, "packaging": { "hashes": [ @@ -345,88 +348,65 @@ }, "pillow": { "hashes": [ - "sha256:01a501be4ae05fd714d269cb9c9f145518e58e73faa3f140ddb67fae0c2607b1", - "sha256:051de330a06c99d6f84bcf582960487835bcae3fc99365185dc2d4f65a390c0e", - "sha256:07c35919f983c2c593498edcc126ad3a94154184899297cc9d27a6587672cbaa", - "sha256:0ae5289948c5e0a16574750021bd8be921c27d4e3527800dc9c2c1d2abc81bf7", - "sha256:0b1efce03619cdbf8bcc61cfae81fcda59249a469f31c6735ea59badd4a6f58a", - "sha256:0cf0208500df8d0c3cad6383cd98a2d038b0678fd4f777a8f7e442c5faeee81d", - "sha256:163136e09bd1d6c6c6026b0a662976e86c58b932b964f255ff384ecc8c3cefa3", - "sha256:18e912a6ccddf28defa196bd2021fe33600cbe5da1aa2f2e2c6df15f720b73d1", - "sha256:24ec3dea52339a610d34401d2d53d0fb3c7fd08e34b20c95d2ad3973193591f1", - "sha256:267f8e4c0a1d7e36e97c6a604f5b03ef58e2b81c1becb4fccecddcb37e063cc7", - "sha256:3273a28734175feebbe4d0a4cde04d4ed20f620b9b506d26f44379d3c72304e1", - "sha256:39fbd5d62167197318a0371b2a9c699ce261b6800bb493eadde2ba30d868fe8c", - "sha256:4132c78200372045bb348fcad8d52518c8f5cfc077b1089949381ee4a61f1c6d", - "sha256:4baab2d2da57b0d9d544a2ce0f461374dd90ccbcf723fe46689aff906d43a964", - "sha256:4c678e23006798fc8b6f4cef2eaad267d53ff4c1779bd1af8725cc11b72a63f3", - "sha256:4d4bc2e6bb6861103ea4655d6b6f67af8e5336e7216e20fff3e18ffa95d7a055", - "sha256:505738076350a337c1740a31646e1de09a164c62c07db3b996abdc0f9d2e50cf", - "sha256:5233664eadfa342c639b9b9977190d64ad7aca4edc51a966394d7e08e7f38a9f", - "sha256:52e2e56fc3706d8791761a157115dc8391319720ad60cc32992350fda74b6be2", - "sha256:5337ac3280312aa065ed0a8ec1e4b6142e9f15c31baed36b5cd964745853243f", - "sha256:5ccd97e0f01f42b7e35907272f0f8ad2c3660a482d799a0c564c7d50e83604d4", - "sha256:5d95cb9f6cced2628f3e4de7e795e98b2659dfcc7176ab4a01a8b48c2c2f488f", - "sha256:634209852cc06c0c1243cc74f8fdc8f7444d866221de51125f7b696d775ec5ca", - "sha256:75d1f20bd8072eff92c5f457c266a61619a02d03ece56544195c56d41a1a0522", - "sha256:7eda4c737637af74bac4b23aa82ea6fbb19002552be85f0b89bc27e3a762d239", - "sha256:801ddaa69659b36abf4694fed5aa9f61d1ecf2daaa6c92541bbbbb775d97b9fe", - "sha256:825aa6d222ce2c2b90d34a0ea31914e141a85edefc07e17342f1d2fdf121c07c", - "sha256:87fe838f9dac0597f05f2605c0700b1926f9390c95df6af45d83141e0c514bd9", - "sha256:9c215442ff8249d41ff58700e91ef61d74f47dfd431a50253e1a1ca9436b0697", - "sha256:a3d90022f2202bbb14da991f26ca7a30b7e4c62bf0f8bf9825603b22d7e87494", - "sha256:a631fd36a9823638fe700d9225f9698fb59d049c942d322d4c09544dc2115356", - "sha256:a6523a23a205be0fe664b6b8747a5c86d55da960d9586db039eec9f5c269c0e6", - "sha256:a756ecf9f4b9b3ed49a680a649af45a8767ad038de39e6c030919c2f443eb000", - "sha256:ac036b6a6bac7010c58e643d78c234c2f7dc8bb7e591bd8bc3555cf4b1527c28", - "sha256:b117287a5bdc81f1bac891187275ec7e829e961b8032c9e5ff38b70fd036c78f", - "sha256:ba04f57d1715ca5ff74bb7f8a818bf929a204b3b3c2c2826d1e1cc3b1c13398c", - "sha256:ba6ef2bd62671c7fb9cdb3277414e87a5cd38b86721039ada1464f7452ad30b2", - "sha256:c8939dba1a37960a502b1a030a4465c46dd2c2bca7adf05fa3af6bea594e720e", - "sha256:cd878195166723f30865e05d87cbaf9421614501a4bd48792c5ed28f90fd36ca", - "sha256:cee815cc62d136e96cf76771b9d3eb58e0777ec18ea50de5cfcede8a7c429aa8", - "sha256:d1722b7aa4b40cf93ac3c80d3edd48bf93b9208241d166a14ad8e7a20ee1d4f3", - "sha256:d7c1c06246b05529f9984435fc4fa5a545ea26606e7f450bdbe00c153f5aeaad", - "sha256:db418635ea20528f247203bf131b40636f77c8209a045b89fa3badb89e1fcea0", - "sha256:e1555d4fda1db8005de72acf2ded1af660febad09b4708430091159e8ae1963e", - "sha256:e9c8066249c040efdda84793a2a669076f92a301ceabe69202446abb4c5c5ef9", - "sha256:e9f13711780c981d6eadd6042af40e172548c54b06266a1aabda7de192db0838", - "sha256:f0e3288b92ca5dbb1649bd00e80ef652a72b657dc94989fa9c348253d179054b", - "sha256:f227d7e574d050ff3996049e086e1f18c7bd2d067ef24131e50a1d3fe5831fbc", - "sha256:f62b1aeb5c2ced8babd4fbba9c74cbef9de309f5ed106184b12d9778a3971f15", - "sha256:f71ff657e63a9b24cac254bb8c9bd3c89c7a1b5e00ee4b3997ca1c18100dac28", - "sha256:fc9a12aad714af36cf3ad0275a96a733526571e52710319855628f476dcb144e" + "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" ], "index": "pypi", - "version": "==5.4.1" + "version": "==5.3.0" }, "pycares": { "hashes": [ - "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" + "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" ], - "version": "==2.4.0" + "version": "==2.3.0" }, "pycparser": { "hashes": [ @@ -436,10 +416,10 @@ }, "pygments": { "hashes": [ - "sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", - "sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d" + "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", + "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" ], - "version": "==2.3.1" + "version": "==2.2.0" }, "pynacl": { "hashes": [ @@ -501,10 +481,10 @@ }, "pytz": { "hashes": [ - "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", - "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" + "sha256:31cb35c89bd7d333cd32c5f278fca91b523b0834369e757f4c5641ea252236ca", + "sha256:8e0f8568c118d3077b46be7d654cc8167fa916092e28320cde048e54bfc9f1e6" ], - "version": "==2018.9" + "version": "==2018.7" }, "pyyaml": { "hashes": [ @@ -525,11 +505,11 @@ }, "requests": { "hashes": [ - "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", - "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" + "sha256:65b3a120e4329e33c9889db89c80976c5272f56ea92d3e74da8a463992e3ff54", + "sha256:ea881206e59f41dbd0bd445437d792e43906703fff75ca8ff43ccdb11f33f263" ], "index": "pypi", - "version": "==2.21.0" + "version": "==2.20.1" }, "shortuuid": { "hashes": [ @@ -539,10 +519,10 @@ }, "six": { "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" ], - "version": "==1.12.0" + "version": "==1.11.0" }, "snowballstemmer": { "hashes": [ @@ -551,20 +531,13 @@ ], "version": "==1.2.1" }, - "soupsieve": { - "hashes": [ - "sha256:1d6ca207e67765d5297a59d1b5a18344a84587674d8c002cea72081c01a7f638", - "sha256:dff67354bff219f169ee634173c0148fcb0f7b23304ffddcfa2bb2f07accf30a" - ], - "version": "==1.7" - }, "sphinx": { "hashes": [ - "sha256:429e3172466df289f0f742471d7e30ba3ee11f3b5aecd9a840480d03f14bcfe5", - "sha256:c4cb17ba44acffae3d3209646b6baec1e215cad3065e852c68cc569d4df1b9f8" + "sha256:120732cbddb1b2364471c3d9f8bfd4b0c5b550862f99a65736c77f970b142aea", + "sha256:b348790776490894e0424101af9c8413f2a86831524bd55c5f379d3e3e12ca64" ], "index": "pypi", - "version": "==1.8.3" + "version": "==1.8.2" }, "sphinxcontrib-websupport": { "hashes": [ @@ -608,19 +581,17 @@ }, "yarl": { "hashes": [ - "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" + "sha256:2556b779125621b311844a072e0ed367e8409a18fa12cbd68eb1258d187820f9", + "sha256:4aec0769f1799a9d4496827292c02a7b1f75c0bab56ab2b60dd94ebb57cbd5ee", + "sha256:55369d95afaacf2fa6b49c84d18b51f1704a6560c432a0f9a1aeb23f7b971308", + "sha256:6c098b85442c8fe3303e708bbb775afd0f6b29f77612e8892627bcab4b939357", + "sha256:9182cd6f93412d32e009020a44d6d170d2093646464a88aeec2aef50592f8c78", + "sha256:c8cbc21bbfa1dd7d5386d48cc814fe3d35b80f60299cdde9279046f399c3b0d8", + "sha256:db6f70a4b09cde813a4807843abaaa60f3b15fb4a2a06f9ae9c311472662daa1", + "sha256:f17495e6fe3d377e3faac68121caef6f974fcb9e046bc075bcff40d8e5cc69a4", + "sha256:f85900b9cca0c67767bb61b2b9bd53208aaa7373dae633dbe25d179b4bf38aa7" + ], + "version": "==1.2.6" } }, "develop": { @@ -633,10 +604,10 @@ }, "certifi": { "hashes": [ - "sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7", - "sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033" + "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", + "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" ], - "version": "==2018.11.29" + "version": "==2018.10.15" }, "chardet": { "hashes": [ @@ -715,10 +686,10 @@ }, "idna": { "hashes": [ - "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", - "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", + "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" ], - "version": "==2.8" + "version": "==2.7" }, "mccabe": { "hashes": [ @@ -736,7 +707,6 @@ }, "pycodestyle": { "hashes": [ - "sha256:74abc4e221d393ea5ce1f129ea6903209940c1ecd29e002e8c6933c2b21026e0", "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" ], @@ -775,11 +745,11 @@ }, "requests": { "hashes": [ - "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", - "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" + "sha256:65b3a120e4329e33c9889db89c80976c5272f56ea92d3e74da8a463992e3ff54", + "sha256:ea881206e59f41dbd0bd445437d792e43906703fff75ca8ff43ccdb11f33f263" ], "index": "pypi", - "version": "==2.21.0" + "version": "==2.20.1" }, "safety": { "hashes": [ @@ -791,10 +761,10 @@ }, "six": { "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" ], - "version": "==1.12.0" + "version": "==1.11.0" }, "urllib3": { "hashes": [ -- cgit v1.2.3 From ef622b6505f01b6305a766c6a1903799c4e95ba7 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 13 Jan 2019 01:00:32 +0100 Subject: fixing a bad conflict resolution --- bot/decorators.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/bot/decorators.py b/bot/decorators.py index 80311243d..5b4a0cbac 100644 --- a/bot/decorators.py +++ b/bot/decorators.py @@ -69,17 +69,6 @@ def without_role(*role_ids: int): return commands.check(predicate) -def in_channel(channel_id): - """ - Checks if the command was executed - inside of the specified channel. - """ - - async def predicate(ctx: Context): - return in_channel_check(ctx, channel_id) - return commands.check(predicate) - - def locked(): """ Allows the user to only run one instance of the decorated command at a time. -- cgit v1.2.3 From 57c65d4dde7d6d3385b9f5270a4fce2805def910 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 13 Jan 2019 01:08:27 +0100 Subject: fixing a bad conflict resolution pt2 --- bot/decorators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/decorators.py b/bot/decorators.py index 5b4a0cbac..710045c10 100644 --- a/bot/decorators.py +++ b/bot/decorators.py @@ -10,7 +10,7 @@ from discord.ext import commands from discord.ext.commands import CheckFailure, Context from bot.constants import ERROR_REPLIES -from bot.utils.checks import in_channel_check, with_role_check, without_role_check +from bot.utils.checks import with_role_check, without_role_check log = logging.getLogger(__name__) -- cgit v1.2.3 From 0b3d189ca7344ba371e5212ba1a1a0070fa15091 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 13 Jan 2019 13:24:08 +0100 Subject: Using the exception message as the description in BadArgument error embeds. --- bot/cogs/information.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index 12970bd0e..129166d2f 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -133,7 +133,7 @@ class Information: # someone other than the caller if user and user != ctx.author: if not with_role_check(ctx, *MODERATION_ROLES): - raise BadArgument("Only mods can target other users.") + raise BadArgument("You do not have permission to use this command on users other than yourself.") # Non-moderators may only do this in #bot-commands if not with_role_check(ctx, *MODERATION_ROLES): @@ -210,7 +210,7 @@ class Information: if isinstance(error, BadArgument): embed.title = random.choice(NEGATIVE_REPLIES) - embed.description = "You do not have permission to use this command on users other than yourself." + embed.description = str(error) await ctx.send(embed=embed) elif isinstance(error, MissingPermissions): -- cgit v1.2.3