Repository: Cog-Creators/Red-DiscordBot

Issue:
[Mod] Voicemutes are broken
# Other bugs

<!-- 
Did you find a bug with something other than a command? Fill out the following:
-->

#### What were you trying to do?
Voice muting a user
<!-- Replace this line with a description of what you were trying to do -->

#### What were you expecting to happen?
The user to get muted
<!-- Replace this line with a description of what you were expecting to happen -->

#### What actually happened?
Modlog entry created. Nothing else happened
<!-- Replace this line with a description of what actually happened. Include any error messages -->

#### How can we reproduce this issue?
Voice mute someone.
<!-- Replace with numbered steps to reproduce the issue -->

Not sure if this is worth fixing as someone with manage channel perms can just mute people. If we don't want to fix it we might want to remove the voicemute command though


Discussion:
Just tried to reproduce this and it worked fine for me. The Permission was successfully denied on the user I targeted.
It seems like this may be a Discord issue. Looking a the Discord permissions screen, when a user is already in a voice channel, it doesn't affect them unless the user rejoins. So this looks like a Discord issue. Maybe.

Edit - oh, and a modlog entry wasn't created for me.
> It seems like this may be a Discord issue. Looking a the Discord permissions screen, when a user is already in a voice channel, it doesn't affect them unless the user rejoins. So this looks like a Discord issue. Maybe.

Yeah, it seems that way, and sadly I don't think we can do anything about it :/

> Edit - oh, and a modlog entry wasn't created for me.

Are you sure you have vmute case type enabled? 
Ah, probably that. Except kicking and rejoining the user or using the API equivalent of ![http://i.vex.my.to/8G5QA](http://i.vex.my.to/8G5QAc) if such a thing exists as that button does it instantly.
> Except kicking and rejoining the user

We can kick the users, but can't rejoin them.

> or using the API equivalent of [image of server mute checkbox] if such a thing exists as that button does it instantly.

And we can't use that as `[p]mute voice` is supposed to be a mute in single channel and this will do a voice mute for whole server (equivalent of `[p]voiceban`)
Looking a little bit more into this, there's a *workaround* which requires Move Members permission - API allows you to "move" the user into the voice channel they're currently in, which makes the denied Speak permission actually affect that member. I don't know if it's intended, but as long as nobody in Discord says it isn't, we could just use that.

Resolving patch:
diff --git a/redbot/cogs/mod/mutes.py b/redbot/cogs/mod/mutes.py
--- a/redbot/cogs/mod/mutes.py
+++ b/redbot/cogs/mod/mutes.py
@@ -207,6 +207,17 @@ async def voice_mute(self, ctx: commands.Context, user: discord.Member, *, reaso
             await ctx.send(
                 _("Muted {user} in channel {channel.name}").format(user=user, channel=channel)
             )
+            try:
+                if channel.permissions_for(ctx.me).move_members:
+                    await user.move_to(channel)
+                else:
+                    raise RuntimeError
+            except (discord.Forbidden, RuntimeError):
+                await ctx.send(
+                    _(
+                        "Because I don't have the Move Members permission, this will take into effect when the user rejoins."
+                    )
+                )
         else:
             await ctx.send(issue)
 
@@ -322,6 +333,17 @@ async def unmute_voice(
             await ctx.send(
                 _("Unmuted {user} in channel {channel.name}").format(user=user, channel=channel)
             )
+            try:
+                if channel.permissions_for(ctx.me).move_members:
+                    await user.move_to(channel)
+                else:
+                    raise RuntimeError
+            except (discord.Forbidden, RuntimeError):
+                await ctx.send(
+                    _(
+                        "Because I don't have the Move Members permission, this will take into effect when the user rejoins."
+                    )
+                )
         else:
             await ctx.send(_("Unmute failed. Reason: {}").format(message))
 


Test patch: