Ejemplo n.º 1
0
 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}**"
     )
Ejemplo n.º 2
0
 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
Ejemplo n.º 3
0
    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))
Ejemplo n.º 4
0
 async def play_song_wrapper(self,
                             voice_client: discord.VoiceClient,
                             channel: discord.VoiceChannel = None):
     try:
         self.play_song(voice_client, channel)
     except discord.errors.ClientException as e:
         if 'Not connected to voice' in str(e):
             channel.connect()
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    def is_hide(channel: discord.VoiceChannel) -> bool:
        guild: discord.Guild = channel.guild
        everyone_perms = dict(channel.overwrites_for(guild.default_role))

        if everyone_perms['view_channel']:
            return False

        return True
	async def stop(self, ctx):
		vc = ctx.voice_client

		if not vc or not vc.is_connected():
			return await ctx.send('I\'m not playing any song at the moment', delete_after=10)

		try:
			await ctx.guild.voice_client.disconnect() #Implement this on Music class
			await self.music_player.stop_queue_loop()
			self.music_player = None
		except AttributeError:
			pass
Ejemplo n.º 8
0
    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()
Ejemplo n.º 10
0
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.",
    )
Ejemplo n.º 11
0
    def play_song(self,
                  voice_client: discord.VoiceClient,
                  channel: discord.VoiceChannel = None) -> None:
        """
        Plays the first song in the playlist queue.

        :param voice_client: The discord VoiceClient that the bot should play into.
        :param channel: A channel to connect to if the bot is currently not in one.
        :return: None
        """
        try:
            print(self.playlist)
            source = discord.FFmpegOpusAudio(
                self.playlist[0],
                options={'use_wallclock_as_timestamps': True})
            voice_client.play(source, after=self.play_after)
            self.playlist.pop(0)
            self.current_song_playing = self.playlist_data.pop(0)
            self.song_started_at = datetime.datetime.now()
        except discord.errors.ClientException as e:
            if 'Not connected to voice' in str(e):
                channel.connect()
Ejemplo n.º 12
0
    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.")
Ejemplo n.º 13
0
    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
Ejemplo n.º 14
0
    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()
Ejemplo n.º 15
0
    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)
Ejemplo n.º 16
0
    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()
Ejemplo n.º 17
0
    async def setTimeChannel(self, ctx, channel: VoiceChannel):
        """
        Docstring goes here.
        """
        guild = ctx.guild
        ok = add_guild_time_channel(guild, channel)
        if ok:
            msg = (
                "{} set as the Snorlax time channel successfully."
                " Make sure Snorlax has the correct permissions!".format(
                    channel.mention
                )
            )
            # Make sure the channel permissions are set
            role = ctx.guild.default_role
            overwrites = channel.overwrites_for(role)
            overwrites.connect = False
            await channel.set_permissions(role, overwrite=overwrites)
        else:
            msg = (
                "Error when setting the time channel."
            )

        await ctx.channel.send(msg)
Ejemplo n.º 18
0
 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."
         )
Ejemplo n.º 19
0
    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!')
Ejemplo n.º 20
0
 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
Ejemplo n.º 21
0
def test_server_info_command(time_since_patch, cog, ctx, moderator_role):
    time_since_patch.return_value = '2 days ago'

    ctx.guild.created_at = datetime(2001, 1, 1)
    ctx.guild.features = ('lemons', 'apples')
    ctx.guild.region = 'The Moon'
    ctx.guild.roles = [moderator_role]
    ctx.guild.channels = [
        TextChannel(state={},
                    guild=ctx.guild,
                    data={
                        'id': 42,
                        'name': 'lemons-offering',
                        'position': 22,
                        'type': 'text'
                    }),
        CategoryChannel(state={},
                        guild=ctx.guild,
                        data={
                            'id': 5125,
                            'name': 'the-lemon-collection',
                            'position': 22,
                            'type': 'category'
                        }),
        VoiceChannel(state={},
                     guild=ctx.guild,
                     data={
                         'id': 15290,
                         'name': 'listen-to-lemon',
                         'position': 22,
                         'type': 'voice'
                     })
    ]
    ctx.guild.members = [
        member('online'),
        member('online'),
        member('idle'),
        member('dnd'),
        member('dnd'),
        member('dnd'),
        member('dnd'),
        member('offline'),
        member('offline'),
        member('offline')
    ]
    ctx.guild.member_count = 1_234
    ctx.guild.icon_url = 'a-lemon.png'

    coroutine = cog.server_info.callback(cog, ctx)
    assert asyncio.run(coroutine) is None  # no rval

    time_since_patch.assert_called_once_with(ctx.guild.created_at,
                                             precision='days')
    _, kwargs = ctx.send.call_args
    embed = kwargs.pop('embed')
    assert embed.colour == Colour.blurple()
    assert embed.description == textwrap.dedent(f"""
        **Server information**
        Created: {time_since_patch.return_value}
        Voice region: {ctx.guild.region}
        Features: {', '.join(ctx.guild.features)}

        **Counts**
        Members: {ctx.guild.member_count:,}
        Roles: {len(ctx.guild.roles)}
        Text: 1
        Voice: 1
        Channel categories: 1

        **Members**
        {Emojis.status_online} 2
        {Emojis.status_idle} 1
        {Emojis.status_dnd} 4
        {Emojis.status_offline} 3
        """)
    assert embed.thumbnail.url == 'a-lemon.png'
	async def pause(self, ctx):
		vc = ctx.voice_client
		if vc and vc.is_playing():
			vc.pause()
Ejemplo n.º 23
0
    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)
Ejemplo n.º 24
0
 def _bot_can_move_members(self, channel: discord.VoiceChannel) -> bool:
     return channel.permissions_for(channel.guild.me).move_members
	async def resume(self, ctx):
		vc = ctx.voice_client
		if vc and vc.is_paused():
			vc.resume()
Ejemplo n.º 26
0
    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
Ejemplo n.º 27
0
 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)