added community voting and fixed bugs
This commit is contained in:
@@ -21,8 +21,16 @@ from utils.config import (
|
||||
remove_isolated_user,
|
||||
get_isolated_users,
|
||||
increment_absolution_points,
|
||||
get_keywords,
|
||||
add_keyword_points,
|
||||
clear_votes,
|
||||
)
|
||||
from cogs.moderation import (
|
||||
get_or_create_xcom_role,
|
||||
get_or_create_xcom_channel,
|
||||
VOTE_XCOM_THRESHOLD,
|
||||
VOTE_RESET_DAYS,
|
||||
)
|
||||
from cogs.moderation import get_or_create_xcom_role, get_or_create_xcom_channel
|
||||
|
||||
# Simple in-memory rate limiting for flood detection (user_id -> deque of timestamps)
|
||||
USER_MESSAGE_TIMES: Dict[int, Deque[datetime]] = defaultdict(lambda: deque(maxlen=20))
|
||||
@@ -94,14 +102,71 @@ class ExcommunicadoBot(commands.Bot):
|
||||
if xcom_channel_id:
|
||||
ch = message.guild.get_channel(xcom_channel_id)
|
||||
if ch:
|
||||
content = message.content or "*(no text content)*"
|
||||
prefix = f"**[{message.channel.name}]** {message.author.mention}: "
|
||||
# Discord hard limit is 2000 chars; truncate to stay under it
|
||||
max_content = 2000 - len(prefix) - 1
|
||||
if len(content) > max_content:
|
||||
content = content[: max_content - 1] + "…"
|
||||
await ch.send(
|
||||
f"**[{message.channel.name}]** {message.author.mention}: {message.content}"
|
||||
prefix + content,
|
||||
allowed_mentions=discord.AllowedMentions.none(),
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return # do not count floods or process commands from isolated users
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
# --- Admin-curated keyword / key-phrase auto-scoring ---
|
||||
# Captures critical abuse (e.g. trading cracked software/games, illegal
|
||||
# materials) even when no admin is online. Staff/owner are immune.
|
||||
author = message.author
|
||||
is_staff = isinstance(author, discord.Member) and (
|
||||
author.guild_permissions.manage_roles
|
||||
or author.guild_permissions.administrator
|
||||
or author.id == message.guild.owner_id
|
||||
)
|
||||
keywords = guild_data.get("keywords", {})
|
||||
if keywords and not is_staff and message.content:
|
||||
content_low = message.content.lower()
|
||||
matched_weight = 0
|
||||
matched_terms = []
|
||||
for phrase, info in keywords.items():
|
||||
if phrase and phrase in content_low:
|
||||
matched_weight += int(info.get("weight", 1))
|
||||
matched_terms.append(info.get("display", phrase))
|
||||
if matched_weight > 0:
|
||||
try:
|
||||
result = add_keyword_points(
|
||||
message.guild.id, author.id, matched_weight, reset_days=VOTE_RESET_DAYS
|
||||
)
|
||||
print(
|
||||
f"[KEYWORD] {author} matched {matched_terms} (+{matched_weight}) "
|
||||
f"-> score {result['score']} in {message.guild.name}"
|
||||
)
|
||||
me = message.guild.me
|
||||
can_manage = me is not None and author.top_role < me.top_role
|
||||
if result["score"] >= VOTE_XCOM_THRESHOLD and can_manage:
|
||||
cog = self.get_cog("ModerationCog")
|
||||
if cog is not None:
|
||||
reason = "Auto-flagged keywords: " + ", ".join(matched_terms[:5])
|
||||
channel, already = await cog._perform_xcom(
|
||||
message.guild, author, reason, "keyword auto-detect"
|
||||
)
|
||||
clear_votes(message.guild.id, author.id)
|
||||
log_embed = discord.Embed(
|
||||
title="🚩 Keyword Auto-XCOM",
|
||||
description=f"{author.mention} ({author.id}) was auto-XCOM'd into {channel.mention} after matching flagged keywords.",
|
||||
color=discord.Color.dark_red(),
|
||||
timestamp=now,
|
||||
)
|
||||
log_embed.add_field(name="Matched", value=", ".join(matched_terms[:10]) or "—", inline=False)
|
||||
await self.log_action(message.guild, log_embed)
|
||||
return
|
||||
except Exception as kw_err:
|
||||
print(f"[KEYWORD] Auto-XCOM failed: {kw_err}")
|
||||
|
||||
times = USER_MESSAGE_TIMES[message.author.id]
|
||||
times.append(now)
|
||||
|
||||
@@ -130,8 +195,6 @@ class ExcommunicadoBot(commands.Bot):
|
||||
except Exception as flood_err:
|
||||
print(f"[FLOOD] Auto-XCOM failed: {flood_err}")
|
||||
|
||||
await self.process_commands(message)
|
||||
|
||||
async def log_action(self, guild: discord.Guild, embed: discord.Embed) -> None:
|
||||
"""Send log to configured log channel if set."""
|
||||
if self.log_channel_id:
|
||||
|
||||
Reference in New Issue
Block a user