示例#1
0
    async def determine_music_source(self, ctx: commands.Context,
                                     song_str: Optional[str]):
        try:
            player = lavalink.get_player(ctx.guild.id)
        except (KeyError, IndexError):
            player = None
        if not player and song_str:
            return BOT_SONG_RE.sub("", song_str)
        if not (player or song_str):
            return None
        if player and song_str:
            return BOT_SONG_RE.sub("", song_str)

        possible_music = player.current
        if not possible_music:
            return None
        return BOT_SONG_RE.sub("", possible_music.title)
示例#2
0
 async def command_stop(self, ctx: commands.Context):
     """Stop playback and clear the queue."""
     dj_enabled = self._dj_status_cache.setdefault(
         ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
     )
     vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
     if not self._player_check(ctx):
         return await self.send_embed_msg(ctx, title=_("Nothing playing."))
     player = lavalink.get_player(ctx.guild.id)
     can_skip = await self._can_instaskip(ctx, ctx.author)
     is_alone = await self.is_requester_alone(ctx)
     if (not ctx.author.voice or ctx.author.voice.channel != player.channel) and not can_skip:
         return await self.send_embed_msg(
             ctx,
             title=_("Unable To Stop Player"),
             description=_("You must be in the voice channel to stop the music."),
         )
     if (vote_enabled or (vote_enabled and dj_enabled)) and not can_skip and not is_alone:
         return await self.send_embed_msg(
             ctx,
             title=_("Unable To Stop Player"),
             description=_("There are other people listening - vote to skip instead."),
         )
     if dj_enabled and not vote_enabled and not can_skip:
         return await self.send_embed_msg(
             ctx,
             title=_("Unable To Stop Player"),
             description=_("You need the DJ role to stop the music."),
         )
     if (
         player.is_playing
         or (not player.is_playing and player.paused)
         or player.queue
         or getattr(player.current, "extras", {}).get("autoplay")
     ):
         eq = player.fetch("eq")
         if eq:
             await self.config.custom("EQUALIZER", ctx.guild.id).eq_bands.set(eq.bands)
         player.queue = []
         player.store("playing_song", None)
         player.store("prev_requester", None)
         player.store("prev_song", None)
         player.store("requester", None)
         await player.stop()
         await self.send_embed_msg(ctx, title=_("Stopping..."))
示例#3
0
    async def command_disconnect(self, ctx: commands.Context):
        """Disconnect from the voice channel."""
        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        else:
            dj_enabled = self._dj_status_cache.setdefault(
                ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
            vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
            player = lavalink.get_player(ctx.guild.id)
            can_skip = await self._can_instaskip(ctx, ctx.author)
            if ((vote_enabled or (vote_enabled and dj_enabled))
                    and not can_skip
                    and not await self.is_requester_alone(ctx)):
                return await self.send_embed_msg(
                    ctx,
                    title=_("Unable To Disconnect"),
                    description=
                    _("There are other people listening - vote to skip instead."
                      ),
                )
            if dj_enabled and not vote_enabled and not can_skip:
                return await self.send_embed_msg(
                    ctx,
                    title=_("Unable To Disconnect"),
                    description=_("You need the DJ role to disconnect."),
                )
            if dj_enabled and not can_skip:
                return await self.send_embed_msg(
                    ctx,
                    title=_("Unable to Disconnect"),
                    description=_("You need the DJ role to disconnect."),
                )

            await self.send_embed_msg(ctx, title=_("Disconnecting..."))
            self.bot.dispatch("red_audio_audio_disconnect", ctx.guild)
            self.update_player_lock(ctx, False)
            eq = player.fetch("eq")
            player.queue = []
            player.store("playing_song", None)
            if eq:
                await self.config.custom("EQUALIZER",
                                         ctx.guild.id).eq_bands.set(eq.bands)
            await player.stop()
            await player.disconnect()
            await self.api_interface.persistent_queue_api.drop(ctx.guild.id)
示例#4
0
    async def command_bump(self, ctx: commands.Context, index: int):
        """Bump a track number to the top of the queue."""
        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
        )
        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        player = lavalink.get_player(ctx.guild.id)
        can_skip = await self._can_instaskip(ctx, ctx.author)
        if (
            not ctx.author.voice or ctx.author.voice.channel != player.channel
        ) and not can_skip:
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Bump Track"),
                description=_("You must be in the voice channel to bump a track."),
            )
        if dj_enabled and not can_skip:
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Bump Track"),
                description=_("You need the DJ role to bump tracks."),
            )
        if index > len(player.queue) or index < 1:
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Bump Track"),
                description=_(
                    "Song number must be greater than 1 and within the queue limit."
                ),
            )

        bump_index = index - 1
        bump_song = player.queue[bump_index]
        bump_song.extras["bumped"] = True
        player.queue.insert(0, bump_song)
        removed = player.queue.pop(index)
        description = await self.get_track_description(
            removed, self.local_folder_current_path
        )
        await self.send_embed_msg(
            ctx,
            title=_("Moved track to the top of the queue."),
            description=description,
        )
