async def move_all_members(self, ctx, channel_from: discord.VoiceChannel, channel_to: discord.VoiceChannel): member_amount = len(channel_from.members) if member_amount == 0: return await ctx.send( f"{channel_from.name} doesn't have any members in it.") # Check permissions to ensure a smooth transisition if channel_from.permissions_for(ctx.guild.me).move_members is False: return await ctx.send( f"I don't have permissions to move members in {channel_from.name}" ) if channel_to.permissions_for(ctx.guild.me).move_members is False: return await ctx.send( f"I don't have permissions to move members in {channel_to.name}" ) # Move the members """Internal function for massmoving, massmoves all members to the target channel""" for member in channel_from.members: try: await member.move_to(channel_to) except: pass await ctx.send( f"Done, massmoved {member_amount} members from **{channel_from.name}** to **{channel_to.name}**" )
def check_if_member_or_role_allowed( channel: discord.VoiceChannel, member_or_role: Union[discord.Member, discord.Role], ): """Check if a member/role is allowed to view and connect to a voice channel.""" if isinstance(member_or_role, discord.Member): return ( channel.permissions_for(member_or_role).connect and channel.permissions_for(member_or_role).view_channel ) elif isinstance(member_or_role, discord.Role): if member_or_role in channel.overwrites: everyone_allow, everyone_deny = channel.overwrites[ member_or_role ].pair() if ( everyone_deny.connect or everyone_deny.view_channel or ( not everyone_allow.connect and not member_or_role.permissions.connect ) or ( not everyone_allow.view_channel and not member_or_role.permissions.view_channel ) ): return False else: return True return ( member_or_role.permissions.connect and member_or_role.permissions.view_channel ) return False
async def massmove( self, ctx: commands.Context, from_channel: discord.VoiceChannel, to_channel: discord.VoiceChannel = None, ): """Move all members from one voice channel to another Use double quotes if channel name has spaces""" fails = 0 if not from_channel.members: await ctx.send( chat.error( _("There is no users in channel {}.").format( from_channel.mention))) return if not from_channel.permissions_for(ctx.me).move_members: await ctx.send(chat.error(_("I cant move users from that channel")) ) return if to_channel and not to_channel.permissions_for(ctx.me).connect: await ctx.send(chat.error(_("I cant move users to that channel"))) return async with ctx.typing(): for member in from_channel.members: try: await member.move_to(to_channel, reason=get_audit_reason( ctx.author, _("Massmove"))) except discord.HTTPException: fails += 1 continue await ctx.send( _("Finished moving users. {} members could not be moved.").format( fails))
async def _join(self, ctx, *, channel: discord.VoiceChannel = None): """ Menghubungkan bot ini ke Voice Channel Params: - channel: discord.VoiceChannel [Optional] The channel to connect to. If a channel is not specified, an attempt to join the voice channel you are in will be made. """ # if channel is not passed, will try to connect to same channel as author if not channel: try: channel = ctx.author.voice.channel except AttributeError: await ctx.send( "Silahkan pilih voice channel atau kamu harus masuk ke voice channel terlebih dahulu." ) return perm = channel.permissions_for(ctx.guild.me) if perm.connect is False: await ctx.send( f"Gagal terhubung ke **{channel}**, pastikan bot memiliki *role* yang tepat untuk bisa join ke **{channel}**." ) return if perm.speak is False: await ctx.send( f"Bot tidak memiliki *role* untuk berbicara di **{channel}**, pastikan bot memiliki *role* yang tepat untuk bisa berbicara di **{channel}**." ) return await self.join_or_move(ctx, channel) return
async def youtube_together(self, ctx: LightningContext, *, voice_channel: discord.VoiceChannel): if not voice_channel.permissions_for(ctx.me).create_instant_invite: await ctx.send("Unable to create an invite for YouTube Together.\n" "I need the `Create Invites` permission to do so.") return invite = await voice_channel.create_invite( max_age=0, target_type=discord.InviteTarget.embedded_application, target_application_id=755600276941176913) await ctx.send(invite.url)
async def _join_voice_channel(self, voice_channel: discord.VoiceChannel) -> discord.VoiceProtocol: # Make sure we have permission to join the voice channel. If we try to join a voice channel without permission, it will timeout. permissions = voice_channel.permissions_for(voice_channel.guild.me) if not all([permissions.view_channel, permissions.connect, permissions.speak]): raise InsufficientPermissionsException(['View Channel', 'Connect', 'Speak']) # Check if we are already connected to this voice channel for voice_client in self._bot.voice_clients: if voice_client.channel == voice_channel: return voice_client # Connect to the voice channel return await voice_channel.connect()
def bot_can_move_members(channel: discord.VoiceChannel) -> Result[bool]: """ Checks if the bot can move members in the specified trigger channel. :param channel: Trigger channel specified by the user. :return: Result of the check, with error message if not successful. """ if channel.permissions_for(channel.guild.me).move_members: return Result(success=True, value=True, error=None) return Result( success=False, value=False, error="The bot does not have permissions to move members out of the trigger channel.", )
async def monitor(self, ctx, voice_channel: discord.VoiceChannel = None): "Start updating a channel wth the current realm status" # Check if the bot has permission to the channel bot_perms = voice_channel.permissions_for(ctx.me) if not bot_perms.manage_channels: await ctx.send(f'I require the "Manage Channels" permission for {voice_channel.mention} to execute that command.') return guild_config = self.config.guild(ctx.guild) await guild_config.server_channel.set(voice_channel.id if voice_channel else None) if voice_channel: await ctx.send(f"Setup {voice_channel} as the monitor channel.") else: await ctx.send(f"Disabled monitor channel.")
def check_voice_permissions(self, channel: discord.VoiceChannel) -> bool: """Custom voice channel permission checker Note: - @commands.bot_has_guild_permissions(...) only checks if the bot has this permission in one of the roles it has in the guild - @commands.bot_has_permissions(...) can only check the permissions of the text channel it processed the command from, but not the actual voice channel - Wavelink does not check for permissions before connecting, so errors are silently eaten """ voice_permissions = channel.permissions_for(channel.guild.me) if voice_permissions.connect and voice_permissions.speak: return True return False
async def join(self, ctx, channel: VoiceChannel = None): """Join the given voice channel.""" if not channel: raise BananaCrime('I need a channel to join') if not channel.permissions_for(ctx.guild.me).connect: raise BananaCrime( "I don't have permission to join that voice channel") vclient = ctx.voice_client async with self.bot.guild_records[ctx.guild.id].lock: if vclient and vclient.is_connected(): if vclient.channel == channel: raise BananaCrime("I'm already in this channel") await vclient.move_to(channel) else: await channel.connect()
async def connect(self, ctx: commands.Context, *, channel: discord.VoiceChannel = None): """Music|Connect to a voice channel.|""" player: Player = self.bot.wavelink.get_player(guild_id=ctx.guild.id, cls=Player, context=ctx) if player.is_connected: return channel = getattr(ctx.author.voice, 'channel', channel) if channel is None: raise NoChannelProvided permissions = channel.permissions_for(ctx.me) if not permissions.connect or not permissions.speak: # Check user limit too? return await ctx.send("I need the `CONNECT` and `SPEAK` permissions.") await player.connect(channel.id)
def __init__(self, channel: discord.VoiceChannel): """ Initialize our music interface. This should be followed by a call to ``connect()``. :param channel: The channel to connect to. :raises NoJoinPermission: We do not have permission to join the desired channel. :raises NoSpeakPermission: We do not have permission to speak in the desired channel. :rtype: None """ if self.initialized: # we already exist. abourt return self.channel: discord.VoiceChannel = channel channel_perms = channel.permissions_for(channel.guild.me) if not channel_perms.connect: raise NoJoinPermission() if channel_perms.connect and not channel_perms.speak: raise NoSpeakPermission()
async def connect_voice(self, voice: discord.VoiceChannel, ctx: commands.Context = None): """Custom voice channel permission checker that was implemented because... 1. @commands.bot_has_guild_permissions(...) decorator only checks if the bot has this permission in one of the roles it has in the SERVER, and the 2. @commands.bot_has_permissions(...) decorator checks the permissions in the current TEXT channel, but not the actual voice channel. """ self_permissions = voice.permissions_for(voice.guild.me) if self_permissions.connect and self_permissions.speak: await voice.connect() return if ctx: required_perms = { "connect": self_permissions.connect, "speak": self_permissions.speak } missing_perms = "`, `".join( perm for perm, val in required_perms.items() if not val) icon = self.bot.icons["fail"] ctx.send( f"{icon} I'm missing `{missing_perms}` permission(s) for the voice channel." )
async def chan(self, ctx: commands.Context, *, ch: discord.VoiceChannel): """Join a voice channel on the current server.""" # All errors shall be communicated to the user, and also # passed to the bot's on_command_error handler. if not ch.permissions_for(ctx.guild.me).connect: raise commands.BotMissingPermissions(['connect']) if ch.guild != ctx.guild: raise VoiceCommandError('Guild mismatch') if str(ctx.guild.id) in self.voice_chans: if ch.id == self.voice_chans[str(ctx.guild.id)]: raise VoiceCommandError('Already connected to that channel') vcl: discord.VoiceClient = ctx.voice_client if vcl is None: raise VoiceCommandError( 'Guild does not support voice connections') if vcl.is_connected(): await vcl.move_to(ch) else: await ch.connect() else: await ch.connect() self.voice_chans[str(ctx.guild.id)] = ch.id await ctx.send('Joined the voice channel!')
async def delete_channel(self, channel: discord.VoiceChannel): """Delete an unusued channel if no one is in""" if len(channel.members) == 0 and channel.permissions_for( channel.guild.me).manage_channels: await channel.delete(reason="Unusued") self.db_delete_channel(channel)
def can_join_and_speak(self, channel: discord.VoiceChannel) -> bool: current_perms = channel.permissions_for(channel.guild.me) return current_perms.speak and current_perms.connect
async def check_perms_source_dest( self, autoroom_source: discord.VoiceChannel, category_dest: discord.CategoryChannel, detailed=False, ): """Check if the permissions in an AutoRoom Source and a destination category are sufficient.""" source = autoroom_source.permissions_for(autoroom_source.guild.me) dest = category_dest.permissions_for(category_dest.guild.me) # Check the basics result = (source.move_members and source.view_channel and source.connect and dest.view_channel and dest.manage_channels and dest.manage_messages and dest.connect and dest.move_members) if not detailed and not result: return False # Check the @everyone overwrites if they exist override_section = None if (autoroom_source.overwrites and autoroom_source.guild.default_role in autoroom_source.overwrites): overwrites = autoroom_source.overwrites[ autoroom_source.guild.default_role] # Skip permissions we can't give (manage_roles) or are required to be True (view_channel/connect) overwrites.update(view_channel=None, manage_roles=None, connect=None) for overwrite in overwrites: if overwrite[1] is not None: check_result = getattr(dest, overwrite[0]) if detailed: result = result and check_result if not override_section: override_section = SettingDisplay( f"Optional @everyone Permissions") override_section.add( overwrite[0].capitalize().replace("_", " "), check_result) elif not check_result: return False if not detailed: return True source_section = SettingDisplay( f"Required on Source: {autoroom_source.name}") source_section.add("Move members", source.move_members) source_section.add("View channels", source.view_channel) source_section.add("Connect", source.connect) dest_section = SettingDisplay( f"Required on Destination: {category_dest.name}") dest_section.add("View channels", dest.view_channel) dest_section.add("Manage channels", dest.manage_channels) dest_section.add("Manage messages", dest.manage_messages) dest_section.add("Connect", dest.connect) dest_section.add("Move members", dest.move_members) autoroom_sections = [dest_section] if override_section: autoroom_sections.append(override_section) return result, source_section.display(*autoroom_sections)
def _bot_can_move_members(self, channel: discord.VoiceChannel) -> bool: return channel.permissions_for(channel.guild.me).move_members
def check_perms_source_dest( self, autoroom_source: discord.VoiceChannel, category_dest: discord.CategoryChannel, with_manage_roles_guild=False, with_text_channel=False, with_optional_clone_perms=False, split_required_optional_check=False, detailed=False, ): """Check if the permissions in an AutoRoom Source and a destination category are sufficient.""" source = autoroom_source.permissions_for(autoroom_source.guild.me) dest = category_dest.permissions_for(category_dest.guild.me) result_required = True result_optional = True # Required for perm_name in self.perms_bot_source: result_required = result_required and getattr(source, perm_name) for perm_name in self.perms_bot_dest: result_required = result_required and getattr(dest, perm_name) if with_manage_roles_guild: result_required = ( result_required and category_dest.guild.me.guild_permissions.manage_roles ) # Optional if with_text_channel: for perm_name in self.perms_bot_dest_text: result_optional = result_optional and getattr(dest, perm_name) clone_section = None if with_optional_clone_perms: if detailed: clone_result, clone_section = self._check_perms_source_dest_optional( autoroom_source, dest, detailed=True ) else: clone_result = self._check_perms_source_dest_optional( autoroom_source, dest ) result_optional = result_optional and clone_result result = result_required and result_optional if not detailed: if split_required_optional_check: return result_required, result_optional else: return result source_section = SettingDisplay("Required on Source Voice Channel") for perm_name in self.perms_bot_source: source_section.add( perm_name.capitalize().replace("_", " "), getattr(source, perm_name) ) dest_section = SettingDisplay("Required on Destination Category") for perm_name in self.perms_bot_dest: dest_section.add( perm_name.capitalize().replace("_", " "), getattr(dest, perm_name) ) autoroom_sections = [dest_section] if with_manage_roles_guild: guild_section = SettingDisplay("Required in Guild") guild_section.add( "Manage roles", category_dest.guild.me.guild_permissions.manage_roles ) autoroom_sections.append(guild_section) if with_text_channel: text_section = SettingDisplay( "Optional on Destination Category (for text channel)" ) for perm_name in self.perms_bot_dest_text: text_section.add( perm_name.capitalize().replace("_", " "), getattr(dest, perm_name) ) autoroom_sections.append(text_section) if clone_section: autoroom_sections.append(clone_section) status_emoji = "\N{NO ENTRY SIGN}" if result: status_emoji = "\N{WHITE HEAVY CHECK MARK}" elif result_required: status_emoji = "\N{WARNING SIGN}\N{VARIATION SELECTOR-16}" result_str = ( f"\n{status_emoji} Source VC: {autoroom_source.mention} -> Dest Category: {category_dest.mention}" "\n" f"{source_section.display(*autoroom_sections)}" ) if split_required_optional_check: return result_required, result_optional, result_str else: return result, result_str