244 lines
9.8 KiB
Python
244 lines
9.8 KiB
Python
from red_commons.logging import getLogger
|
|
from redbot.core import Config, commands
|
|
|
|
from .converters import AutoModActionFlags, AutoModRuleFlags, AutoModTriggerFlags
|
|
from .menus import (
|
|
AutoModActionsPages,
|
|
AutoModRulePages,
|
|
AutoModTriggersPages,
|
|
BaseMenu,
|
|
ConfirmView,
|
|
)
|
|
|
|
log = getLogger("red.trusty-cogs.automod")
|
|
|
|
|
|
class AutoMod(commands.Cog):
|
|
"""
|
|
Interact with and view discord's automod
|
|
"""
|
|
|
|
__author__ = ["TrustyJAID"]
|
|
__version__ = "1.0.4"
|
|
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
self.config = Config.get_conf(self, 218773382617890828)
|
|
self.config.register_guild(actions={}, triggers={}, rules={})
|
|
self._commit = ""
|
|
self._repo = ""
|
|
|
|
def format_help_for_context(self, ctx: commands.Context) -> str:
|
|
"""
|
|
Thanks Sinbad!
|
|
"""
|
|
pre_processed = super().format_help_for_context(ctx)
|
|
ret = f"{pre_processed}\n\n- Cog Version: {self.__version__}\n"
|
|
# we'll only have a repo if the cog was installed through Downloader at some point
|
|
if self._repo:
|
|
ret += f"- Repo: {self._repo}\n"
|
|
# we should have a commit if we have the repo but just incase
|
|
if self._commit:
|
|
ret += f"- Commit: [{self._commit[:9]}]({self._repo}/tree/{self._commit})"
|
|
return ret
|
|
|
|
async def cog_before_invoke(self, ctx: commands.Context):
|
|
await self._get_commit()
|
|
|
|
async def _get_commit(self):
|
|
if self._repo:
|
|
return
|
|
downloader = self.bot.get_cog("Downloader")
|
|
if not downloader:
|
|
return
|
|
cogs = await downloader.installed_cogs()
|
|
for cog in cogs:
|
|
if cog.name == "automod":
|
|
if cog.repo is not None:
|
|
self._repo = cog.repo.clean_url
|
|
self._commit = cog.commit
|
|
|
|
@commands.hybrid_group(name="automod")
|
|
@commands.guild_only()
|
|
async def automod(self, ctx: commands.Context):
|
|
"""Commnads for interacting with automod"""
|
|
|
|
@automod.command(name="rules", aliases=["list", "rule", "view"])
|
|
@commands.bot_has_permissions(manage_guild=True)
|
|
@commands.mod_or_permissions(manage_guild=True)
|
|
async def view_automod(self, ctx: commands.Context):
|
|
"""View the servers current automod rules"""
|
|
rules = await ctx.guild.fetch_automod_rules()
|
|
if len(rules) <= 0:
|
|
await ctx.send("There are no rules setup yet.")
|
|
return
|
|
pages = AutoModRulePages(rules, guild=ctx.guild)
|
|
await BaseMenu(pages, self).start(ctx)
|
|
|
|
@automod.command(name="actions", aliases=["action"])
|
|
@commands.mod_or_permissions(manage_guild=True)
|
|
async def view_automod_actions(self, ctx: commands.Context):
|
|
"""View the servers saved automod actions"""
|
|
actions_dict = await self.config.guild(ctx.guild).actions()
|
|
actions = []
|
|
for k, v in actions_dict.items():
|
|
v.update({"name": k, "guild": ctx.guild})
|
|
actions.append(v)
|
|
if len(actions) <= 0:
|
|
await ctx.send("There are no actions saved.")
|
|
return
|
|
pages = AutoModActionsPages(actions, guild=ctx.guild)
|
|
await BaseMenu(pages, self).start(ctx)
|
|
|
|
@automod.command(name="triggers", aliases=["trigger"])
|
|
@commands.mod_or_permissions(manage_guild=True)
|
|
async def view_automod_triggers(self, ctx: commands.Context):
|
|
"""View the servers saved automod triggers"""
|
|
triggers_dict = await self.config.guild(ctx.guild).triggers()
|
|
triggers = []
|
|
for k, v in triggers_dict.items():
|
|
v.update({"name": k, "guild": ctx.guild})
|
|
triggers.append(v)
|
|
if len(triggers) <= 0:
|
|
await ctx.send("There are no triggers saved.")
|
|
return
|
|
pages = AutoModTriggersPages(triggers, guild=ctx.guild)
|
|
await BaseMenu(pages, self).start(ctx)
|
|
|
|
@automod.group(name="create", aliases=["c"])
|
|
@commands.admin_or_permissions(manage_guild=True)
|
|
async def create(self, ctx: commands.Context):
|
|
"""Create automod rules, triggers, and actions"""
|
|
|
|
@create.command(name="rule")
|
|
@commands.bot_has_permissions(manage_guild=True)
|
|
@commands.admin_or_permissions(manage_guild=True)
|
|
async def create_automod_rule(
|
|
self, ctx: commands.Context, name: str, *, rule: AutoModRuleFlags
|
|
):
|
|
"""
|
|
Create an automod rule in the server
|
|
- `<name>` The name of the rule for future reference.
|
|
- `<rule>` What the rule will do using the following information.
|
|
Usage:
|
|
- `trigger:` The name of a saved trigger.
|
|
- `actions:` The name(s) of saved actions.
|
|
- `enabled:` yes/true/t to enable this rule right away.
|
|
- `roles:` The roles that are exempt from this rule.
|
|
- `channels:` The channels that are exempt from this rule.
|
|
- `reason:` An optional reason for creating this rule.
|
|
|
|
Example:
|
|
`[p]automod create rule rule_name trigger: mytrigger actions: timeoutuser notifymods enabled: true roles: @mods`
|
|
Will create an automod rule with the saved trigger `mytrigger` and
|
|
the saved actions `timeoutuser` and `notifymods`.
|
|
"""
|
|
if not name:
|
|
await ctx.send_help()
|
|
return
|
|
log.debug(f"{rule.to_args()}")
|
|
if not rule.trigger:
|
|
await ctx.send("No trigger was provided for the rule.")
|
|
return
|
|
rule_args = rule.to_args()
|
|
name = name.lower()
|
|
if rule_args.get("reason") is not None:
|
|
rule_args["reason"] = f"Created by {ctx.author}\n" + rule_args["reason"]
|
|
try:
|
|
rule = await ctx.guild.create_automod_rule(name=name, **rule_args)
|
|
except Exception as e:
|
|
rule_args_str = "\n".join(f"- {k}: {v}" for k, v in rule_args.items())
|
|
await ctx.send(
|
|
(
|
|
"There was an error creating a rule with the following rules:\n"
|
|
f"Error: {e}\n"
|
|
f"Name: {name}\n"
|
|
f"Rules:\n{rule_args_str}"
|
|
)
|
|
)
|
|
return
|
|
pages = AutoModRulePages([rule], guild=ctx.guild)
|
|
await BaseMenu(pages, self).start(ctx)
|
|
|
|
@create.command(name="action", aliases=["a"])
|
|
@commands.admin_or_permissions(manage_guild=True)
|
|
async def create_automod_action(
|
|
self, ctx: commands.Context, name: str, *, action: AutoModActionFlags
|
|
):
|
|
"""
|
|
Create a saved action for use in automod Rules.
|
|
|
|
- `<name>` The name of this action for reference later.
|
|
Usage: `<action>`
|
|
- `message:` The message to send to a user when triggered.
|
|
- `channel:` The channel to send a notification to.
|
|
- `duration:` How long to timeout the user for. Max 28 days.
|
|
Only one of these options can be applied at a time.
|
|
Examples:
|
|
`[p]automod create action grumpyuser message: You're being too grumpy`
|
|
`[p]automod create action notifymods channel: #modlog`
|
|
`[p]automod create action 2hrtimeout duration: 2 hours`
|
|
|
|
"""
|
|
try:
|
|
action.get_action()
|
|
except ValueError as e:
|
|
# d.py errors here are concise enough to explain the issue.
|
|
await ctx.send(e)
|
|
return
|
|
name = name.lower()
|
|
async with self.config.guild(ctx.guild).actions() as actions:
|
|
if name in actions:
|
|
pred = ConfirmView(ctx.author)
|
|
pred.message = await ctx.send(
|
|
f"An action with the name `{name}` already exists. Would you like to overwrite it?",
|
|
view=pred,
|
|
)
|
|
await pred.wait()
|
|
if not pred.result:
|
|
await ctx.send("Please choose a different name then.")
|
|
return
|
|
actions[name] = action.to_json()
|
|
await ctx.send(f"Saving action `{name}` with the following settings:\n{action.to_str()}")
|
|
|
|
@create.command(name="trigger")
|
|
@commands.admin_or_permissions(manage_guild=True)
|
|
async def create_automod_trigger(
|
|
self, ctx: commands.Context, name: str, *, trigger: AutoModTriggerFlags
|
|
):
|
|
"""
|
|
Create a saved trigger for use in automod Rules.
|
|
|
|
- `<name>` The name of this trigger for reference later.
|
|
Usage: `<trigger>`
|
|
- `allows:` A space separated list of words to allow.
|
|
- `keywords:` A space separated list of words to filter.
|
|
- `mentions:` The number of user/role mentions that would trigger this rule (0-50).
|
|
- `presets:` Any combination of discord presets. e.g. `profanity`, `sexual_content`, or `slurs`.
|
|
- `regex:` A space separated list of regex patterns to include.
|
|
Note: If you want to use `mentions` you cannot also use `presets`, `keywords` or
|
|
`regex` in the same trigger. Likewise if you use any `presets` you cannot
|
|
use `keywords`, `regex`, or `mentions`.
|
|
Examples:
|
|
`[p]automod create trigger mytrigger regex: ^b(a|@)dw(o|0)rd(s|5)$`
|
|
"""
|
|
try:
|
|
trigger.get_trigger()
|
|
except ValueError as e:
|
|
# d.py errors here are concise enough to explain the issue.
|
|
await ctx.send(e)
|
|
return
|
|
name = name.lower()
|
|
async with self.config.guild(ctx.guild).triggers() as triggers:
|
|
if name in triggers:
|
|
pred = ConfirmView(ctx.author)
|
|
pred.message = await ctx.send(
|
|
f"A trigger with the name `{name}` already exists. Would you like to overwrite it?",
|
|
view=pred,
|
|
)
|
|
await pred.wait()
|
|
if not pred.result:
|
|
await ctx.send("Please choose a different name then.")
|
|
return
|
|
triggers[name] = trigger.to_json()
|
|
await ctx.send(f"Saving trigger `{name}` with the following settings:\n{trigger.to_str()}")
|