示例#5
0
 async def command_volume(self, ctx: commands.Context, vol: int = None):
     """Set the volume, 1% - 150%."""
     dj_enabled = self._dj_status_cache.setdefault(
         ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
     can_skip = await self._can_instaskip(ctx, ctx.author)
     if not vol:
         vol = await self.config.guild(ctx.guild).volume()
         embed = discord.Embed(title=_("Current Volume:"),
                               description=str(vol) + "%")
         if not self._player_check(ctx):
             embed.set_footer(text=_("Nothing playing."))
         return await self.send_embed_msg(ctx, embed=embed)
     if self._player_check(ctx):
         player = lavalink.get_player(ctx.guild.id)
         if (not ctx.author.voice or ctx.author.voice.channel !=
                 player.channel) and not can_skip:
             return await self.send_embed_msg(
                 ctx,
                 title=_("Unable To Change Volume"),
                 description=_(
                     "You must be in the voice channel to change the volume."
                 ),
             )
     if dj_enabled and not can_skip and not await self._has_dj_role(
             ctx, ctx.author):
         return await self.send_embed_msg(
             ctx,
             title=_("Unable To Change Volume"),
             description=_("You need the DJ role to change the volume."),
         )
     if vol < 0:
         vol = 0
     if vol > 150:
         vol = 150
         await self.config.guild(ctx.guild).volume.set(vol)
         if self._player_check(ctx):
             await lavalink.get_player(ctx.guild.id).set_volume(vol)
     else:
         await self.config.guild(ctx.guild).volume.set(vol)
         if self._player_check(ctx):
             await lavalink.get_player(ctx.guild.id).set_volume(vol)
     embed = discord.Embed(title=_("Volume:"), description=str(vol) + "%")
     if not self._player_check(ctx):
         embed.set_footer(text=_("Nothing playing."))
     await self.send_embed_msg(ctx, embed=embed)
示例#6
0
文件: utils.py 项目: Cheoz/dondog
async def queue_duration(ctx):
    player = lavalink.get_player(ctx.guild.id)
    duration = []
    for i in range(len(player.queue)):
        if not player.queue[i].is_stream:
            duration.append(player.queue[i].length)
    queue_dur = sum(duration)
    if not player.queue:
        queue_dur = 0
    try:
        if not player.current.is_stream:
            remain = player.current.length - player.position
        else:
            remain = 0
    except AttributeError:
        remain = 0
    queue_total_duration = remain + queue_dur
    return queue_total_duration
示例#7
0
 async def queue_duration(self, ctx: commands.Context) -> int:
     player = lavalink.get_player(ctx.guild.id)
     dur = [
         i.length
         async for i in AsyncIter(player.queue, steps=50).filter(lambda x: not x.is_stream)
     ]
     queue_dur = sum(dur)
     if not player.queue:
         queue_dur = 0
     try:
         if not player.current.is_stream:
             remain = player.current.length - player.position
         else:
             remain = 0
     except AttributeError:
         remain = 0
     queue_total_duration = remain + queue_dur
     return queue_total_duration
示例#8
0
文件: queue.py 项目: jeavinci/Lilith
 async def command_queue_clean(self, ctx: commands.Context):
     """Removes songs from the queue if the requester is not in the voice channel."""
     try:
         player = lavalink.get_player(ctx.guild.id)
     except KeyError:
         return await self.send_embed_msg(ctx, title=_("There's nothing in the queue."))
     dj_enabled = self._dj_status_cache.setdefault(
         ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
     )
     if not self._player_check(ctx) or not player.queue:
         return await self.send_embed_msg(ctx, title=_("There's nothing in the queue."))
     if (
         dj_enabled
         and not await self._can_instaskip(ctx, ctx.author)
         and not await self.is_requester_alone(ctx)
     ):
         return await self.send_embed_msg(
             ctx,
             title=_("Unable To Clean Queue"),
             description=_("You need the DJ role to clean the queue."),
         )
     clean_tracks = []
     removed_tracks = 0
     listeners = player.channel.members
     async for track in AsyncIter(player.queue):
         if track.requester in listeners:
             clean_tracks.append(track)
         else:
             await self.api_interface.persistent_queue_api.played(
                 ctx.guild.id, track.extras.get("enqueue_time")
             )
             removed_tracks += 1
     player.queue = clean_tracks
     if removed_tracks == 0:
         await self.send_embed_msg(ctx, title=_("Removed 0 tracks."))
     else:
         await self.send_embed_msg(
             ctx,
             title=_("Removed Tracks From The Queue"),
             description=_(
                 "Removed {removed_tracks} tracks queued by members "
                 "outside of the voice channel."
             ).format(removed_tracks=removed_tracks),
         )
示例#9
0
文件: queue.py 项目: jeavinci/Lilith
    async def command_queue_search(self, ctx: commands.Context, *, search_words: str):
        """Search the queue."""
        try:
            player = lavalink.get_player(ctx.guild.id)
        except KeyError:
            return await self.send_embed_msg(ctx, title=_("There's nothing in the queue."))
        if not self._player_check(ctx) or not player.queue:
            return await self.send_embed_msg(ctx, title=_("There's nothing in the queue."))

        search_list = await self._build_queue_search_list(player.queue, search_words)
        if not search_list:
            return await self.send_embed_msg(ctx, title=_("No matches."))

        len_search_pages = math.ceil(len(search_list) / 10)
        search_page_list = []
        async for page_num in AsyncIter(range(1, len_search_pages + 1)):
            embed = await self._build_queue_search_page(ctx, page_num, search_list)
            search_page_list.append(embed)
        await menu(ctx, search_page_list, DEFAULT_CONTROLS)
示例#10
0
文件: utils.py 项目: Cheoz/dondog
async def draw_time(ctx):
    player = lavalink.get_player(ctx.guild.id)
    paused = player.paused
    pos = player.position
    dur = player.current.length
    sections = 12
    loc_time = round((pos / dur) * sections)
    bar = "\N{BOX DRAWINGS HEAVY HORIZONTAL}"
    seek = "\N{RADIO BUTTON}"
    if paused:
        msg = "\N{DOUBLE VERTICAL BAR}"
    else:
        msg = "\N{BLACK RIGHT-POINTING TRIANGLE}"
    for i in range(sections):
        if i == loc_time:
            msg += seek
        else:
            msg += bar
    return msg
示例#11
0
    async def command_pause(self, ctx: commands.Context):
        """Pause or resume a playing track."""
        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        player = lavalink.get_player(ctx.guild.id)
        can_skip = await self._can_instaskip(ctx, ctx.author)
        if (not ctx.author.voice or
                ctx.author.voice.channel != player.channel) and not can_skip:
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Manage Tracks"),
                description=_(
                    "You must be in the voice channel to pause or resume."),
            )
        if dj_enabled and not can_skip and not await self.is_requester_alone(
                ctx):
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Manage Tracks"),
                description=_(
                    "You need the DJ role to pause or resume tracks."),
            )
        player.store("channel", ctx.channel.id)
        player.store("guild", ctx.guild.id)
        if not player.current:
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        description = await self.get_track_description(
            player.current, self.local_folder_current_path)

        if player.current and not player.paused:
            await player.pause()
            return await self.send_embed_msg(ctx,
                                             title=_("Track Paused"),
                                             description=description)
        if player.current and player.paused:
            await player.pause(False)
            return await self.send_embed_msg(ctx,
                                             title=_("Track Resumed"),
                                             description=description)

        await self.send_embed_msg(ctx, title=_("Nothing playing."))
示例#12
0
 async def draw_time(self, ctx) -> str:
     player = lavalink.get_player(ctx.guild.id)
     paused = player.paused
     pos = player.position or 1
     dur = getattr(player.current, "length", player.position or 1)
     sections = 12
     loc_time = round((pos / dur if dur != 0 else pos) * sections)
     bar = "\N{BOX DRAWINGS HEAVY HORIZONTAL}"
     seek = "\N{RADIO BUTTON}"
     if paused:
         msg = "\N{DOUBLE VERTICAL BAR}\N{VARIATION SELECTOR-16}"
     else:
         msg = "\N{BLACK RIGHT-POINTING TRIANGLE}\N{VARIATION SELECTOR-16}"
     for i in range(sections):
         if i == loc_time:
             msg += seek
         else:
             msg += bar
     return msg
