From debe73add8bf5c5f9b33e32201f1ce212758c8e4 Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 6 Feb 2020 21:44:56 +0100 Subject: No longer check if every role is @everyone; just skip the first element in the list --- bot/cogs/information.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index 125d7ce24..bc2deae8f 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -32,8 +32,7 @@ class Information(Cog): async def roles_info(self, ctx: Context) -> None: """Returns a list of all roles and their corresponding IDs.""" # Sort the roles alphabetically and remove the @everyone role - roles = sorted(ctx.guild.roles, key=lambda role: role.name) - roles = [role for role in roles if role.name != "@everyone"] + roles = sorted(ctx.guild.roles[1:], key=lambda role: role.name) # Build a string role_string = "" @@ -202,7 +201,7 @@ class Information(Cog): name = f"{user.nick} ({name})" joined = time_since(user.joined_at, precision="days") - roles = ", ".join(role.mention for role in user.roles if role.name != "@everyone") + roles = ", ".join(role.mention for role in user.roles[1:]) description = [ textwrap.dedent(f""" -- cgit v1.2.3 From 766331588ebad2ac74ccde572d241803db77f70c Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 6 Feb 2020 21:45:18 +0100 Subject: Roles cannot return None because everyone has the Developer role by default, and non-verified users cannot use this command. --- 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 bc2deae8f..21e3cfc39 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -212,7 +212,7 @@ class Information(Cog): {custom_status} **Member Information** Joined: {joined} - Roles: {roles or None} + Roles: {roles} """).strip() ] -- cgit v1.2.3 From 515b490fca1f151e654ff72a9fcf8f3113f239c3 Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 6 Feb 2020 21:46:45 +0100 Subject: Remove some a lot of unneccesary newlines that arguably make it harder to read --- bot/cogs/information.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index 21e3cfc39..68614d2c4 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -45,7 +45,6 @@ class Information(Cog): colour=Colour.blurple(), description=role_string ) - embed.set_footer(text=f"Total roles: {len(roles)}") await ctx.send(embed=embed) @@ -75,23 +74,17 @@ class Information(Cog): parsed_roles.append(role) for role in parsed_roles: + h, s, v = colorsys.rgb_to_hsv(*role.colour.to_rgb()) + embed = Embed( title=f"{role.name} info", colour=role.colour, ) - embed.add_field(name="ID", value=role.id, inline=True) - embed.add_field(name="Colour (RGB)", value=f"#{role.colour.value:0>6x}", inline=True) - - h, s, v = colorsys.rgb_to_hsv(*role.colour.to_rgb()) - embed.add_field(name="Colour (HSV)", value=f"{h:.2f} {s:.2f} {v}", inline=True) - embed.add_field(name="Member count", value=len(role.members), inline=True) - embed.add_field(name="Position", value=role.position) - embed.add_field(name="Permission code", value=role.permissions.value, inline=True) await ctx.send(embed=embed) -- cgit v1.2.3 From 5f799b68316e03cd0a565af484f7dee3f79ed35e Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 6 Feb 2020 21:48:26 +0100 Subject: Refactor how channels and statuses are counted; using Counter() - way cleaner. --- bot/cogs/information.py | 52 ++++++++++++++++--------------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index 68614d2c4..412447835 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -3,7 +3,7 @@ import logging import pprint import textwrap import typing -from collections import defaultdict +from collections import Counter, defaultdict from typing import Any, Mapping, Optional import discord @@ -96,36 +96,18 @@ class Information(Cog): features = ", ".join(ctx.guild.features) region = ctx.guild.region - # How many of each type of channel? roles = len(ctx.guild.roles) - channels = ctx.guild.channels - text_channels = 0 - category_channels = 0 - voice_channels = 0 - for channel in channels: - if type(channel) == TextChannel: - text_channels += 1 - elif type(channel) == CategoryChannel: - category_channels += 1 - elif type(channel) == VoiceChannel: - voice_channels += 1 + member_count = ctx.guild.member_count + + # How many of each type of channel? + channels = Counter({TextChannel: 0, VoiceChannel: 0, CategoryChannel: 0}) + for channel in ctx.guild.channels: + channels[channel.__class__] += 1 # How many of each user status? - member_count = ctx.guild.member_count - members = ctx.guild.members - online = 0 - dnd = 0 - idle = 0 - offline = 0 - for member in members: - if str(member.status) == "online": - online += 1 - elif str(member.status) == "offline": - offline += 1 - elif str(member.status) == "idle": - idle += 1 - elif str(member.status) == "dnd": - dnd += 1 + statuses = Counter({status.value: 0 for status in Status}) + for member in ctx.guild.members: + statuses[member.status.value] += 1 embed = Embed( colour=Colour.blurple(), @@ -138,15 +120,15 @@ class Information(Cog): **Counts** Members: {member_count:,} Roles: {roles} - Text: {text_channels} - Voice: {voice_channels} - Channel categories: {category_channels} + Text Channels: {channels[TextChannel]} + Voice Channels: {channels[VoiceChannel]} + Channel categories: {channels[CategoryChannel]} **Members** - {constants.Emojis.status_online} {online} - {constants.Emojis.status_idle} {idle} - {constants.Emojis.status_dnd} {dnd} - {constants.Emojis.status_offline} {offline} + {constants.Emojis.status_online} {statuses['online']} + {constants.Emojis.status_idle} {statuses['idle']} + {constants.Emojis.status_dnd} {statuses['dnd']} + {constants.Emojis.status_offline} {statuses['offline']} """) ) -- cgit v1.2.3 From 79fb50772065e23827396911682da51e24440787 Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 6 Feb 2020 21:48:39 +0100 Subject: Update tests to reflect status changes --- tests/bot/cogs/test_information.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/bot/cogs/test_information.py b/tests/bot/cogs/test_information.py index 4496a2ae0..519d2622b 100644 --- a/tests/bot/cogs/test_information.py +++ b/tests/bot/cogs/test_information.py @@ -125,10 +125,10 @@ class InformationCogTests(unittest.TestCase): ) ], members=[ - *(helpers.MockMember(status='online') for _ in range(2)), - *(helpers.MockMember(status='idle') for _ in range(1)), - *(helpers.MockMember(status='dnd') for _ in range(4)), - *(helpers.MockMember(status='offline') for _ in range(3)), + *(helpers.MockMember(status=discord.Status.online) for _ in range(2)), + *(helpers.MockMember(status=discord.Status.idle) for _ in range(1)), + *(helpers.MockMember(status=discord.Status.dnd) for _ in range(4)), + *(helpers.MockMember(status=discord.Status.offline) for _ in range(3)), ], member_count=1_234, icon_url='a-lemon.jpg', -- cgit v1.2.3 From 90dd064f2a8cfe66e5cefbe7b679dac38f6f7845 Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 6 Feb 2020 21:50:10 +0100 Subject: Instead of sending a message everytime a role can't be converted, append it to a list, and then send them it at once (less spammy) --- bot/cogs/information.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index 412447835..bc67ab5c2 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -58,6 +58,7 @@ class Information(Cog): To specify multiple roles just add to the arguments, delimit roles with spaces in them using quotation marks. """ parsed_roles = [] + failed_roles = [] for role_name in roles: if isinstance(role_name, Role): @@ -68,11 +69,17 @@ class Information(Cog): role = utils.find(lambda r: r.name.lower() == role_name.lower(), ctx.guild.roles) if not role: - await ctx.send(f":x: Could not convert `{role_name}` to a role") + failed_roles.append(role_name) continue parsed_roles.append(role) + if failed_roles: + await ctx.send( + ":x: I could not convert the following role names to a role: \n- " + "\n- ".join(failed_roles) + ) + for role in parsed_roles: h, s, v = colorsys.rgb_to_hsv(*role.colour.to_rgb()) -- cgit v1.2.3 From 8f1f8055383e5cbf017f4f2cec7074518dab95fd Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 6 Feb 2020 21:59:46 +0100 Subject: Fix up imports a bit; there's no need to import all of discord and typing for just 1 or 2 uses (e.g. Union, and Message). --- bot/cogs/information.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index bc67ab5c2..3b8a88309 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -2,14 +2,11 @@ import colorsys import logging import pprint import textwrap -import typing from collections import Counter, defaultdict -from typing import Any, Mapping, Optional +from typing import Any, Mapping, Optional, Union -import discord -from discord import CategoryChannel, Colour, Embed, Member, Role, TextChannel, VoiceChannel, utils -from discord.ext import commands -from discord.ext.commands import BucketType, Cog, Context, command, group +from discord import CategoryChannel, Colour, Embed, Member, Message, Role, Status, TextChannel, VoiceChannel, utils +from discord.ext.commands import BucketType, Cog, Context, Paginator, command, group from discord.utils import escape_markdown from bot import constants @@ -51,7 +48,7 @@ class Information(Cog): @with_role(*constants.MODERATION_ROLES) @command(name="role") - async def role_info(self, ctx: Context, *roles: typing.Union[Role, str]) -> None: + async def role_info(self, ctx: Context, *roles: Union[Role, str]) -> None: """ Return information on a role or list of roles. @@ -337,13 +334,13 @@ class Information(Cog): @cooldown_with_role_bypass(2, 60 * 3, BucketType.member, bypass_roles=constants.STAFF_ROLES) @group(invoke_without_command=True) @in_channel(constants.Channels.bot, bypass_roles=constants.STAFF_ROLES) - async def raw(self, ctx: Context, *, message: discord.Message, json: bool = False) -> None: + async def raw(self, ctx: Context, *, message: Message, json: bool = False) -> None: """Shows information about the raw API response.""" # I *guess* it could be deleted right as the command is invoked but I felt like it wasn't worth handling # doing this extra request is also much easier than trying to convert everything back into a dictionary again raw_data = await ctx.bot.http.get_message(message.channel.id, message.id) - paginator = commands.Paginator() + paginator = Paginator() def add_content(title: str, content: str) -> None: paginator.add_line(f'== {title} ==\n') @@ -371,7 +368,7 @@ class Information(Cog): await ctx.send(page) @raw.command() - async def json(self, ctx: Context, message: discord.Message) -> None: + async def json(self, ctx: Context, message: Message) -> None: """Shows information about the raw API response in a copy-pasteable Python format.""" await ctx.invoke(self.raw, message=message, json=True) -- cgit v1.2.3 From 4653dadbbe929055355892b322e4b0cfd3e09ab6 Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 6 Feb 2020 22:00:13 +0100 Subject: Change if statement to elif; if the first if statement returns true, the second cannot be true making it unneccesary to check --- 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 3b8a88309..e1a68ee63 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -147,7 +147,7 @@ class Information(Cog): user = ctx.author # Do a role check if this is being executed on someone other than the caller - if user != ctx.author and not with_role_check(ctx, *constants.MODERATION_ROLES): + elif user != ctx.author and not with_role_check(ctx, *constants.MODERATION_ROLES): await ctx.send("You may not use this command on users other than yourself.") return -- cgit v1.2.3 From 24136095302d192b25d83430a1b9607f05f6059c Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 6 Feb 2020 22:37:03 +0100 Subject: Fix some of the testing for information.py; I think this should be it. (hopefully). --- tests/bot/cogs/test_information.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bot/cogs/test_information.py b/tests/bot/cogs/test_information.py index 519d2622b..296c3c556 100644 --- a/tests/bot/cogs/test_information.py +++ b/tests/bot/cogs/test_information.py @@ -153,8 +153,8 @@ class InformationCogTests(unittest.TestCase): **Counts** Members: {self.ctx.guild.member_count:,} Roles: {len(self.ctx.guild.roles)} - Text: 1 - Voice: 1 + Text Channels: 1 + Voice Channels: 1 Channel categories: 1 **Members** -- cgit v1.2.3 From b0fe5841f58d72a12b3f3ddfd5de7b648770fd58 Mon Sep 17 00:00:00 2001 From: Deniz Date: Sat, 8 Feb 2020 18:48:32 +0100 Subject: Use the enum itself instead of its string value --- bot/cogs/information.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index e1a68ee63..efe660851 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -109,9 +109,9 @@ class Information(Cog): channels[channel.__class__] += 1 # How many of each user status? - statuses = Counter({status.value: 0 for status in Status}) + statuses = Counter({status: 0 for status in Status}) for member in ctx.guild.members: - statuses[member.status.value] += 1 + statuses[member.status] += 1 embed = Embed( colour=Colour.blurple(), @@ -129,10 +129,10 @@ class Information(Cog): Channel categories: {channels[CategoryChannel]} **Members** - {constants.Emojis.status_online} {statuses['online']} - {constants.Emojis.status_idle} {statuses['idle']} - {constants.Emojis.status_dnd} {statuses['dnd']} - {constants.Emojis.status_offline} {statuses['offline']} + {constants.Emojis.status_online} {statuses[Status.online]} + {constants.Emojis.status_idle} {statuses[Status.idle]} + {constants.Emojis.status_dnd} {statuses[Status.dnd]} + {constants.Emojis.status_offline} {statuses[Status.offline]} """) ) -- cgit v1.2.3 From bc932aa09848bc10683d66b7e7d9f6054e9958c6 Mon Sep 17 00:00:00 2001 From: Deniz Date: Wed, 12 Feb 2020 20:33:31 +0100 Subject: Use collections.Counter properly. Use the ChannelType enum instead of the __class__ attribute, and re-add the None check for !user roles. --- bot/cogs/information.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index efe660851..2461cc749 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -5,7 +5,7 @@ import textwrap from collections import Counter, defaultdict from typing import Any, Mapping, Optional, Union -from discord import CategoryChannel, Colour, Embed, Member, Message, Role, Status, TextChannel, VoiceChannel, utils +from discord import Colour, Embed, Member, Message, Role, Status, utils from discord.ext.commands import BucketType, Cog, Context, Paginator, command, group from discord.utils import escape_markdown @@ -104,14 +104,11 @@ class Information(Cog): member_count = ctx.guild.member_count # How many of each type of channel? - channels = Counter({TextChannel: 0, VoiceChannel: 0, CategoryChannel: 0}) - for channel in ctx.guild.channels: - channels[channel.__class__] += 1 + channels = Counter(c.type for c in ctx.guild.channels) + channel_counts = "".join(sorted(f"{str(ch).title()} channels: {channels[ch]} \n" for ch in channels)).strip() # How many of each user status? - statuses = Counter({status: 0 for status in Status}) - for member in ctx.guild.members: - statuses[member.status] += 1 + statuses = Counter(member.status for member in ctx.guild.members) embed = Embed( colour=Colour.blurple(), @@ -124,9 +121,7 @@ class Information(Cog): **Counts** Members: {member_count:,} Roles: {roles} - Text Channels: {channels[TextChannel]} - Voice Channels: {channels[VoiceChannel]} - Channel categories: {channels[CategoryChannel]} + {channel_counts} **Members** {constants.Emojis.status_online} {statuses[Status.online]} @@ -135,7 +130,6 @@ class Information(Cog): {constants.Emojis.status_offline} {statuses[Status.offline]} """) ) - embed.set_thumbnail(url=ctx.guild.icon_url) await ctx.send(embed=embed) @@ -191,7 +185,7 @@ class Information(Cog): {custom_status} **Member Information** Joined: {joined} - Roles: {roles} + Roles: {roles or None} """).strip() ] -- cgit v1.2.3 From 6703e3b7db972017764f91232a82c163be2cd588 Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 13 Feb 2020 17:35:34 +0100 Subject: Update the tests accordingly to reflect the new changes --- tests/bot/cogs/test_information.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bot/cogs/test_information.py b/tests/bot/cogs/test_information.py index 296c3c556..deae7ebad 100644 --- a/tests/bot/cogs/test_information.py +++ b/tests/bot/cogs/test_information.py @@ -153,9 +153,9 @@ class InformationCogTests(unittest.TestCase): **Counts** Members: {self.ctx.guild.member_count:,} Roles: {len(self.ctx.guild.roles)} - Text Channels: 1 - Voice Channels: 1 - Channel categories: 1 + Category channels: 1 + Text channels: 1 + Voice channels: 1 **Members** {constants.Emojis.status_online} 2 -- cgit v1.2.3 From b26122d72c1a41a4919c95642c6bc16e82d535a3 Mon Sep 17 00:00:00 2001 From: Deniz Date: Thu, 13 Feb 2020 17:35:56 +0100 Subject: Add thousand separators to Members count, closes #744 --- bot/cogs/information.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index 2461cc749..c8b5eb5ad 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -124,10 +124,10 @@ class Information(Cog): {channel_counts} **Members** - {constants.Emojis.status_online} {statuses[Status.online]} - {constants.Emojis.status_idle} {statuses[Status.idle]} - {constants.Emojis.status_dnd} {statuses[Status.dnd]} - {constants.Emojis.status_offline} {statuses[Status.offline]} + {constants.Emojis.status_online} {statuses[Status.online]:,} + {constants.Emojis.status_idle} {statuses[Status.idle]:,} + {constants.Emojis.status_dnd} {statuses[Status.dnd]:,} + {constants.Emojis.status_offline} {statuses[Status.offline]:,} """) ) embed.set_thumbnail(url=ctx.guild.icon_url) -- cgit v1.2.3 From c0bc8d03804739d8ff025f4bf71846b09569b75c Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 16 Feb 2020 10:59:37 -0800 Subject: Fix missing Django logs when using Docker Compose Fixed by allocating a pseudo-tty to the web and bot services in Docker Compose. --- docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 7281c7953..11deceae8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,6 +23,7 @@ services: - staff.web ports: - "127.0.0.1:8000:8000" + tty: true depends_on: - postgres environment: @@ -37,6 +38,7 @@ services: volumes: - ./logs:/bot/logs - .:/bot:ro + tty: true depends_on: - web environment: -- cgit v1.2.3 From 62d198beb6aff28d25098d85d0236e5895444428 Mon Sep 17 00:00:00 2001 From: F4zi <44242259+F4zi780@users.noreply.github.com> Date: Mon, 17 Feb 2020 12:52:06 +0200 Subject: Pagination migrations - Emoji Data Structure Modified Changed the pagination emoji collection from list to tuple This change was suggested since this collection is constant --- bot/pagination.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/pagination.py b/bot/pagination.py index e82763912..4c2976e17 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -14,7 +14,7 @@ RIGHT_EMOJI = "\u27A1" # [:arrow_right:] LAST_EMOJI = "\u23ED" # [:track_next:] DELETE_EMOJI = constants.Emojis.trashcan # [:trashcan:] -PAGINATION_EMOJI = [FIRST_EMOJI, LEFT_EMOJI, RIGHT_EMOJI, LAST_EMOJI, DELETE_EMOJI] +PAGINATION_EMOJI = (FIRST_EMOJI, LEFT_EMOJI, RIGHT_EMOJI, LAST_EMOJI, DELETE_EMOJI) log = logging.getLogger(__name__) -- cgit v1.2.3 From 7b619a2dd17e00464d93b56717391fe53e0fe6bb Mon Sep 17 00:00:00 2001 From: Deniz Date: Fri, 21 Feb 2020 17:48:10 +0100 Subject: Use the code provided by sco1 to fix the checks failing. --- bot/cogs/information.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/bot/cogs/information.py b/bot/cogs/information.py index c8b5eb5ad..fd49e2828 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -3,6 +3,7 @@ import logging import pprint import textwrap from collections import Counter, defaultdict +from string import Template from typing import Any, Mapping, Optional, Union from discord import Colour, Embed, Member, Message, Role, Status, utils @@ -109,10 +110,14 @@ class Information(Cog): # How many of each user status? statuses = Counter(member.status for member in ctx.guild.members) + embed = Embed(colour=Colour.blurple()) - embed = Embed( - colour=Colour.blurple(), - description=textwrap.dedent(f""" + # Because channel_counts lacks leading whitespace, it breaks the dedent if it's inserted directly by the + # f-string. While this is correctly formated by Discord, it makes unit testing difficult. To keep the formatting + # without joining a tuple of strings we can use a Template string to insert the already-formatted channel_counts + # after the dedent is made. + embed.description = Template( + textwrap.dedent(f""" **Server information** Created: {created} Voice region: {region} @@ -121,7 +126,7 @@ class Information(Cog): **Counts** Members: {member_count:,} Roles: {roles} - {channel_counts} + $channel_counts **Members** {constants.Emojis.status_online} {statuses[Status.online]:,} @@ -129,7 +134,7 @@ class Information(Cog): {constants.Emojis.status_dnd} {statuses[Status.dnd]:,} {constants.Emojis.status_offline} {statuses[Status.offline]:,} """) - ) + ).substitute({"channel_counts": channel_counts}) embed.set_thumbnail(url=ctx.guild.icon_url) await ctx.send(embed=embed) -- cgit v1.2.3 From c46498ad20c463d72e6d5da05852371f9ab20e6c Mon Sep 17 00:00:00 2001 From: Deniz Date: Fri, 21 Feb 2020 17:57:36 +0100 Subject: Remove the space that makes the test fail --- 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 fd49e2828..13c8aabaa 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -106,7 +106,7 @@ class Information(Cog): # How many of each type of channel? channels = Counter(c.type for c in ctx.guild.channels) - channel_counts = "".join(sorted(f"{str(ch).title()} channels: {channels[ch]} \n" for ch in channels)).strip() + channel_counts = "".join(sorted(f"{str(ch).title()} channels: {channels[ch]}\n" for ch in channels)).strip() # How many of each user status? statuses = Counter(member.status for member in ctx.guild.members) -- cgit v1.2.3 From b554470d35176246b6a18190230b81d592389056 Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Sun, 23 Feb 2020 16:12:48 +1000 Subject: Suppress NotFound on react clear, tidy imports. --- bot/pagination.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/bot/pagination.py b/bot/pagination.py index e82763912..d6bfe6205 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -1,8 +1,9 @@ import asyncio import logging -from typing import Iterable, List, Optional, Tuple +import typing as t +from contextlib import suppress -from discord import Embed, Member, Message, Reaction +import discord from discord.abc import User from discord.ext.commands import Context, Paginator @@ -89,12 +90,12 @@ class LinePaginator(Paginator): @classmethod async def paginate( cls, - lines: Iterable[str], + lines: t.List[str], ctx: Context, - embed: Embed, + embed: discord.Embed, prefix: str = "", suffix: str = "", - max_lines: Optional[int] = None, + max_lines: t.Optional[int] = None, max_size: int = 500, empty: bool = True, restrict_to_user: User = None, @@ -102,7 +103,7 @@ class LinePaginator(Paginator): footer_text: str = None, url: str = None, exception_on_empty_embed: bool = False - ) -> Optional[Message]: + ) -> t.Optional[discord.Message]: """ Use a paginator and set of reactions to provide pagination over a set of lines. @@ -114,11 +115,11 @@ class LinePaginator(Paginator): Pagination will also be removed automatically if no reaction is added for five minutes (300 seconds). Example: - >>> embed = Embed() + >>> embed = discord.Embed() >>> embed.set_author(name="Some Operation", url=url, icon_url=icon) - >>> await LinePaginator.paginate((line for line in lines), ctx, embed) + >>> await LinePaginator.paginate([line for line in lines], ctx, embed) """ - def event_check(reaction_: Reaction, user_: Member) -> bool: + def event_check(reaction_: discord.Reaction, user_: discord.Member) -> bool: """Make sure that this reaction is what we want to operate on.""" no_restrictions = ( # Pagination is not restricted @@ -281,8 +282,9 @@ class LinePaginator(Paginator): await message.edit(embed=embed) - log.debug("Ending pagination and removing all reactions...") - await message.clear_reactions() + log.debug("Ending pagination and clearing reactions.") + with suppress(discord.NotFound): + await message.clear_reactions() class ImagePaginator(Paginator): @@ -316,13 +318,13 @@ class ImagePaginator(Paginator): @classmethod async def paginate( cls, - pages: List[Tuple[str, str]], - ctx: Context, embed: Embed, + pages: t.List[t.Tuple[str, str]], + ctx: Context, embed: discord.Embed, prefix: str = "", suffix: str = "", timeout: int = 300, exception_on_empty_embed: bool = False - ) -> Optional[Message]: + ) -> t.Optional[discord.Message]: """ Use a paginator and set of reactions to provide pagination over a set of title/image pairs. @@ -334,11 +336,11 @@ class ImagePaginator(Paginator): Note: Pagination will be removed automatically if no reaction is added for five minutes (300 seconds). Example: - >>> embed = Embed() + >>> embed = discord.Embed() >>> embed.set_author(name="Some Operation", url=url, icon_url=icon) >>> await ImagePaginator.paginate(pages, ctx, embed) """ - def check_event(reaction_: Reaction, member: Member) -> bool: + def check_event(reaction_: discord.Reaction, member: discord.Member) -> bool: """Checks each reaction added, if it matches our conditions pass the wait_for.""" return all(( # Reaction is on the same message sent @@ -445,5 +447,6 @@ class ImagePaginator(Paginator): await message.edit(embed=embed) - log.debug("Ending pagination and removing all reactions...") - await message.clear_reactions() + log.debug("Ending pagination and clearing reactions.") + with suppress(discord.NotFound): + await message.clear_reactions() -- cgit v1.2.3 From a18f7ede045f10c6a6a06cae36b9450f869cf5ca Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Sun, 23 Feb 2020 16:13:10 +1000 Subject: Define `_count` in `__init__`. --- bot/pagination.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bot/pagination.py b/bot/pagination.py index d6bfe6205..b6525c2d0 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -301,6 +301,7 @@ class ImagePaginator(Paginator): self._current_page = [prefix] self.images = [] self._pages = [] + self._count = 0 def add_line(self, line: str = '', *, empty: bool = False) -> None: """Adds a line to each page.""" -- cgit v1.2.3 From a809754a1ad7e920180b8ff841282b7337ec0e4f Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Sun, 23 Feb 2020 20:32:47 +1000 Subject: Don't log exception traceback on Forbidden for welcomes. --- bot/cogs/verification.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/bot/cogs/verification.py b/bot/cogs/verification.py index 988e0d49a..f13ccd728 100644 --- a/bot/cogs/verification.py +++ b/bot/cogs/verification.py @@ -1,7 +1,8 @@ import logging +from contextlib import suppress from datetime import datetime -from discord import Colour, Message, NotFound, Object +from discord import Colour, Forbidden, Message, NotFound, Object from discord.ext import tasks from discord.ext.commands import Cog, Context, command @@ -127,17 +128,13 @@ class Verification(Cog): await ctx.author.add_roles(Object(Roles.verified), reason="Accepted the rules") try: await ctx.author.send(WELCOME_MESSAGE) - except Exception: - # Catch the exception, in case they have DMs off or something - log.exception(f"Unable to send welcome message to user {ctx.author}.") - - log.trace(f"Deleting the message posted by {ctx.author}.") - - try: - self.mod_log.ignore(Event.message_delete, ctx.message.id) - await ctx.message.delete() - except NotFound: - log.trace("No message found, it must have been deleted by another bot.") + except Forbidden: + log.info(f"Sending welcome message failed for {ctx.author}.") + finally: + log.trace(f"Deleting accept message by {ctx.author}.") + with suppress(NotFound): + self.mod_log.ignore(Event.message_delete, ctx.message.id) + await ctx.message.delete() @command(name='subscribe') @in_channel(Channels.bot) -- cgit v1.2.3 From 470adee6e9069782189e803752fa2d9ee08465e4 Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Mon, 24 Feb 2020 01:15:52 +1000 Subject: Reduce log level of tag cooldown notice. --- bot/cogs/tags.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index 54a51921c..b6360dfae 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -116,8 +116,10 @@ class Tags(Cog): if _command_on_cooldown(tag_name): time_left = Cooldowns.tags - (time.time() - self.tag_cooldowns[tag_name]["time"]) - log.warning(f"{ctx.author} tried to get the '{tag_name}' tag, but the tag is on cooldown. " - f"Cooldown ends in {time_left:.1f} seconds.") + log.info( + f"{ctx.author} tried to get the '{tag_name}' tag, but the tag is on cooldown. " + f"Cooldown ends in {time_left:.1f} seconds." + ) return await self._get_tags() -- cgit v1.2.3 From 12fdfde0ce1cbc4df7c7d9184acb7cda4f1d92db Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Mon, 24 Feb 2020 01:49:44 +1000 Subject: Change verification post log level to info, tidy code. --- bot/cogs/verification.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/bot/cogs/verification.py b/bot/cogs/verification.py index f13ccd728..582237374 100644 --- a/bot/cogs/verification.py +++ b/bot/cogs/verification.py @@ -93,19 +93,21 @@ class Verification(Cog): ping_everyone=Filter.ping_everyone, ) - ctx = await self.bot.get_context(message) # type: Context - + ctx: Context = await self.bot.get_context(message) if ctx.command is not None and ctx.command.name == "accept": - return # They used the accept command + return - for role in ctx.author.roles: - if role.id == Roles.verified: - log.warning(f"{ctx.author} posted '{ctx.message.content}' " - "in the verification channel, but is already verified.") - return # They're already verified + if any(r.id == Roles.verified for r in ctx.author.roles): + log.info( + f"{ctx.author} posted '{ctx.message.content}' " + "in the verification channel, but is already verified." + ) + return - log.debug(f"{ctx.author} posted '{ctx.message.content}' in the verification " - "channel. We are providing instructions how to verify.") + log.debug( + f"{ctx.author} posted '{ctx.message.content}' in the verification " + "channel. We are providing instructions how to verify." + ) await ctx.send( f"{ctx.author.mention} Please type `!accept` to verify that you accept our rules, " f"and gain access to the rest of the server.", @@ -113,11 +115,8 @@ class Verification(Cog): ) log.trace(f"Deleting the message posted by {ctx.author}") - - try: + with suppress(NotFound): await ctx.message.delete() - except NotFound: - log.trace("No message found, it must have been deleted by another bot.") @command(name='accept', aliases=('verify', 'verified', 'accepted'), hidden=True) @without_role(Roles.verified) -- cgit v1.2.3