Applying previous commit.

This commit is contained in:
Slipstream 2025-06-07 17:48:17 +00:00
parent 0a8be35c47
commit 452eb6b8dc
Signed by: slipstream
GPG Key ID: 13E498CE010AC6FD
2 changed files with 98 additions and 12 deletions

View File

@ -1001,6 +1001,7 @@ class AIModerationCog(commands.Cog):
action="The action you are appealing",
reason="Explain why you believe the action was incorrect",
guild_id="If using in DMs, provide the server ID",
message_id="ID of the moderated message you are appealing (optional)",
)
async def appeal_submit(
self,
@ -1008,6 +1009,7 @@ class AIModerationCog(commands.Cog):
action: str,
reason: str,
guild_id: int | None = None,
message_id: int | None = None,
):
guild = interaction.guild or (
self.bot.get_guild(guild_id) if guild_id else None
@ -1026,10 +1028,33 @@ class AIModerationCog(commands.Cog):
)
return
ai_review = await self.run_appeal_ai(guild, interaction.user, action, reason)
infractions = get_user_infraction_history(guild.id, interaction.user.id)
target_infraction = None
if message_id:
for infr in infractions[::-1]:
if infr.get("message_id") == message_id:
target_infraction = infr
break
if not target_infraction and infractions:
target_infraction = infractions[-1]
ai_review = await self.run_appeal_ai(
guild,
interaction.user,
action,
reason,
target_infraction,
)
timestamp = datetime.datetime.utcnow().isoformat()
ref = target_infraction.get("message_id") if target_infraction else None
await add_user_appeal(
guild.id, interaction.user.id, action, reason, timestamp, ai_review
guild.id,
interaction.user.id,
action,
reason,
timestamp,
ai_review,
str(ref) if ref else None,
)
embed = discord.Embed(title="New Appeal", color=discord.Color.blue())
@ -1039,6 +1064,8 @@ class AIModerationCog(commands.Cog):
inline=False,
)
embed.add_field(name="Action", value=action, inline=False)
if ref:
embed.add_field(name="Infraction", value=f"Message ID: {ref}", inline=False)
embed.add_field(name="Appeal", value=reason, inline=False)
embed.add_field(name="AI Review", value=ai_review[:1000], inline=False)
embed.timestamp = discord.utils.utcnow()
@ -1085,11 +1112,11 @@ class AIModerationCog(commands.Cog):
summary = summary[:147] + "..."
if len(ai_sum) > 150:
ai_sum = ai_sum[:147] + "..."
embed.add_field(
name=f"Appeal #{i} - {ts}",
value=f"Action: {appeal.get('action')}\nReason: {summary}\nAI: {ai_sum}",
inline=False,
)
value = f"Action: {appeal.get('action')}\nReason: {summary}\nAI: {ai_sum}"
ref = appeal.get("infraction_reference")
if ref:
value = f"Infraction: {ref}\n" + value
embed.add_field(name=f"Appeal #{i} - {ts}", value=value, inline=False)
await interaction.response.send_message(embed=embed, ephemeral=False)
@appeal_subgroup.command(
@ -1121,7 +1148,7 @@ class AIModerationCog(commands.Cog):
results: list[tuple[str, str]] = []
for action, text in scenarios:
result = await self.run_appeal_ai(
interaction.guild, interaction.user, action, text
interaction.guild, interaction.user, action, text, None
)
results.append((action, result))
@ -1820,6 +1847,7 @@ CRITICAL: Do NOT output anything other than the required JSON response.
message: discord.Message,
ai_decision: dict,
notify_mods_message: str = None,
link_urls: list[str] | None = None,
):
"""
Takes action based on the AI's violation decision.
@ -2071,6 +2099,10 @@ CRITICAL: Do NOT output anything other than the required JSON response.
"BAN",
reasoning,
current_timestamp_iso,
message.id,
message.channel.id,
message.content[:100] if message.content else "",
[a.url for a in message.attachments] + (link_urls or []),
)
elif action == "KICK":
@ -2103,6 +2135,10 @@ CRITICAL: Do NOT output anything other than the required JSON response.
"KICK",
reasoning,
current_timestamp_iso,
message.id,
message.channel.id,
message.content[:100] if message.content else "",
[a.url for a in message.attachments] + (link_urls or []),
)
elif action.startswith("TIMEOUT"):
@ -2154,6 +2190,10 @@ CRITICAL: Do NOT output anything other than the required JSON response.
action,
reasoning,
current_timestamp_iso,
message.id,
message.channel.id,
message.content[:100] if message.content else "",
[a.url for a in message.attachments] + (link_urls or []),
)
else:
action_taken_message = (
@ -2221,6 +2261,10 @@ CRITICAL: Do NOT output anything other than the required JSON response.
"WARN",
reasoning,
current_timestamp_iso,
message.id,
message.channel.id,
message.content[:100] if message.content else "",
[a.url for a in message.attachments] + (link_urls or []),
)
elif action == "NOTIFY_MODS":
@ -2381,7 +2425,12 @@ CRITICAL: Do NOT output anything other than the required JSON response.
)
async def run_appeal_ai(
self, guild: discord.Guild, member: discord.User, action: str, appeal_text: str
self,
guild: discord.Guild,
member: discord.User,
action: str,
appeal_text: str,
infraction: dict | None = None,
) -> str:
"""Run the appeal text through the higher tier AI model."""
if not self.genai_client:
@ -2396,10 +2445,28 @@ CRITICAL: Do NOT output anything other than the required JSON response.
"Return a short verdict (UPHOLD or OVERTURN) and your reasoning in plain text."
)
context_lines = []
if infraction:
channel_name = guild.get_channel(infraction.get("channel_id", 0))
channel_display = (
channel_name.name if channel_name else str(infraction.get("channel_id"))
)
context_lines.append(f"Original Channel: {channel_display}")
msg_content = infraction.get("message_content")
if msg_content:
context_lines.append(f"Message Snippet: {msg_content}")
attachments = infraction.get("attachments")
if attachments:
context_lines.append(f"Attachments: {attachments}")
reasoning = infraction.get("reasoning")
if reasoning:
context_lines.append(f"AI Reasoning: {reasoning}")
user_prompt = (
f"Server Rules:\n{SERVER_RULES}\n\n"
f"User History:\n{history_text}\n\n"
f"Action Appealed: {action}\n"
+ ("\n".join(context_lines) + "\n\n" if context_lines else "")
+ f"Action Appealed: {action}\n"
f"Appeal Text: {appeal_text}"
)
@ -2439,6 +2506,7 @@ CRITICAL: Do NOT output anything other than the required JSON response.
if message.author.bot:
print(f"Ignoring message {message.id} from bot.")
return
link_urls: list[str] = []
embed_urls = [embed.url for embed in message.embeds if embed.url]
link_urls = (
self.extract_direct_attachment_urls(" ".join(embed_urls))
@ -2613,7 +2681,9 @@ CRITICAL: Do NOT output anything other than the required JSON response.
if ai_decision.get("action") == "NOTIFY_MODS"
else None
)
await self.handle_violation(message, ai_decision, notify_mods_message)
await self.handle_violation(
message, ai_decision, notify_mods_message, link_urls
)
else:
# AI found no violation
print(
@ -2725,7 +2795,9 @@ CRITICAL: Do NOT output anything other than the required JSON response.
results = []
guild = interaction.guild
for action, text in scenarios:
review = await self.run_appeal_ai(guild, interaction.user, action, text)
review = await self.run_appeal_ai(
guild, interaction.user, action, text, None
)
results.append((action, text, review))
embed = discord.Embed(

View File

@ -128,6 +128,10 @@ async def add_user_infraction(
action_taken: str,
reasoning: str,
timestamp: str,
message_id: int | None = None,
channel_id: int | None = None,
message_content: str | None = None,
attachments: list[str] | None = None,
):
key = f"{guild_id}_{user_id}"
if key not in USER_INFRACTIONS:
@ -139,6 +143,14 @@ async def add_user_infraction(
"action_taken": action_taken,
"reasoning": reasoning,
}
if message_id is not None:
infraction_record["message_id"] = message_id
if channel_id is not None:
infraction_record["channel_id"] = channel_id
if message_content is not None:
infraction_record["message_content"] = message_content
if attachments:
infraction_record["attachments"] = attachments
USER_INFRACTIONS[key].append(infraction_record)
USER_INFRACTIONS[key] = USER_INFRACTIONS[key][-10:]
await save_user_infractions()
@ -156,6 +168,7 @@ async def add_user_appeal(
appeal_text: str,
timestamp: str,
ai_review: str,
infraction_reference: str | None = None,
):
key = f"{guild_id}_{user_id}"
if key not in USER_APPEALS:
@ -166,6 +179,7 @@ async def add_user_appeal(
"action": action,
"appeal_text": appeal_text,
"ai_review": ai_review,
"infraction_reference": infraction_reference,
}
USER_APPEALS[key].append(appeal_record)
USER_APPEALS[key] = USER_APPEALS[key][-10:]