示例#13
0
    async def command_equalizer_load(self, ctx: commands.Context, eq_preset: str):
        """Load a saved eq preset."""
        eq_preset = eq_preset.lower()
        eq_presets = await self.config.custom("EQUALIZER", ctx.guild.id).eq_presets()
        try:
            eq_values = eq_presets[eq_preset]["bands"]
        except KeyError:
            return await self.send_embed_msg(
                ctx,
                title=_("No Preset Found"),
                description=_(
                    "Preset named {eq_preset} does not exist.".format(eq_preset=eq_preset)
                ),
            )
        except TypeError:
            eq_values = eq_presets[eq_preset]

        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))

        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
        )
        player = lavalink.get_player(ctx.guild.id)
        if dj_enabled and not await self._can_instaskip(ctx, ctx.author):
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Load Preset"),
                description=_("You need the DJ role to load equalizer presets."),
            )
        player.store("notify_channel", ctx.channel.id)
        await self.config.custom("EQUALIZER", ctx.guild.id).eq_bands.set(eq_values)
        await self._eq_check(ctx, player)
        eq = player.fetch("eq", Equalizer())
        await self._eq_msg_clear(player.fetch("eq_message"))
        message = await ctx.send(
            content=box(eq.visualise(), lang="ini"),
            embed=discord.Embed(
                colour=await ctx.embed_colour(),
                title=_("The {eq_preset} preset was loaded.".format(eq_preset=eq_preset)),
            ),
        )
        player.store("eq_message", message)
示例#14
0
 async def on_voice_state_update(self, member: discord.Member,
                                 before: discord.VoiceState,
                                 after: discord.VoiceState) -> None:
     await self.cog_ready_event.wait()
     if after.channel != before.channel:
         try:
             self.skip_votes[before.channel.guild].remove(member.id)
         except (ValueError, KeyError, AttributeError):
             pass
     channel = self.rgetattr(member, "voice.channel", None)
     bot_voice_state = self.rgetattr(member, "guild.me.voice.self_deaf",
                                     None)
     if channel and bot_voice_state is False:
         try:
             player = lavalink.get_player(channel.guild.id)
         except (KeyError, AttributeError):
             pass
         else:
             if player.channel.id == channel.id:
                 await self.self_deafen(player)
示例#15
0
    async def command_shuffle_bumpped(self, ctx: commands.Context):
        """Toggle bumped track shuffle.

        Set this to disabled if you wish to avoid bumped songs being shuffled. This takes priority
        over `[p]shuffle`.
        """
        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
        )
        can_skip = await self._can_instaskip(ctx, ctx.author)
        if dj_enabled and not can_skip:
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Toggle Shuffle"),
                description=_("You need the DJ role to toggle shuffle."),
            )
        if self._player_check(ctx):
            await self.set_player_settings(ctx)
            player = lavalink.get_player(ctx.guild.id)
            if (
                not ctx.author.voice or ctx.author.voice.channel != player.channel
            ) and not can_skip:
                return await self.send_embed_msg(
                    ctx,
                    title=_("Unable To Toggle Shuffle"),
                    description=_("You must be in the voice channel to toggle shuffle."),
                )
            player.store("channel", ctx.channel.id)
            player.store("guild", ctx.guild.id)

        bumped = await self.config.guild(ctx.guild).shuffle_bumped()
        await self.config.guild(ctx.guild).shuffle_bumped.set(not bumped)
        await self.send_embed_msg(
            ctx,
            title=_("Setting Changed"),
            description=_("Shuffle bumped tracks: {true_or_false}.").format(
                true_or_false=_("Enabled") if not bumped else _("Disabled")
            ),
        )
        if self._player_check(ctx):
            await self.set_player_settings(ctx)
示例#16
0
    async def command_repeat(self, ctx: commands.Context):
        """Toggle repeat."""
        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
        )
        can_skip = await self._can_instaskip(ctx, ctx.author)
        if dj_enabled and not can_skip and not await self._has_dj_role(ctx, ctx.author):
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Toggle Repeat"),
                description=_("You need the DJ role to toggle repeat."),
            )
        if self._player_check(ctx):
            await self.set_player_settings(ctx)
            player = lavalink.get_player(ctx.guild.id)
            if (
                not ctx.author.voice or ctx.author.voice.channel != player.channel
            ) and not can_skip:
                return await self.send_embed_msg(
                    ctx,
                    title=_("Unable To Toggle Repeat"),
                    description=_("You must be in the voice channel to toggle repeat."),
                )
            player.store("channel", ctx.channel.id)
            player.store("guild", ctx.guild.id)

        autoplay = await self.config.guild(ctx.guild).auto_play()
        repeat = await self.config.guild(ctx.guild).repeat()
        msg = ""
        msg += _("Repeat tracks: {true_or_false}.").format(
            true_or_false=_("Enabled") if not repeat else _("Disabled")
        )
        await self.config.guild(ctx.guild).repeat.set(not repeat)
        if repeat is not True and autoplay is True:
            msg += _("\nAuto-play has been disabled.")
            await self.config.guild(ctx.guild).auto_play.set(False)

        embed = discord.Embed(title=_("Setting Changed"), description=msg)
        await self.send_embed_msg(ctx, embed=embed)
        if self._player_check(ctx):
            await self.set_player_settings(ctx)
示例#17
0
 async def on_red_audio_track_start(self, guild: discord.Guild,
                                    track: lavalink.Track,
                                    requester: discord.Member):
     if not (guild and track):
         return
     if track.author.lower() not in track.title.lower():
         title = f"{track.title}"
     else:
         title = track.title
     self._cache[guild.id] = title
     auto_lyrics = await self.config.guild(guild).auto_lyrics()
     if auto_lyrics is True:
         notify_channel = lavalink.get_player(guild.id).fetch("channel")
         if not notify_channel:
             return
         notify_channel = self.bot.get_channel(notify_channel)
         botsong = BOT_SONG_RE.sub('', self._cache[guild.id]).strip()
         try:
             async with notify_channel.typing():
                 title, artist, lyrics, source = await getlyrics(botsong)
                 paged_embeds = []
                 paged_content = [
                     p for p in pagify(lyrics, page_length=900)
                 ]
                 for index, page in enumerate(paged_content):
                     e = discord.Embed(
                         title='{} by {}'.format(title, artist),
                         description=page,
                         colour=await
                         self.bot.get_embed_color(notify_channel))
                     e.set_footer(
                         text='Requested by {} | Source: {} | Page: {}/{}'.
                         format(track.requester, source, index,
                                len(paged_content)))
                     paged_embeds.append(e)
             await menu(notify_channel,
                        paged_embeds,
                        controls=DEFAULT_CONTROLS,
                        timeout=180.0)
         except discord.Forbidden:
             return await notify_channel.send("Missing embed permissions..")
