diff --git a/cogs/gpt_3_commands_and_converser.py b/cogs/gpt_3_commands_and_converser.py index f2749c4..b39a20c 100644 --- a/cogs/gpt_3_commands_and_converser.py +++ b/cogs/gpt_3_commands_and_converser.py @@ -484,10 +484,17 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): async def on_message_edit(self, before, after): # Moderation - if after.guild.id in self.moderation_queues and self.moderation_queues[after.guild.id] is not None: + if ( + after.guild.id in self.moderation_queues + and self.moderation_queues[after.guild.id] is not None + ): # Create a timestamp that is 0.5 seconds from now - timestamp = (datetime.datetime.now() + datetime.timedelta(seconds=0.5)).timestamp() - await self.moderation_queues[after.guild.id].put(Moderation(after, timestamp)) + timestamp = ( + datetime.datetime.now() + datetime.timedelta(seconds=0.5) + ).timestamp() + await self.moderation_queues[after.guild.id].put( + Moderation(after, timestamp) + ) if after.author.id in self.redo_users: if after.id == original_message[after.author.id]: @@ -514,7 +521,10 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): print("Doing the encapsulated send") await self.encapsulated_send( - user_id=after.author.id, prompt=edited_content, ctx=ctx, response_message=response_message + user_id=after.author.id, + prompt=edited_content, + ctx=ctx, + response_message=response_message, ) self.redo_users[after.author.id].prompt = after.content @@ -529,10 +539,17 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): content = message.content.strip() # Moderations service - if message.guild.id in self.moderation_queues and self.moderation_queues[message.guild.id] is not None: + if ( + message.guild.id in self.moderation_queues + and self.moderation_queues[message.guild.id] is not None + ): # Create a timestamp that is 0.5 seconds from now - timestamp = (datetime.datetime.now() + datetime.timedelta(seconds=0.5)).timestamp() - await self.moderation_queues[message.guild.id].put(Moderation(message, timestamp)) + timestamp = ( + datetime.datetime.now() + datetime.timedelta(seconds=0.5) + ).timestamp() + await self.moderation_queues[message.guild.id].put( + Moderation(message, timestamp) + ) conversing = self.check_conversing( message.author.id, message.channel.id, content @@ -983,8 +1000,8 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): async def moderations_test(self, ctx: discord.ApplicationContext, prompt: str): await ctx.defer() response = await self.model.send_moderations_request(prompt) - await ctx.respond(response['results'][0]['category_scores']) - await ctx.send_followup(response['results'][0]['flagged']) + await ctx.respond(response["results"][0]["category_scores"]) + await ctx.send_followup(response["results"][0]["flagged"]) @add_to_group("system") @discord.slash_command( @@ -992,10 +1009,20 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): description="The AI moderations service", guild_ids=ALLOWED_GUILDS, ) - @discord.option(name="status", description="Enable or disable the moderations service for the current guild (on/off)", required = True) - @discord.option(name="alert_channel_id", description="The channel ID to send moderation alerts to", required=False) + @discord.option( + name="status", + description="Enable or disable the moderations service for the current guild (on/off)", + required=True, + ) + @discord.option( + name="alert_channel_id", + description="The channel ID to send moderation alerts to", + required=False, + ) @discord.guild_only() - async def moderations(self, ctx: discord.ApplicationContext, status: str, alert_channel_id: str): + async def moderations( + self, ctx: discord.ApplicationContext, status: str, alert_channel_id: str + ): await ctx.defer() status = status.lower().strip() @@ -1007,11 +1034,19 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): # Create the moderations service. self.moderation_queues[ctx.guild_id] = asyncio.Queue() if self.moderation_alerts_channel or alert_channel_id: - moderations_channel = await self.bot.fetch_channel(self.moderation_alerts_channel if not alert_channel_id else alert_channel_id) + moderations_channel = await self.bot.fetch_channel( + self.moderation_alerts_channel + if not alert_channel_id + else alert_channel_id + ) else: - moderations_channel = self.moderation_alerts_channel # None + moderations_channel = self.moderation_alerts_channel # None - self.moderation_tasks[ctx.guild_id] = asyncio.ensure_future(Moderation.process_moderation_queue(self.moderation_queues[ctx.guild_id], 1, 1, moderations_channel)) + self.moderation_tasks[ctx.guild_id] = asyncio.ensure_future( + Moderation.process_moderation_queue( + self.moderation_queues[ctx.guild_id], 1, 1, moderations_channel + ) + ) await ctx.respond("Moderations service enabled") elif status == "off": diff --git a/models/moderations_service_model.py b/models/moderations_service_model.py index 6102724..4beab4d 100644 --- a/models/moderations_service_model.py +++ b/models/moderations_service_model.py @@ -12,8 +12,8 @@ from models.usage_service_model import UsageService usage_service = UsageService(Path(os.environ.get("DATA_DIR", os.getcwd()))) model = Model(usage_service) -class Moderation: +class Moderation: def __init__(self, message, timestamp): self.message = message self.timestamp = timestamp @@ -27,10 +27,10 @@ class Moderation: colour=discord.Colour.red(), ) # Set the embed thumbnail - embed.set_thumbnail( - url="https://i.imgur.com/2oL8JSp.png" + embed.set_thumbnail(url="https://i.imgur.com/2oL8JSp.png") + embed.set_footer( + text="If you think this was a mistake, please contact the server admins." ) - embed.set_footer(text="If you think this was a mistake, please contact the server admins.") return embed @staticmethod @@ -38,7 +38,9 @@ class Moderation: # Create a discord embed to send to the user when their message gets moderated embed = discord.Embed( - title="A message was moderated in the "+moderated_message.message.guild.name+" server", + title="A message was moderated in the " + + moderated_message.message.guild.name + + " server", description=f"Message from {moderated_message.message.author.mention} was moderated: {moderated_message.message.content}", colour=discord.Colour.yellow(), ) @@ -48,7 +50,6 @@ class Moderation: embed.add_field(name="Moderated message link", value=link, inline=False) return embed - @staticmethod def determine_moderation_result(response): HATE_THRESHOLD = 0.005 @@ -59,12 +60,28 @@ class Moderation: VIOLENCE_THRESHOLD = 0.01 VIOLENCE_GRAPHIC_THRESHOLD = 0.1 - thresholds = [HATE_THRESHOLD, HATE_VIOLENCE_THRESHOLD, SELF_HARM_THRESHOLD, SEXUAL_THRESHOLD, SEXUAL_MINORS_THRESHOLD, VIOLENCE_THRESHOLD, VIOLENCE_GRAPHIC_THRESHOLD] - threshold_iterator = ['hate','hate/threatening','self-harm','sexual','sexual/minors','violence','violence/graphic'] - - category_scores = response['results'][0]['category_scores'] - - flagged = response['results'][0]['flagged'] + thresholds = [ + HATE_THRESHOLD, + HATE_VIOLENCE_THRESHOLD, + SELF_HARM_THRESHOLD, + SEXUAL_THRESHOLD, + SEXUAL_MINORS_THRESHOLD, + VIOLENCE_THRESHOLD, + VIOLENCE_GRAPHIC_THRESHOLD, + ] + threshold_iterator = [ + "hate", + "hate/threatening", + "self-harm", + "sexual", + "sexual/minors", + "violence", + "violence/graphic", + ] + + category_scores = response["results"][0]["category_scores"] + + flagged = response["results"][0]["flagged"] # Iterate the category scores using the threshold_iterator and compare the values to thresholds for category, threshold in zip(threshold_iterator, thresholds): @@ -90,18 +107,26 @@ class Moderation: # Check if the current timestamp is greater than the deletion timestamp if datetime.now().timestamp() > to_moderate.timestamp: - response = await model.send_moderations_request(to_moderate.message.content) + response = await model.send_moderations_request( + to_moderate.message.content + ) moderation_result = Moderation.determine_moderation_result(response) if moderation_result: # Take care of the flagged message - response_message = await to_moderate.message.reply(embed=Moderation.build_moderation_embed()) + response_message = await to_moderate.message.reply( + embed=Moderation.build_moderation_embed() + ) # Do the same response as above but use an ephemeral message await to_moderate.message.delete() # Send to the moderation alert channel if moderations_alert_channel: - await moderations_alert_channel.send(embed=Moderation.build_admin_moderated_message(to_moderate, response_message)) + await moderations_alert_channel.send( + embed=Moderation.build_admin_moderated_message( + to_moderate, response_message + ) + ) else: await moderation_queue.put(to_moderate) diff --git a/models/openai_model.py b/models/openai_model.py index 6a15c9f..2b44938 100644 --- a/models/openai_model.py +++ b/models/openai_model.py @@ -320,7 +320,7 @@ class Model: async def send_moderations_request(self, text): # Use aiohttp to send the above request: async with aiohttp.ClientSession() as session: - headers={ + headers = { "Content-Type": "application/json", "Authorization": f"Bearer {self.openai_key}", } @@ -332,7 +332,6 @@ class Model: ) as response: return await response.json() - async def send_summary_request(self, prompt): """ Sends a summary request to the OpenAI API