diff --git a/README.md b/README.md index fd2bca9..0b8a19a 100755 --- a/README.md +++ b/README.md @@ -11,6 +11,9 @@ Based on https://gitlab.com/ao/dpybotbase - [x] .py configs - [x] membercount command +- [x] Meme commands and pegaswitch (honestly the easiest part) +- [x] source command +- [x] robocop command - [x] Verification: Actual verification system - [x] Verification: Reset command - [x] Logging: joins @@ -26,19 +29,17 @@ Based on https://gitlab.com/ao/dpybotbase - [x] Moderation: addhacker-removehacker (hacker) - [x] Moderation: probate-unprobate (participant) - [x] Moderation: lock-softlock-unlock (channel lockdown) -- [ ] Moderation: mute-unmute +- [x] Moderation: mute-unmute - [x] Moderation: playing - [x] Moderation: botnickname - [x] Moderation: nickname - [ ] Moderation: clear/purge +- [ ] Moderation: restrictions (people who leave with muted role will get muted role on join) - [ ] Warns: warn - [ ] Warns: delwarnid-delwarn - [ ] Warns: listwarns-listwarnsid - [ ] Warns: clearwarns-clearwarnsid -- [x] .serr and .err -- [x] Meme commands and pegaswitch (honestly the easiest part) -- [x] source command -- [x] robocop command +- [x] .serr and .err (thanks tomger!) --- diff --git a/cogs/mod.py b/cogs/mod.py index 766092b..788a742 100644 --- a/cogs/mod.py +++ b/cogs/mod.py @@ -13,6 +13,72 @@ class ModCog: def check_if_target_is_staff(self, target): return any(r.id in config.staff_role_ids for r in target.roles) + @commands.guild_only() + @commands.bot_has_permissions(kick_members=True) + @commands.check(check_if_staff) + @commands.command() + async def mute(self, ctx, target: discord.Member, *, reason: str = ""): + """Mutes a user, staff only.""" + # TODO: keep a restriction list + # so that muted people can't just leave and rejoin + if self.check_if_target_is_staff(target): + return await ctx.send("I can't mute this user as " + "they're a member of staff.") + + safe_name = self.bot.escape_message(str(target)) + + dm_message = f"You were muted!" + if reason: + dm_message += f" The given reason is: \"{reason}\"." + + try: + await target.send(dm_message) + except discord.errors.Forbidden: + # Prevents kick issues in cases where user blocked bot + # or has DMs disabled + pass + + mute_role = ctx.guild.get_role(config.mute_role) + + await target.add_roles(mute_role, reason=str(ctx.author)) + + chan_message = f"🔇 **Muted**: {ctx.author.mention} muted "\ + f"{target.mention} | {safe_name}\n"\ + f"🏷 __User ID__: {target.id}\n" + if reason: + chan_message += f"✏️ __Reason__: \"{reason}\"" + else: + chan_message += "Please add an explanation below. In the future, "\ + "it is recommended to use `.mute [reason]`"\ + " as the reason is automatically sent to the user." + + log_channel = self.bot.get_channel(config.log_channel) + await log_channel.send(chan_message) + await ctx.send(f"{target.mention} can no longer speak.") + + @commands.guild_only() + @commands.bot_has_permissions(kick_members=True) + @commands.check(check_if_staff) + @commands.command() + async def unmute(self, ctx, target: discord.Member): + """Unmutes a user, staff only.""" + if self.check_if_target_is_staff(target): + return await ctx.send("I can't unmute this user as " + "they're a member of staff.") + + safe_name = self.bot.escape_message(str(target)) + + mute_role = ctx.guild.get_role(config.mute_role) + await target.remove_roles(mute_role, reason=str(ctx.author)) + + chan_message = f"🔈 **Unmuted**: {ctx.author.mention} unmuted "\ + f"{target.mention} | {safe_name}\n"\ + f"🏷 __User ID__: {target.id}\n" + + log_channel = self.bot.get_channel(config.log_channel) + await log_channel.send(chan_message) + await ctx.send(f"{target.mention} can now speak again.") + @commands.guild_only() @commands.bot_has_permissions(kick_members=True) @commands.check(check_if_staff) diff --git a/config.py.template b/config.py.template index 73ab340..328449e 100644 --- a/config.py.template +++ b/config.py.template @@ -41,3 +41,5 @@ welcome_channel = 526372470752673792 # rules-info channel in NotSwitched community_channels = [526378423468425236] # Channels requiring community role general_channels = [526372255052201995] # Channels everyone can access + +mute_role = 526500080879140874 # Mute role in NotSwitched