示例#18
0
    async def on_voice_state_update(
        self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState
    ) -> None:
        if await self.bot.cog_disabled_in_guild(self, member.guild):
            return
        await self.cog_ready_event.wait()
        if after.channel != before.channel:
            try:
                self.skip_votes[before.channel.guild.id].discard(member.id)
            except (ValueError, KeyError, AttributeError):
                pass

        # if (
        #     member == member.guild.me
        #     and before.channel
        #     and after.channel
        #     and after.channel.id != before.channel.id
        # ):
        #     try:
        #         player = lavalink.get_player(member.guild.id)
        #         if player.is_playing:
        #             await player.resume(player.current, start=player.position, replace=False)
        #             log.debug("Bot changed channel - Resume playback")
        #     except:
        #         log.debug("Bot changed channel - Unable to resume playback")

        channel = self.rgetattr(member, "voice.channel", None)
        bot_voice_state = self.rgetattr(member, "guild.me.voice.self_deaf", None)
        if (
            channel
            and bot_voice_state is False
            and await self.config.guild(member.guild).auto_deafen()
        ):
            try:
                player = lavalink.get_player(channel.guild.id)
            except (KeyError, AttributeError):
                pass
            else:
                if player.channel.id == channel.id:
                    await self.self_deafen(player)
示例#19
0
    async def command_equalizer(self, ctx: commands.Context):
        """Equalizer management.

        Band positions are 1-15 and values have a range of -0.25 to 1.0.
        Band names are 25, 40, 63, 100, 160, 250, 400, 630, 1k, 1.6k, 2.5k, 4k,
        6.3k, 10k, and 16k Hz.
        Setting a band value to -0.25 nullifies it while +0.25 is double.
        """
        if not self._player_check(ctx):
            ctx.command.reset_cooldown(ctx)
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
        )
        player = lavalink.get_player(ctx.guild.id)
        eq = player.fetch("eq", Equalizer())
        reactions = [
            "\N{BLACK LEFT-POINTING TRIANGLE}\N{VARIATION SELECTOR-16}",
            "\N{LEFTWARDS BLACK ARROW}\N{VARIATION SELECTOR-16}",
            "\N{BLACK UP-POINTING DOUBLE TRIANGLE}",
            "\N{UP-POINTING SMALL RED TRIANGLE}",
            "\N{DOWN-POINTING SMALL RED TRIANGLE}",
            "\N{BLACK DOWN-POINTING DOUBLE TRIANGLE}",
            "\N{BLACK RIGHTWARDS ARROW}\N{VARIATION SELECTOR-16}",
            "\N{BLACK RIGHT-POINTING TRIANGLE}\N{VARIATION SELECTOR-16}",
            "\N{BLACK CIRCLE FOR RECORD}\N{VARIATION SELECTOR-16}",
            "\N{INFORMATION SOURCE}\N{VARIATION SELECTOR-16}",
        ]
        await self._eq_msg_clear(player.fetch("eq_message"))
        eq_message = await ctx.send(box(eq.visualise(), lang="ini"))

        if dj_enabled and not await self._can_instaskip(ctx, ctx.author):
            with contextlib.suppress(discord.HTTPException):
                await eq_message.add_reaction("\N{INFORMATION SOURCE}\N{VARIATION SELECTOR-16}")
        else:
            start_adding_reactions(eq_message, reactions)

        eq_msg_with_reacts = await ctx.fetch_message(eq_message.id)
        player.store("eq_message", eq_msg_with_reacts)
        await self._eq_interact(ctx, player, eq, eq_msg_with_reacts, 0)
