[Mod] Add kick and warn to mention spam (#4038)

* Mention spam addition

Adjust code to allow for warning and kicking in mention spam automoderation.

Added new subcommand group, mentionspam. Which will display settings of warn, kick, ban, mentionspam when called.

Adjust config to account for this.

* Condense config + removal of comments

Condense config into one variable to make one call.

Removed unneeded comments I left.

* Add warning casetype

Copied over from warnings cog

* Update strings + change function names

* Changed prints and logs. Account for showsettings, removed blocking.

If this style breaks, blame draper...

* Black format...still blaming draper.

* Adding period at end of description

Co-authored-by: Flame442 <34169552+Flame442@users.noreply.github.com>

* config migration

* Fix TypeError, add default information.

* Max_mention wording change

Thanks to @zephyrkul for suggesting the word changes.

* Require argument for max_mention

* Fix warn modlog case creation

* Fix casetype conflict

maaaaaaaaaagicccccccccc timeeeeeeeeeeeeeeeeeeeeeeeee

Co-authored-by: Draper <27962761+Drapersniper@users.noreply.github.com>
Co-authored-by: Flame442 <34169552+Flame442@users.noreply.github.com>
This commit is contained in:
Sharky 2020-08-11 21:24:22 -06:00 committed by GitHub
parent 9798538438
commit 73a34eacd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 216 additions and 33 deletions

View File

@ -42,18 +42,19 @@ class Events(MixinMeta):
return False
async def check_mention_spam(self, message):
guild = message.guild
author = message.author
guild, author = message.guild, message.author
mention_spam = await self.config.guild(guild).mention_spam.all()
max_mentions = await self.config.guild(guild).ban_mention_spam()
if max_mentions:
mentions = set(message.mentions)
if len(mentions) >= max_mentions:
if mention_spam["ban"]:
if len(mentions) >= mention_spam["ban"]:
try:
await guild.ban(author, reason=_("Mention spam (Autoban)"))
except discord.HTTPException:
log.info(
"Failed to ban member for mention spam in server {}.".format(guild.id)
log.warning(
"Failed to ban a member ({member}) for mention spam in server {guild}.".format(
member=author.id, guild=guild.id
)
)
else:
await modlog.create_case(
@ -68,6 +69,62 @@ class Events(MixinMeta):
channel=None,
)
return True
if mention_spam["kick"]:
if len(mentions) >= mention_spam["kick"]:
try:
await guild.kick(author, reason=_("Mention Spam (Autokick)"))
except discord.HTTPException:
log.warning(
"Failed to kick a member ({member}) for mention spam in server {guild}".format(
member=author.id, guild=guild.id
)
)
else:
await modlog.create_case(
self.bot,
guild,
message.created_at,
"kick",
author,
guild.me,
_("Mention spam (Autokick)"),
until=None,
channel=None,
)
return True
if mention_spam["warn"]:
if len(mentions) >= mention_spam["warn"]:
try:
await author.send(_("Please do not mass mention people!"))
except (discord.HTTPException, discord.Forbidden):
try:
await message.channel.send(
_("{member}, Please do not mass mention people!").format(
member=author.mention
)
)
except (discord.HTTPException, discord.Forbidden):
log.warning(
"Failed to warn a member ({member}) for mention spam in server {guild}".format(
member=author.id, guild=guild.id
)
)
return False
await modlog.create_case(
self.bot,
guild,
message.created_at,
"warning",
author,
guild.me,
_("Mention spam (Autowarn)"),
until=None,
channel=None,
)
return True
return False
@commands.Cog.listener()

View File

@ -49,7 +49,7 @@ class Mod(
default_global_settings = {"version": ""}
default_guild_settings = {
"ban_mention_spam": False,
"mention_spam": {"ban": None, "kick": None, "warn": None},
"delete_repeats": -1,
"ignored": False,
"respect_hierarchy": True,
@ -130,7 +130,7 @@ class Mod(
val = 3
else:
val = -1
await self.config.guild(discord.Object(id=guild_id)).delete_repeats.set(val)
await self.config.guild_from_id(guild_id).delete_repeats.set(val)
await self.config.version.set("1.0.0") # set version of last update
if await self.config.version() < "1.1.0":
message_sent = False
@ -165,6 +165,16 @@ class Mod(
self.bot.loop.create_task(send_to_owners_with_prefix_replaced(self.bot, msg))
break
await self.config.version.set("1.2.0")
if await self.config.version() < "1.3.0":
guild_dict = await self.config.all_guilds()
async for guild_id in AsyncIter(guild_dict.keys(), steps=25):
async with self.config.guild_from_id(guild_id).all() as guild_data:
current_state = guild_data.pop("ban_mention_spam", False)
if current_state is not False:
if "mention_spam" not in guild_data:
guild_data["mention_spam"] = {}
guild_data["mention_spam"]["ban"] = current_state
await self.config.version.set("1.3.0")
@commands.command()
@commands.is_owner()

View File

@ -25,7 +25,9 @@ class ModSettings(MixinMeta):
guild = ctx.guild
data = await self.config.guild(guild).all()
delete_repeats = data["delete_repeats"]
ban_mention_spam = data["ban_mention_spam"]
warn_mention_spam = data["mention_spam"]["warn"]
kick_mention_spam = data["mention_spam"]["kick"]
ban_mention_spam = data["mention_spam"]["ban"]
respect_hierarchy = data["respect_hierarchy"]
delete_delay = data["delete_delay"]
reinvite_on_unban = data["reinvite_on_unban"]
@ -37,6 +39,16 @@ class ModSettings(MixinMeta):
if delete_repeats != -1
else _("No")
)
msg += _("Warn mention spam: {num_mentions}\n").format(
num_mentions=_("{num} mentions").format(num=warn_mention_spam)
if warn_mention_spam
else _("No")
)
msg += _("Kick mention spam: {num_mentions}\n").format(
num_mentions=_("{num} mentions").format(num=kick_mention_spam)
if kick_mention_spam
else _("No")
)
msg += _("Ban mention spam: {num_mentions}\n").format(
num_mentions=_("{num} mentions").format(num=ban_mention_spam)
if ban_mention_spam
@ -87,35 +99,131 @@ class ModSettings(MixinMeta):
_("Role hierarchy will be ignored when moderation commands are issued.")
)
@modset.command()
@modset.group()
@commands.guild_only()
async def banmentionspam(self, ctx: commands.Context, max_mentions: int = 0):
async def mentionspam(self, ctx: commands.Context):
"""
Manage the automoderation settings for mentionspam.
"""
@mentionspam.command(name="warn")
@commands.guild_only()
async def mentionspam_warn(self, ctx: commands.Context, max_mentions: int):
"""
Sets the autowarn conditions for mention spam.
Users will be warned if they send any messages which contain more than
`<max_mentions>` mentions.
`<max_mentions>` Must be 0 or greater. Set to 0 to disable this feature.
"""
mention_spam = await self.config.guild(ctx.guild).mention_spam.all()
if not max_mentions:
if not mention_spam["warn"]:
return await ctx.send(_("Autowarn for mention spam is already disabled."))
await self.config.guild(ctx.guild).mention_spam.warn.set(False)
return await ctx.send(_("Autowarn for mention spam disabled."))
if max_mentions < 1:
return await ctx.send(_("`<max_mentions>` must be 1 or higher to autowarn."))
mismatch_message = ""
if mention_spam["kick"]:
if max_mentions >= mention_spam["kick"]:
mismatch_message += _("\nAutowarn is equal to or higher than autokick.")
if mention_spam["ban"]:
if max_mentions >= mention_spam["ban"]:
mismatch_message += _("\nAutowarn is equal to or higher than autoban.")
await self.config.guild(ctx.guild).mention_spam.warn.set(max_mentions)
await ctx.send(
_(
"Autowarn for mention spam enabled. "
"Anyone mentioning {max_mentions} or more different people "
"in a single message will be autowarned.\n{mismatch_message}"
).format(max_mentions=max_mentions, mismatch_message=mismatch_message)
)
@mentionspam.command(name="kick")
@commands.guild_only()
async def mentionspam_kick(self, ctx: commands.Context, max_mentions: int):
"""
Sets the autokick conditions for mention spam.
Users will be kicked if they send any messages which contain more than
`<max_mentions>` mentions.
`<max_mentions>` Must be 0 or greater. Set to 0 to disable this feature.
"""
mention_spam = await self.config.guild(ctx.guild).mention_spam.all()
if not max_mentions:
if not mention_spam["kick"]:
return await ctx.send(_("Autokick for mention spam is already disabled."))
await self.config.guild(ctx.guild).mention_spam.kick.set(False)
return await ctx.send(_("Autokick for mention spam disabled."))
if max_mentions < 1:
return await ctx.send(_("`<max_mentions>` must be 1 or higher to autokick."))
mismatch_message = ""
if mention_spam["warn"]:
if max_mentions <= mention_spam["warn"]:
mismatch_message += _("\nAutokick is equal to or lower than autowarn.")
if mention_spam["ban"]:
if max_mentions >= mention_spam["ban"]:
mismatch_message += _("\nAutokick is equal to or higher than autoban.")
await self.config.guild(ctx.guild).mention_spam.kick.set(max_mentions)
await ctx.send(
_(
"Autokick for mention spam enabled. "
"Anyone mentioning {max_mentions} or more different people "
"in a single message will be autokicked.\n{mismatch_message}"
).format(max_mentions=max_mentions, mismatch_message=mismatch_message)
)
@mentionspam.command(name="ban")
@commands.guild_only()
async def mentionspam_ban(self, ctx: commands.Context, max_mentions: int):
"""Set the autoban conditions for mention spam.
Users will be banned if they send any message which contains more than
`<max_mentions>` mentions.
`<max_mentions>` must be at least 5. Set to 0 to disable.
`<max_mentions>` Must be 0 or greater. Set to 0 to disable this feature.
"""
guild = ctx.guild
if max_mentions:
if max_mentions < 5:
max_mentions = 5
await self.config.guild(guild).ban_mention_spam.set(max_mentions)
mention_spam = await self.config.guild(ctx.guild).mention_spam.all()
if not max_mentions:
if not mention_spam["ban"]:
return await ctx.send(_("Autoban for mention spam is already disabled."))
await self.config.guild(ctx.guild).mention_spam.ban.set(False)
return await ctx.send(_("Autoban for mention spam disabled."))
if max_mentions < 1:
return await ctx.send(_("`<max_mentions>` must be 1 or higher to autoban."))
mismatch_message = ""
if mention_spam["warn"]:
if max_mentions <= mention_spam["warn"]:
mismatch_message += _("\nAutoban is equal to or lower than autowarn.")
if mention_spam["kick"]:
if max_mentions <= mention_spam["kick"]:
mismatch_message += _("\nAutoban is equal to or lower than autokick.")
await self.config.guild(ctx.guild).mention_spam.ban.set(max_mentions)
await ctx.send(
_(
"Autoban for mention spam enabled. "
"Anyone mentioning {max_mentions} or more different people "
"in a single message will be autobanned."
).format(max_mentions=max_mentions)
"in a single message will be autobanned.\n{mismatch_message}"
).format(max_mentions=max_mentions, mismatch_message=mismatch_message)
)
else:
cur_setting = await self.config.guild(guild).ban_mention_spam()
if not cur_setting:
await ctx.send(_("Autoban for mention spam is already disabled."))
return
await self.config.guild(guild).ban_mention_spam.set(False)
await ctx.send(_("Autoban for mention spam disabled."))
@modset.command()
@commands.guild_only()

View File

@ -92,6 +92,13 @@ voicekick = {
"case_str": "Voice Kick",
}
warning = {
"name": "warning",
"default_setting": True,
"image": "\N{WARNING SIGN}\N{VARIATION SELECTOR-16}",
"case_str": "Warning",
}
all_generics = (
ban,
kick,
@ -108,4 +115,5 @@ all_generics = (
serverunmute,
channelunmute,
voicekick,
warning,
)