From 59ace990d179372a4d091fdc0bc69ce7be55f1e9 Mon Sep 17 00:00:00 2001 From: GEORGE MATTA Date: Sat, 31 Dec 2022 23:48:23 -0800 Subject: [PATCH 1/6] Add a column in db for reports channel and add to settings --- cogs/{dnd_commands.py => .dnd_commands.py} | 0 ...new_role_picker.py => .new_role_picker.py} | 0 cogs/bot_settings.py | 13 ++++++++++++ cogs/ping_command.py | 20 +++++++++++++++++++ config/database.pgsql | 1 + 5 files changed, 34 insertions(+) rename cogs/{dnd_commands.py => .dnd_commands.py} (100%) rename cogs/{new_role_picker.py => .new_role_picker.py} (100%) create mode 100644 cogs/ping_command.py diff --git a/cogs/dnd_commands.py b/cogs/.dnd_commands.py similarity index 100% rename from cogs/dnd_commands.py rename to cogs/.dnd_commands.py diff --git a/cogs/new_role_picker.py b/cogs/.new_role_picker.py similarity index 100% rename from cogs/new_role_picker.py rename to cogs/.new_role_picker.py diff --git a/cogs/bot_settings.py b/cogs/bot_settings.py index 06db9c3..1a47e6f 100644 --- a/cogs/bot_settings.py +++ b/cogs/bot_settings.py @@ -34,6 +34,19 @@ async def wrapper(ctx: vbu.SlashContext, data: list): callback=vbu.menus.Menu.callbacks.set_table_column(vbu.menus.DataLocation.GUILD, "guild_settings", "quote_channel_id"), cache_callback=vbu.menus.Menu.callbacks.set_cache_from_key(vbu.menus.DataLocation.GUILD, "quote_channel_id"), ), + vbu.menus.Option( + display=lambda ctx: f"Set report channel (currently {ctx.get_mentionable_channel(ctx.bot.guild_settings[ctx.guild.id]['report_channel_id']).mention})", + component_display="Report channel", + converters=[ + vbu.menus.Converter( + prompt="What channel do you want to send reports to?", + converter=discord.TextChannel, + ) + ], + allow_none=True, + callback=vbu.menus.Menu.callbacks.set_table_column(vbu.menus.DataLocation.GUILD, "guild_settings", "report_channel_id"), + cache_callback=vbu.menus.Menu.callbacks.set_cache_from_key(vbu.menus.DataLocation.GUILD, "report_channel_id"), + ), vbu.menus.Option( display=lambda ctx: f"Set reactions needed for quote (currently {ctx.bot.guild_settings[ctx.guild.id]['quote_reactions_needed']})", component_display="Reactions needed", diff --git a/cogs/ping_command.py b/cogs/ping_command.py new file mode 100644 index 0000000..6c14e90 --- /dev/null +++ b/cogs/ping_command.py @@ -0,0 +1,20 @@ +from discord.ext import commands, vbu + + +class PingCommand(vbu.Cog): + + @commands.command() + async def ping(self, ctx: vbu.Context): + """ + An example ping command. + """ + + if isinstance(ctx, vbu.SlashContext): + await ctx.interaction.response.send_message("Pong!") + else: + await ctx.send("Pong!") + + +def setup(bot: vbu.Bot): + x = PingCommand(bot) + bot.add_cog(x) diff --git a/config/database.pgsql b/config/database.pgsql index 11e8c59..996fc67 100644 --- a/config/database.pgsql +++ b/config/database.pgsql @@ -2,6 +2,7 @@ CREATE TABLE IF NOT EXISTS guild_settings( guild_id BIGINT PRIMARY KEY, prefix VARCHAR(30), quote_channel_id BIGINT, + report_channel_id BIGINT, automatic_nickname_update BOOLEAN DEFAULT FALSE, rainbow_line_autodelete BOOLEAN DEFAULT FALSE, leaderboard_message_url VARCHAR(150), From 366c6464c8268ce594fe5b73fc376c5683eabcc0 Mon Sep 17 00:00:00 2001 From: GEORGE MATTA Date: Sun, 1 Jan 2023 02:23:12 -0800 Subject: [PATCH 2/6] Report command will make necessary checks and send to channel --- cogs/bot_settings.py | 13 ++++++ cogs/report_commands.py | 95 +++++++++++++++++++++++++++++++++++++++++ config/database.pgsql | 1 + 3 files changed, 109 insertions(+) create mode 100644 cogs/report_commands.py diff --git a/cogs/bot_settings.py b/cogs/bot_settings.py index 1a47e6f..c993e77 100644 --- a/cogs/bot_settings.py +++ b/cogs/bot_settings.py @@ -47,6 +47,19 @@ async def wrapper(ctx: vbu.SlashContext, data: list): callback=vbu.menus.Menu.callbacks.set_table_column(vbu.menus.DataLocation.GUILD, "guild_settings", "report_channel_id"), cache_callback=vbu.menus.Menu.callbacks.set_cache_from_key(vbu.menus.DataLocation.GUILD, "report_channel_id"), ), + vbu.menus.Option( + display=lambda ctx: f"Set staff role (currently {ctx.get_mentionable_role(ctx.bot.guild_settings[ctx.guild.id]['staff_role_id']).mention})", + component_display="Staff role", + converters=[ + vbu.menus.Converter( + prompt="What role should be alerted for reports?", + converter=discord.Role, + ) + ], + allow_none=True, + callback=vbu.menus.Menu.callbacks.set_table_column(vbu.menus.DataLocation.GUILD, "guild_settings", "staff_role_id"), + cache_callback=vbu.menus.Menu.callbacks.set_cache_from_key(vbu.menus.DataLocation.GUILD, "staff_role_id"), + ), vbu.menus.Option( display=lambda ctx: f"Set reactions needed for quote (currently {ctx.bot.guild_settings[ctx.guild.id]['quote_reactions_needed']})", component_display="Reactions needed", diff --git a/cogs/report_commands.py b/cogs/report_commands.py new file mode 100644 index 0000000..dc798d3 --- /dev/null +++ b/cogs/report_commands.py @@ -0,0 +1,95 @@ +from discord.ext import commands, vbu +import discord + +class ReportCommand(vbu.Cog): + + @commands.command( + application_command_meta=commands.ApplicationCommandMeta() + ) + # Perhaps giving users a way to infinitely ping staff isn't the best idea... + # ...but they could also be legitimate reports + @commands.cooldown(1, 5, commands.BucketType.channel) + @commands.guild_only() + async def report(self, ctx: vbu.Context, reported: discord.Member, reason: str = "*no reason provided*"): + """ + Sends a report to the assigned reports channel. + """ + + # If they reported themselves + if ctx.author.id == reported.id: + return await ctx.send("It doesn't make sense to report yourself...") + + # Get the report channel + report_channel_id = self.bot.guild_settings[ctx.guild.id]['report_channel_id'] + + # If an ID is not even set + if not report_channel_id: + return await ctx.send("A report channel was not chosen in the settings. Run the `/settings` command to set a channel.") + + # Get the channel object + report_channel: discord.TextChannel = ctx.guild.get_channel(report_channel_id) + + # Reports channel must be valid + if not report_channel: + try: # Fetch the channel if we can't find it + report_channel = await ctx.guild.fetch_channel(report_channel_id) + except discord.NotFound: # The channel doesn't exist + return await ctx.send("The report channel ID does not point to a channel in this server.") + except Exception: # Something else went wrong + return await ctx.send("Something went wrong finding the report channel. Run the `/settings` command to set a valid channel.") + + # Get the staff role + staff_role_id = self.bot.guild_settings[ctx.guild.id]["staff_role_id"] + staff_role: discord.Role = ctx.guild.get_role(staff_role_id) + + # Try to find a staff role if we haven't already + if not staff_role: + try: # Fetch the role if we can't find it + staff_role = await ctx.guild.fetch_role(staff_role_id) + except Exception: + # We tried our best, we just won't ping a role + pass + + # Create a message with the reporter, who they're reporting, the reason, and the message link + # In embed form + embed = vbu.Embed(colour=0xFF0000) + + # All the necessary information - we cut off the reason to the first 500 characters + embed.description = f""" + **Reported:** {reported.mention} (ID: {reported.id}) + **Reason:** {reason[:500]} + **Channel:** {ctx.message.channel.mention} ([Link](<{ctx.message.jump_url}>)) + """ + + # Make the embed asthetic if we can (add an author and an image of the reported person's avatar) + try: + embed.set_author_to_user(ctx.author) + embed.set_thumbnail(reported.avatar.url) + except: + # Probably a problem with the image + pass + + # Send the message to the reports channel + await report_channel.send( + content = + f"__{staff_role.mention if staff_role else ''} New report from {ctx.author.mention} against {reported.mention}__", + embed=embed, + allowed_mentions=discord.AllowedMentions(everyone=False, users=False, roles=True) + ) + + # If you want it to just be a message (no embed) + # await report_channel.send( + # content = f"{staff_role.mention if staff_role else ''} New report from {ctx.author.mention} against {reported.mention}.\n" + + # f"**Reported:** {reported.mention} (ID: {reported.id})\n" + + # f"**Reason:** {reason[:500]}\n" + + # f"**Channel:** {ctx.message.channel.mention} (<{ctx.message.jump_url}>)", + # allowed_mentions = discord.AllowedMentions(everyone=False, users=False, roles=True) + # ) + + # Acknowledge the original command message + await ctx.okay() + + +def setup(bot: vbu.Bot): + x = ReportCommand(bot) + bot.add_cog(x) diff --git a/config/database.pgsql b/config/database.pgsql index 996fc67..f6e377a 100644 --- a/config/database.pgsql +++ b/config/database.pgsql @@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS guild_settings( prefix VARCHAR(30), quote_channel_id BIGINT, report_channel_id BIGINT, + staff_role_id BIGINT, automatic_nickname_update BOOLEAN DEFAULT FALSE, rainbow_line_autodelete BOOLEAN DEFAULT FALSE, leaderboard_message_url VARCHAR(150), From d29b048bce1f9922de06d76669c71020fe5c2536 Mon Sep 17 00:00:00 2001 From: GEORGE MATTA Date: Sun, 1 Jan 2023 02:49:42 -0800 Subject: [PATCH 3/6] Add a button system to keep track of which reports are done --- cogs/report_commands.py | 60 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/cogs/report_commands.py b/cogs/report_commands.py index dc798d3..1168c3b 100644 --- a/cogs/report_commands.py +++ b/cogs/report_commands.py @@ -3,6 +3,47 @@ class ReportCommand(vbu.Cog): + @vbu.Cog.listener() + async def on_interaction(self, interaction: discord.Interaction): + # If the button pressed isn't a report completion button + if interaction.custom_id != "report_complete_button": + return + + # Disable the button since it's been completed + pressed_button = interaction.component + pressed_button.disable() + await interaction.response.defer_update() + + components = discord.ui.MessageComponents( + discord.ui.ActionRow( + pressed_button, + discord.ui.Button( + label = f"{interaction.user.name}#{interaction.user.discriminator}", + custom_id = "report_name_button", + style = discord.ButtonStyle.gray, + disabled=True + ), + ), + ) + + # Get the original report message so we can update it + original_message = interaction.message + + # If we have an embed, update its color to green + embed = None + if original_message.embeds: + embed = original_message.embeds[0] + embed.colour = 0x00ff00 + + # Edit the original message to have our changes + await original_message.edit( + content = original_message.content, + embed = embed, + components = components + ) + + + @commands.command( application_command_meta=commands.ApplicationCommandMeta() ) @@ -68,13 +109,25 @@ async def report(self, ctx: vbu.Context, reported: discord.Member, reason: str = except: # Probably a problem with the image pass - + + # Create a button to add to the report message to keep track of if a staff member completes the report + components = discord.ui.MessageComponents( + discord.ui.ActionRow( + discord.ui.Button( + label = "Complete", + custom_id = "report_complete_button", + style = discord.ButtonStyle.success + ), + ), + ) + # Send the message to the reports channel await report_channel.send( content = f"__{staff_role.mention if staff_role else ''} New report from {ctx.author.mention} against {reported.mention}__", embed=embed, - allowed_mentions=discord.AllowedMentions(everyone=False, users=False, roles=True) + allowed_mentions=discord.AllowedMentions(everyone=False, users=False, roles=True), + components = components ) # If you want it to just be a message (no embed) @@ -83,7 +136,8 @@ async def report(self, ctx: vbu.Context, reported: discord.Member, reason: str = # f"**Reported:** {reported.mention} (ID: {reported.id})\n" + # f"**Reason:** {reason[:500]}\n" + # f"**Channel:** {ctx.message.channel.mention} (<{ctx.message.jump_url}>)", - # allowed_mentions = discord.AllowedMentions(everyone=False, users=False, roles=True) + # allowed_mentions = discord.AllowedMentions(everyone=False, users=False, roles=True), + # components = components # ) # Acknowledge the original command message From 8556832430c3c3aabe66ad1a4e3300861c9cec3c Mon Sep 17 00:00:00 2001 From: GEORGE MATTA Date: Sun, 1 Jan 2023 02:50:33 -0800 Subject: [PATCH 4/6] prepare to merge --- cogs/{.dnd_commands.py => dnd_commands.py} | 0 cogs/{.new_role_picker.py => new_role_picker.py} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename cogs/{.dnd_commands.py => dnd_commands.py} (100%) rename cogs/{.new_role_picker.py => new_role_picker.py} (100%) diff --git a/cogs/.dnd_commands.py b/cogs/dnd_commands.py similarity index 100% rename from cogs/.dnd_commands.py rename to cogs/dnd_commands.py diff --git a/cogs/.new_role_picker.py b/cogs/new_role_picker.py similarity index 100% rename from cogs/.new_role_picker.py rename to cogs/new_role_picker.py From c4b64cc25332fff534bd1dbe4c29003433908538 Mon Sep 17 00:00:00 2001 From: GEORGE MATTA Date: Sun, 1 Jan 2023 02:51:45 -0800 Subject: [PATCH 5/6] Remove ping command cog --- cogs/ping_command.py | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 cogs/ping_command.py diff --git a/cogs/ping_command.py b/cogs/ping_command.py deleted file mode 100644 index 6c14e90..0000000 --- a/cogs/ping_command.py +++ /dev/null @@ -1,20 +0,0 @@ -from discord.ext import commands, vbu - - -class PingCommand(vbu.Cog): - - @commands.command() - async def ping(self, ctx: vbu.Context): - """ - An example ping command. - """ - - if isinstance(ctx, vbu.SlashContext): - await ctx.interaction.response.send_message("Pong!") - else: - await ctx.send("Pong!") - - -def setup(bot: vbu.Bot): - x = PingCommand(bot) - bot.add_cog(x) From 97ab315341cd9aa81358e2ba6da4191a7c2ffeda Mon Sep 17 00:00:00 2001 From: GEORGE MATTA Date: Sun, 1 Jan 2023 02:54:40 -0800 Subject: [PATCH 6/6] remove unncessary space --- cogs/report_commands.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cogs/report_commands.py b/cogs/report_commands.py index 1168c3b..78e2db9 100644 --- a/cogs/report_commands.py +++ b/cogs/report_commands.py @@ -14,6 +14,7 @@ async def on_interaction(self, interaction: discord.Interaction): pressed_button.disable() await interaction.response.defer_update() + # Create our components list with the button we had before and an additional button to show the user's name components = discord.ui.MessageComponents( discord.ui.ActionRow( pressed_button, @@ -35,14 +36,12 @@ async def on_interaction(self, interaction: discord.Interaction): embed = original_message.embeds[0] embed.colour = 0x00ff00 - # Edit the original message to have our changes + # Edit the original message to have our changes - change embed color to green, disable compete button, and add a name button await original_message.edit( content = original_message.content, embed = embed, components = components ) - - @commands.command( application_command_meta=commands.ApplicationCommandMeta()