示例#20
0
    async def command_shuffle(self, ctx: commands.Context):
        """Toggle shuffle."""
        if ctx.invoked_subcommand is None:
            dj_enabled = self._dj_status_cache.setdefault(
                ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
            can_skip = await self._can_instaskip(ctx, ctx.author)
            if dj_enabled and not can_skip:
                return await self.send_embed_msg(
                    ctx,
                    title=_("Unable To Toggle Shuffle"),
                    description=_("You need the DJ role to toggle shuffle."),
                )
            if self._player_check(ctx):
                await self.set_player_settings(ctx)
                player = lavalink.get_player(ctx.guild.id)
                if (not ctx.author.voice or ctx.author.voice.channel !=
                        player.channel) and not can_skip:
                    return await self.send_embed_msg(
                        ctx,
                        title=_("Unable To Toggle Shuffle"),
                        description=
                        _("You must be in the voice channel to toggle shuffle."
                          ),
                    )
                player.store("channel", ctx.channel.id)
                player.store("guild", ctx.guild.id)

            shuffle = await self.config.guild(ctx.guild).shuffle()
            await self.config.guild(ctx.guild).shuffle.set(not shuffle)
            await self.send_embed_msg(
                ctx,
                title=_("Setting Changed"),
                description=_("Shuffle tracks: {true_or_false}.").format(
                    true_or_false=_("Enabled") if not shuffle else _("Disabled"
                                                                     )),
            )
            if self._player_check(ctx):
                await self.set_player_settings(ctx)
示例#21
0
文件: player.py 项目: PrimeEdits/bott
    async def maybe_move_player(self, ctx: commands.Context) -> bool:
        try:
            player = lavalink.get_player(ctx.guild.id)
        except KeyError:
            return False
        try:
            in_channel = sum(not m.bot for m in ctx.guild.get_member(
                self.bot.user.id).voice.channel.members)
        except AttributeError:
            return False

        if not ctx.author.voice:
            user_channel = None
        else:
            user_channel = ctx.author.voice.channel

        if in_channel == 0 and user_channel:
            if ((player.channel != user_channel) and not player.current
                    and player.position == 0 and len(player.queue) == 0):
                await player.move_to(user_channel)
                return True
        else:
            return False
示例#22
0
 async def command_queue_clear(self, ctx: commands.Context):
     """Clears the queue."""
     try:
         player = lavalink.get_player(ctx.guild.id)
     except KeyError:
         return await self.send_embed_msg(
             ctx, title=_("There's nothing in the queue."))
     dj_enabled = self._dj_status_cache.setdefault(
         ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
     if not self._player_check(ctx) or not player.queue:
         return await self.send_embed_msg(
             ctx, title=_("There's nothing in the queue."))
     if (dj_enabled and not await self._can_instaskip(ctx, ctx.author)
             and not await self.is_requester_alone(ctx)):
         return await self.send_embed_msg(
             ctx,
             title=_("Unable To Clear Queue"),
             description=_("You need the DJ role to clear the queue."),
         )
     player.queue.clear()
     await self.send_embed_msg(ctx,
                               title=_("Queue Modified"),
                               description=_("The queue has been cleared."))
示例#23
0
    async def on_voice_state_update(self, member: discord.Member,
                                    before: discord.VoiceState,
                                    after: discord.VoiceState) -> None:
        if await self.bot.cog_disabled_in_guild(self, member.guild):
            return
        await self.cog_ready_event.wait()
        if after.channel != before.channel:
            try:
                self.skip_votes[before.channel.guild.id].discard(member.id)
            except (ValueError, KeyError, AttributeError):
                pass

        channel = self.rgetattr(member, "voice.channel", None)
        bot_voice_state = self.rgetattr(member, "guild.me.voice.self_deaf",
                                        None)
        if (channel and bot_voice_state is False
                and await self.config.guild(member.guild).auto_deafen()):
            try:
                player = lavalink.get_player(channel.guild.id)
            except (KeyError, AttributeError):
                pass
            else:
                if player.channel.id == channel.id:
                    await self.self_deafen(player)
示例#24
0
    async def command_now(self, ctx: commands.Context):
        """Now playing."""
        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        emoji = {
            "prev":
            "\N{BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}\N{VARIATION SELECTOR-16}",
            "stop": "\N{BLACK SQUARE FOR STOP}\N{VARIATION SELECTOR-16}",
            "pause":
            "\N{BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR}\N{VARIATION SELECTOR-16}",
            "next":
            "\N{BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}\N{VARIATION SELECTOR-16}",
            "close": "\N{CROSS MARK}",
        }
        expected = tuple(emoji.values())
        player = lavalink.get_player(ctx.guild.id)
        player.store("notify_channel", ctx.channel.id)
        if player.current:
            arrow = await self.draw_time(ctx)
            pos = self.format_time(player.position)
            if player.current.is_stream:
                dur = "LIVE"
            else:
                dur = self.format_time(player.current.length)
            song = (await self.get_track_description(
                player.current, self.local_folder_current_path) or "")
            song += _("\n Requested by: **{track.requester}**").format(
                track=player.current)
            song += "\n\n{arrow}`{pos}`/`{dur}`".format(arrow=arrow,
                                                        pos=pos,
                                                        dur=dur)
        else:
            song = _("Nothing.")

        if player.fetch("np_message") is not None:
            with contextlib.suppress(discord.HTTPException):
                await player.fetch("np_message").delete()
        embed = discord.Embed(title=_("Now Playing"), description=song)
        guild_data = await self.config.guild(ctx.guild).all()

        if guild_data[
                "thumbnail"] and player.current and player.current.thumbnail:
            embed.set_thumbnail(url=player.current.thumbnail)
        shuffle = guild_data["shuffle"]
        repeat = guild_data["repeat"]
        autoplay = guild_data["auto_play"]
        text = ""
        text += (
            _("Auto-Play") + ": " +
            ("\N{WHITE HEAVY CHECK MARK}" if autoplay else "\N{CROSS MARK}"))
        text += (
            (" | " if text else "") + _("Shuffle") + ": " +
            ("\N{WHITE HEAVY CHECK MARK}" if shuffle else "\N{CROSS MARK}"))
        text += (
            (" | " if text else "") + _("Repeat") + ": " +
            ("\N{WHITE HEAVY CHECK MARK}" if repeat else "\N{CROSS MARK}"))

        message = await self.send_embed_msg(ctx, embed=embed, footer=text)

        player.store("np_message", message)

        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
        vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
        if ((dj_enabled or vote_enabled)
                and not await self._can_instaskip(ctx, ctx.author)
                and not await self.is_requester_alone(ctx)):
            return

        if not player.queue and not autoplay:
            expected = (emoji["stop"], emoji["pause"], emoji["close"])
        task: Optional[asyncio.Task]
        if player.current:
            task = start_adding_reactions(message, expected[:5])
        else:
            task = None

        try:
            (r, u) = await self.bot.wait_for(
                "reaction_add",
                check=ReactionPredicate.with_emojis(expected, message,
                                                    ctx.author),
                timeout=30.0,
            )
        except asyncio.TimeoutError:
            return await self._clear_react(message, emoji)
        else:
            if task is not None:
                task.cancel()
        reacts = {v: k for k, v in emoji.items()}
        react = reacts[r.emoji]
        if react == "prev":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_prev)
        elif react == "stop":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_stop)
        elif react == "pause":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_pause)
        elif react == "next":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_skip)
        elif react == "close":
            await message.delete()
示例#25
0
    async def _playlist_check(self, ctx: commands.Context) -> bool:
        if not self._player_check(ctx):
            if self.lavalink_connection_aborted:
                msg = _("Connection to Lavalink has failed")
                desc = EmptyEmbed
                if await self.bot.is_owner(ctx.author):
                    desc = _("Please check your console or logs for details.")
                await self.send_embed_msg(ctx, title=msg, description=desc)
                return False
            try:
                if (not ctx.author.voice.channel.permissions_for(
                        ctx.me).connect
                        or not ctx.author.voice.channel.permissions_for(
                            ctx.me).move_members
                        and self.is_vc_full(ctx.author.voice.channel)):
                    await self.send_embed_msg(
                        ctx,
                        title=_("Unable To Get Playlists"),
                        description=
                        _("I don't have permission to connect to your channel."
                          ),
                    )
                    return False
                await lavalink.connect(
                    ctx.author.voice.channel,
                    deafen=await
                    self.config.guild_from_id(ctx.guild.id).auto_deafen(),
                )
                player = lavalink.get_player(ctx.guild.id)
                player.store("connect", datetime.datetime.utcnow())
                player.store("channel", ctx.channel.id)
                player.store("guild", ctx.guild.id)
            except IndexError:
                await self.send_embed_msg(
                    ctx,
                    title=_("Unable To Get Playlists"),
                    description=_(
                        "Connection to Lavalink has not yet been established."
                    ),
                )
                return False
            except AttributeError:
                await self.send_embed_msg(
                    ctx,
                    title=_("Unable To Get Playlists"),
                    description=_("Connect to a voice channel first."),
                )
                return False

        player = lavalink.get_player(ctx.guild.id)
        player.store("channel", ctx.channel.id)
        player.store("guild", ctx.guild.id)
        if (not ctx.author.voice or ctx.author.voice.channel != player.channel
            ) and not await self._can_instaskip(ctx, ctx.author):
            await self.send_embed_msg(
                ctx,
                title=_("Unable To Get Playlists"),
                description=
                _("You must be in the voice channel to use the playlist command."
                  ),
            )
            return False
        await self._eq_check(ctx, player)
        await self.set_player_settings(ctx)
        return True
示例#26
0
    async def _skip_action(self, ctx: commands.Context, skip_to_track: int = None) -> None:
        player = lavalink.get_player(ctx.guild.id)
        autoplay = await self.config.guild(player.channel.guild).auto_play()
        if not player.current or (not player.queue and not autoplay):
            try:
                pos, dur = player.position, player.current.length
            except AttributeError:
                await self.send_embed_msg(ctx, title=_("There's nothing in the queue."))
                return
            time_remain = self.format_time(dur - pos)
            if player.current.is_stream:
                embed = discord.Embed(title=_("There's nothing in the queue."))
                embed.set_footer(
                    text=_("Currently livestreaming {track}").format(track=player.current.title)
                )
            else:
                embed = discord.Embed(title=_("There's nothing in the queue."))
                embed.set_footer(
                    text=_("{time} left on {track}").format(
                        time=time_remain, track=player.current.title
                    )
                )
            await self.send_embed_msg(ctx, embed=embed)
            return
        elif autoplay and not player.queue:
            embed = discord.Embed(
                title=_("Track Skipped"),
                description=await self.get_track_description(
                    player.current, self.local_folder_current_path
                ),
            )
            await self.send_embed_msg(ctx, embed=embed)
            await player.skip()
            return

        queue_to_append = []
        if skip_to_track is not None and skip_to_track != 1:
            if skip_to_track < 1:
                await self.send_embed_msg(
                    ctx, title=_("Track number must be equal to or greater than 1.")
                )
                return
            elif skip_to_track > len(player.queue):
                await self.send_embed_msg(
                    ctx,
                    title=_("There are only {queuelen} songs currently queued.").format(
                        queuelen=len(player.queue)
                    ),
                )
                return
            embed = discord.Embed(
                title=_("{skip_to_track} Tracks Skipped").format(skip_to_track=skip_to_track)
            )
            await self.send_embed_msg(ctx, embed=embed)
            if player.repeat:
                queue_to_append = player.queue[0 : min(skip_to_track - 1, len(player.queue) - 1)]
            player.queue = player.queue[
                min(skip_to_track - 1, len(player.queue) - 1) : len(player.queue)
            ]
        else:
            embed = discord.Embed(
                title=_("Track Skipped"),
                description=await self.get_track_description(
                    player.current, self.local_folder_current_path
                ),
            )
            await self.send_embed_msg(ctx, embed=embed)
        self.bot.dispatch("red_audio_skip_track", player.channel.guild, player.current, ctx.author)
        await player.play()
        player.queue += queue_to_append
示例#27
0
    async def player_automated_timer(self) -> None:
        stop_times: Dict = {}
        pause_times: Dict = {}
        while True:
            async for p in AsyncIter(lavalink.all_players()):
                server = p.channel.guild
                if await self.bot.cog_disabled_in_guild(self, server):
                    continue

                if [self.bot.user] == p.channel.members:
                    stop_times.setdefault(server.id, time.time())
                    pause_times.setdefault(server.id, time.time())
                else:
                    stop_times.pop(server.id, None)
                    if p.paused and server.id in pause_times:
                        try:
                            await p.pause(False)
                        except Exception as err:
                            debug_exc_log(
                                log,
                                err,
                                f"Exception raised in Audio's unpausing player for {server.id}.",
                            )
                    pause_times.pop(server.id, None)
            servers = stop_times.copy()
            servers.update(pause_times)
            async for sid in AsyncIter(servers, steps=5):
                server_obj = self.bot.get_guild(sid)
                if sid in stop_times and await self.config.guild(
                        server_obj).emptydc_enabled():
                    emptydc_timer = await self.config.guild(server_obj
                                                            ).emptydc_timer()
                    if (time.time() - stop_times[sid]) >= emptydc_timer:
                        stop_times.pop(sid)
                        try:
                            player = lavalink.get_player(sid)
                            await self.api_interface.persistent_queue_api.drop(
                                sid)
                            await player.stop()
                            await player.disconnect()
                        except Exception as err:
                            if "No such player for that guild" in str(err):
                                stop_times.pop(sid, None)
                            debug_exc_log(
                                log, err,
                                f"Exception raised in Audio's emptydc_timer for {sid}."
                            )
                elif (sid in pause_times and await
                      self.config.guild(server_obj).emptypause_enabled()):
                    emptypause_timer = await self.config.guild(
                        server_obj).emptypause_timer()
                    if (time.time() -
                            pause_times.get(sid, 0)) >= emptypause_timer:
                        try:
                            await lavalink.get_player(sid).pause()
                        except Exception as err:
                            if "No such player for that guild" in str(err):
                                pause_times.pop(sid, None)
                            debug_exc_log(
                                log, err,
                                f"Exception raised in Audio's pausing for {sid}."
                            )
            await asyncio.sleep(5)
示例#28
0
    async def _get_spotify_tracks(
        self, ctx: commands.Context, query: Query, forced: bool = False
    ) -> Union[discord.Message, List[lavalink.Track], lavalink.Track]:
        if ctx.invoked_with in ["play", "genre"]:
            enqueue_tracks = True
        else:
            enqueue_tracks = False
        player = lavalink.get_player(ctx.guild.id)
        api_data = await self._check_api_tokens()
        if any([not api_data["spotify_client_id"], not api_data["spotify_client_secret"]]):
            return await self.send_embed_msg(
                ctx,
                title=_("Invalid Environment"),
                description=_(
                    "The owner needs to set the Spotify client ID and Spotify client secret, "
                    "before Spotify URLs or codes can be used. "
                    "\nSee `{prefix}audioset spotifyapi` for instructions."
                ).format(prefix=ctx.prefix),
            )
        elif not api_data["youtube_api"]:
            return await self.send_embed_msg(
                ctx,
                title=_("Invalid Environment"),
                description=_(
                    "The owner needs to set the YouTube API key before Spotify URLs or "
                    "codes can be used.\nSee `{prefix}audioset youtubeapi` for instructions."
                ).format(prefix=ctx.prefix),
            )
        try:
            if self.play_lock[ctx.message.guild.id]:
                return await self.send_embed_msg(
                    ctx,
                    title=_("Unable To Get Tracks"),
                    description=_("Wait until the playlist has finished loading."),
                )
        except KeyError:
            pass

        if query.single_track:
            try:
                res = await self.api_interface.spotify_query(
                    ctx, "track", query.id, skip_youtube=True, notifier=None
                )
                if not res:
                    title = _("Nothing found.")
                    embed = discord.Embed(title=title)
                    if query.is_local and query.suffix in _PARTIALLY_SUPPORTED_MUSIC_EXT:
                        title = _("Track is not playable.")
                        description = _(
                            "**{suffix}** is not a fully supported "
                            "format and some tracks may not play."
                        ).format(suffix=query.suffix)
                        embed = discord.Embed(title=title, description=description)
                    return await self.send_embed_msg(ctx, embed=embed)
            except SpotifyFetchError as error:
                self.update_player_lock(ctx, False)
                return await self.send_embed_msg(
                    ctx, title=error.message.format(prefix=ctx.prefix)
                )
            except Exception as e:
                self.update_player_lock(ctx, False)
                raise e
            self.update_player_lock(ctx, False)
            try:
                if enqueue_tracks:
                    new_query = Query.process_input(res[0], self.local_folder_current_path)
                    new_query.start_time = query.start_time
                    return await self._enqueue_tracks(ctx, new_query)
                else:
                    query = Query.process_input(res[0], self.local_folder_current_path)
                    try:
                        result, called_api = await self.api_interface.fetch_track(
                            ctx, player, query
                        )
                    except TrackEnqueueError:
                        self.update_player_lock(ctx, False)
                        return await self.send_embed_msg(
                            ctx,
                            title=_("Unable to Get Track"),
                            description=_(
                                "I'm unable to get a track from Lavalink at the moment, "
                                "try again in a few minutes."
                            ),
                        )
                    tracks = result.tracks
                    if not tracks:
                        embed = discord.Embed(title=_("Nothing found."))
                        if query.is_local and query.suffix in _PARTIALLY_SUPPORTED_MUSIC_EXT:
                            embed = discord.Embed(title=_("Track is not playable."))
                            embed.description = _(
                                "**{suffix}** is not a fully supported format and some "
                                "tracks may not play."
                            ).format(suffix=query.suffix)
                        return await self.send_embed_msg(ctx, embed=embed)
                    single_track = tracks[0]
                    single_track.start_timestamp = query.start_time * 1000
                    single_track = [single_track]

                    return single_track

            except KeyError:
                self.update_player_lock(ctx, False)
                return await self.send_embed_msg(
                    ctx,
                    title=_("Invalid Environment"),
                    description=_(
                        "The Spotify API key or client secret has not been set properly. "
                        "\nUse `{prefix}audioset spotifyapi` for instructions."
                    ).format(prefix=ctx.prefix),
                )
            except Exception as e:
                self.update_player_lock(ctx, False)
                raise e
        elif query.is_album or query.is_playlist:
            try:
                self.update_player_lock(ctx, True)
                track_list = await self.fetch_spotify_playlist(
                    ctx,
                    "album" if query.is_album else "playlist",
                    query,
                    enqueue_tracks,
                    forced=forced,
                )
            finally:
                self.update_player_lock(ctx, False)
            return track_list
        else:
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Find Tracks"),
                description=_("This doesn't seem to be a supported Spotify URL or code."),
            )
示例#29
0
 async def fetch_spotify_playlist(
     self,
     ctx: commands.Context,
     stype: str,
     query: Query,
     enqueue: bool = False,
     forced: bool = False,
 ):
     player = lavalink.get_player(ctx.guild.id)
     try:
         embed1 = discord.Embed(title=_("Please wait, finding tracks..."))
         playlist_msg = await self.send_embed_msg(ctx, embed=embed1)
         notifier = Notifier(
             ctx,
             playlist_msg,
             {
                 "spotify": _("Getting track {num}/{total}..."),
                 "youtube": _("Matching track {num}/{total}..."),
                 "lavalink": _("Loading track {num}/{total}..."),
                 "lavalink_time": _("Approximate time remaining: {seconds}"),
             },
         )
         track_list = await self.api_interface.spotify_enqueue(
             ctx,
             stype,
             query.id,
             enqueue=enqueue,
             player=player,
             lock=self.update_player_lock,
             notifier=notifier,
             forced=forced,
             query_global=await self.config.global_db_enabled(),
         )
     except SpotifyFetchError as error:
         self.update_player_lock(ctx, False)
         return await self.send_embed_msg(
             ctx,
             title=_("Invalid Environment"),
             description=error.message.format(prefix=ctx.prefix),
         )
     except TrackEnqueueError:
         self.update_player_lock(ctx, False)
         return await self.send_embed_msg(
             ctx,
             title=_("Unable to Get Track"),
             description=_(
                 "I'm unable to get a track from Lavalink at the moment, "
                 "try again in a few minutes."
             ),
             error=True,
         )
     except (RuntimeError, aiohttp.ServerDisconnectedError):
         self.update_player_lock(ctx, False)
         error_embed = discord.Embed(
             title=_("The connection was reset while loading the playlist.")
         )
         await self.send_embed_msg(ctx, embed=error_embed)
         return None
     except Exception as e:
         self.update_player_lock(ctx, False)
         raise e
     finally:
         self.update_player_lock(ctx, False)
     return track_list
示例#30
0
    async def _enqueue_tracks(
        self, ctx: commands.Context, query: Union[Query, list], enqueue: bool = True
    ) -> Union[discord.Message, List[lavalink.Track], lavalink.Track]:
        player = lavalink.get_player(ctx.guild.id)
        try:
            if self.play_lock[ctx.message.guild.id]:
                return await self.send_embed_msg(
                    ctx,
                    title=_("Unable To Get Tracks"),
                    description=_("Wait until the playlist has finished loading."),
                )
        except KeyError:
            self.update_player_lock(ctx, True)
        guild_data = await self.config.guild(ctx.guild).all()
        first_track_only = False
        single_track = None
        index = None
        playlist_data = None
        playlist_url = None
        seek = 0
        if type(query) is not list:
            if not await self.is_query_allowed(self.config, ctx, f"{query}", query_obj=query):
                raise QueryUnauthorized(
                    _("{query} is not an allowed query.").format(query=query.to_string_user())
                )
            if query.single_track:
                first_track_only = True
                index = query.track_index
                if query.start_time:
                    seek = query.start_time
            try:
                result, called_api = await self.api_interface.fetch_track(ctx, player, query)
            except TrackEnqueueError:
                self.update_player_lock(ctx, False)
                return await self.send_embed_msg(
                    ctx,
                    title=_("Unable to Get Track"),
                    description=_(
                        "I'm unable to get a track from Lavalink at the moment, "
                        "try again in a few minutes."
                    ),
                )
            except Exception as e:
                self.update_player_lock(ctx, False)
                raise e
            tracks = result.tracks
            playlist_data = result.playlist_info
            if not enqueue:
                return tracks
            if not tracks:
                self.update_player_lock(ctx, False)
                title = _("Nothing found.")
                embed = discord.Embed(title=title)
                if result.exception_message:
                    if "Status Code" in result.exception_message:
                        embed.set_footer(text=result.exception_message[:2000])
                    else:
                        embed.set_footer(text=result.exception_message[:2000].replace("\n", ""))
                if await self.config.use_external_lavalink() and query.is_local:
                    embed.description = _(
                        "Local tracks will not work "
                        "if the `Lavalink.jar` cannot see the track.\n"
                        "This may be due to permissions or because Lavalink.jar is being run "
                        "in a different machine than the local tracks."
                    )
                elif query.is_local and query.suffix in _PARTIALLY_SUPPORTED_MUSIC_EXT:
                    title = _("Track is not playable.")
                    embed = discord.Embed(title=title)
                    embed.description = _(
                        "**{suffix}** is not a fully supported format and some "
                        "tracks may not play."
                    ).format(suffix=query.suffix)
                return await self.send_embed_msg(ctx, embed=embed)
        else:
            tracks = query
        queue_dur = await self.queue_duration(ctx)
        queue_total_duration = self.format_time(queue_dur)
        before_queue_length = len(player.queue)

        if not first_track_only and len(tracks) > 1:
            # a list of Tracks where all should be enqueued
            # this is a Spotify playlist already made into a list of Tracks or a
            # url where Lavalink handles providing all Track objects to use, like a
            # YouTube or Soundcloud playlist
            if len(player.queue) >= 10000:
                return await self.send_embed_msg(ctx, title=_("Queue size limit reached."))
            track_len = 0
            empty_queue = not player.queue
            async for track in AsyncIter(tracks):
                if len(player.queue) >= 10000:
                    continue
                query = Query.process_input(track, self.local_folder_current_path)
                if not await self.is_query_allowed(
                    self.config,
                    ctx,
                    f"{track.title} {track.author} {track.uri} " f"{str(query)}",
                    query_obj=query,
                ):
                    if IS_DEBUG:
                        log.debug(f"Query is not allowed in {ctx.guild} ({ctx.guild.id})")
                    continue
                elif guild_data["maxlength"] > 0:
                    if self.is_track_length_allowed(track, guild_data["maxlength"]):
                        track_len += 1
                        track.extras.update(
                            {
                                "enqueue_time": int(time.time()),
                                "vc": player.channel.id,
                                "requester": ctx.author.id,
                            }
                        )
                        player.add(ctx.author, track)
                        self.bot.dispatch(
                            "red_audio_track_enqueue", player.channel.guild, track, ctx.author
                        )

                else:
                    track_len += 1
                    track.extras.update(
                        {
                            "enqueue_time": int(time.time()),
                            "vc": player.channel.id,
                            "requester": ctx.author.id,
                        }
                    )
                    player.add(ctx.author, track)
                    self.bot.dispatch(
                        "red_audio_track_enqueue", player.channel.guild, track, ctx.author
                    )
            player.maybe_shuffle(0 if empty_queue else 1)

            if len(tracks) > track_len:
                maxlength_msg = _(" {bad_tracks} tracks cannot be queued.").format(
                    bad_tracks=(len(tracks) - track_len)
                )
            else:
                maxlength_msg = ""
            playlist_name = escape(
                playlist_data.name if playlist_data else _("No Title"), formatting=True
            )
            embed = discord.Embed(
                description=bold(f"[{playlist_name}]({playlist_url})")
                if playlist_url
                else playlist_name,
                title=_("Playlist Enqueued"),
            )
            embed.set_footer(
                text=_("Added {num} tracks to the queue.{maxlength_msg}").format(
                    num=track_len, maxlength_msg=maxlength_msg
                )
            )
            if not guild_data["shuffle"] and queue_dur > 0:
                embed.set_footer(
                    text=_(
                        "{time} until start of playlist playback: starts at #{position} in queue"
                    ).format(time=queue_total_duration, position=before_queue_length + 1)
                )
            if not player.current:
                await player.play()
            self.update_player_lock(ctx, False)
            message = await self.send_embed_msg(ctx, embed=embed)
            return tracks or message
        else:
            single_track = None
            # a ytsearch: prefixed item where we only need the first Track returned
            # this is in the case of [p]play <query>, a single Spotify url/code
            # or this is a localtrack item
            try:
                if len(player.queue) >= 10000:
                    return await self.send_embed_msg(ctx, title=_("Queue size limit reached."))

                single_track = (
                    tracks
                    if isinstance(tracks, lavalink.rest_api.Track)
                    else tracks[index]
                    if index
                    else tracks[0]
                )
                if seek and seek > 0:
                    single_track.start_timestamp = seek * 1000
                query = Query.process_input(single_track, self.local_folder_current_path)
                if not await self.is_query_allowed(
                    self.config,
                    ctx,
                    (
                        f"{single_track.title} {single_track.author} {single_track.uri} "
                        f"{str(query)}"
                    ),
                    query_obj=query,
                ):
                    if IS_DEBUG:
                        log.debug(f"Query is not allowed in {ctx.guild} ({ctx.guild.id})")
                    self.update_player_lock(ctx, False)
                    return await self.send_embed_msg(
                        ctx, title=_("This track is not allowed in this server.")
                    )
                elif guild_data["maxlength"] > 0:
                    if self.is_track_length_allowed(single_track, guild_data["maxlength"]):
                        single_track.extras.update(
                            {
                                "enqueue_time": int(time.time()),
                                "vc": player.channel.id,
                                "requester": ctx.author.id,
                            }
                        )
                        player.add(ctx.author, single_track)
                        player.maybe_shuffle()
                        self.bot.dispatch(
                            "red_audio_track_enqueue",
                            player.channel.guild,
                            single_track,
                            ctx.author,
                        )
                    else:
                        self.update_player_lock(ctx, False)
                        return await self.send_embed_msg(
                            ctx, title=_("Track exceeds maximum length.")
                        )

                else:
                    single_track.extras.update(
                        {
                            "enqueue_time": int(time.time()),
                            "vc": player.channel.id,
                            "requester": ctx.author.id,
                        }
                    )
                    player.add(ctx.author, single_track)
                    player.maybe_shuffle()
                    self.bot.dispatch(
                        "red_audio_track_enqueue", player.channel.guild, single_track, ctx.author
                    )
            except IndexError:
                self.update_player_lock(ctx, False)
                title = _("Nothing found")
                desc = EmptyEmbed
                if await self.bot.is_owner(ctx.author):
                    desc = _("Please check your console or logs for details.")
                return await self.send_embed_msg(ctx, title=title, description=desc)
            except Exception as e:
                self.update_player_lock(ctx, False)
                raise e
            description = await self.get_track_description(
                single_track, self.local_folder_current_path
            )
            embed = discord.Embed(title=_("Track Enqueued"), description=description)
            if not guild_data["shuffle"] and queue_dur > 0:
                embed.set_footer(
                    text=_("{time} until track playback: #{position} in queue").format(
                        time=queue_total_duration, position=before_queue_length + 1
                    )
                )

        if not player.current:
            await player.play()
        self.update_player_lock(ctx, False)
        message = await self.send_embed_msg(ctx, embed=embed)
        return single_track or message