예제 #1
0
    async def on_track_end(self, node, payload):
        if payload.reason == 'REPLACED':
            return

        player = payload.player
        playlist = self.bot.playlists[player.guild_id]

        playlist.add_to_history([playlist.current_song])
        previous_song = playlist.current_song

        playlist.old_progress_bar = ''
        if playlist.progress_bar_task:
            playlist.progress_bar_task.cancel()

        if payload.reason == 'FINISHED':
            # put the progress bar at the end and wait 2 seconds before the next song plays so it looks nicer
            formatted_duration_length = len(format_time.ms(previous_song.duration, accuracy=3).split(' '))
            formatted_position = format_time.ms(previous_song.duration, accuracy=3, progress_bar=formatted_duration_length)

            line_str = '■' * 25
            progress_bar_str = f'`{formatted_position} [{line_str}] {formatted_position}`'

            await playlist.update_music_menu(current_progress=progress_bar_str)
            await asyncio.sleep(2)

        playlist.current_song = None
        return await playlist.next()
예제 #2
0
    async def seek(self, ctx, *, new_position=None):
        if new_position is None:
            return await embed_maker.command_error(ctx)

        playlist = self.bot.playlists[ctx.guild.id]
        player = playlist.wavelink_client.get_player(ctx.guild.id)

        if not playlist.current_song:
            return await embed_maker.message(ctx, 'Nothing is playing currently', colour='red')

        if await self.check_voice(ctx):
            return

        correct_format = re.findall(r'((?:\d+h)? ?(?:\d+m)? ?(?:\d+s)?)', new_position)
        if not correct_format:
            return await embed_maker.message(ctx, 'Invalid timestamp format', colour='red')

        new_position = format_time.to_ms(timestamp=correct_format[0])
        duration = playlist.current_song.duration

        if new_position > duration:
            return await embed_maker.message(ctx, 'timestamp further than duration of song', colour='red')

        await player.seek(new_position)

        formatted_duration_length = len(format_time.ms(duration, accuracy=3).split(' '))
        formatted_duration = format_time.ms(duration, accuracy=3, progress_bar=formatted_duration_length)

        # update progress bar
        part_duration = duration // 25
        equal_segments = [range(i * part_duration, (i + 1) * part_duration) for i in range(25)]

        player = playlist.wavelink_client.get_player(ctx.guild.id)

        current_position = 5000 * round(player.position / 5000)

        pos_range = [r for r in equal_segments if current_position in r]
        if not pos_range:
            return

        position_index = equal_segments.index(pos_range[0])
        formatted_position = format_time.ms(current_position, accuracy=3, progress_bar=formatted_duration_length)

        line_str = '■' * position_index + '—' * (25 - position_index)
        progress_bar_str = f'`{formatted_position} [{line_str}] {formatted_duration}`'

        await playlist.update_music_menu(current_progress=progress_bar_str)

        return await ctx.message.add_reaction('👍')
예제 #3
0
    async def progress_bar(self, duration):
        self.old_progress_bar = ''
        current_position = 0
        formatted_duration_length = len(format_time.ms(duration, accuracy=3).split(' '))
        formatted_duration = format_time.ms(duration, accuracy=3, progress_bar=formatted_duration_length)

        parts = 25
        part_duration = duration // parts
        equal_segments = [range(i * part_duration, (i + 1) * part_duration) for i in range(parts)]

        player = self.wavelink_client.get_player(self.guild.id)

        while current_position < duration:
            if player.is_paused:
                await asyncio.sleep(5)
                continue

            current_position = 5000 * round(player.position / 5000)

            pos_range = [r for r in equal_segments if current_position in r]
            if not pos_range:
                return

            position_index = equal_segments.index(pos_range[0])
            formatted_position = format_time.ms(current_position, accuracy=3, progress_bar=formatted_duration_length)

            line_str = '■' * position_index + '—' * (parts - position_index)
            progress_bar_str = f'`{formatted_position} [{line_str}] {formatted_duration}`'

            if self.old_progress_bar == progress_bar_str:
                await asyncio.sleep(5)
                continue

            self.old_progress_bar = progress_bar_str

            await self.update_music_menu(current_progress=progress_bar_str)
            await asyncio.sleep(5)
예제 #4
0
    async def search(self, ctx, *, query=None):
        if query is None:
            return await embed_maker.command_error(ctx)

        playlist = self.bot.playlists[ctx.guild.id]
        player = playlist.wavelink_client.get_player(ctx.guild.id)

        if not player.is_connected:
            _, error = await ctx.invoke(self.join)
            if error:
                return

        wavelink_client = playlist.wavelink_client
        results = await wavelink_client.get_tracks(f'ytsearch:{query}', retry_on_failure=True)

        if not results:
            return await embed_maker.message(ctx, f"Couldn't find any matches for: {query}")

        search_str = ""
        for i, song in enumerate(results[:10]):
            formatted_duration = format_time.ms(song.duration, accuracy=3)
            search_str += f'`#{i + 1}` [{song.title}](http://y2u.be/{song.ytid}) - `{formatted_duration}`\n\n'

        search_str += '**Pick a song by typing its number.** Type cancel to exit.'
        search_msg = await embed_maker.message(ctx, search_str, nonce=10)

        def check(m):
            return m.channel.id == ctx.channel.id and m.author.id == ctx.author.id

        try:
            msg = await self.bot.wait_for('message', check=check)
            content = msg.content
            if not content.isdigit() or int(content) < 1 or int(content) > 10:
                return await embed_maker.message(ctx, 'Invalid number', colour='red')

            song = results[int(content) - 1]
            await playlist.add(song, ctx.author.id)
            await search_msg.delete()
            await msg.delete()
        except asyncio.TimeoutError:
            await search_msg.delete()
            return await embed_maker.message(ctx, 'Search timeout.', colour='red')
예제 #5
0
    async def update_music_menu(self, page=0, current_progress=''):
        if not self.music_menu:
            return

        player = self.wavelink_client.get_player(self.guild.id)

        if not page and not self.music_menu_page:
            page = 1
        elif not page and self.music_menu_page:
            page = self.music_menu_page

        self.music_menu_page = page

        music_menu_str = '**Currently Playing:**\n'

        if not current_progress:
            current_progress = self.old_progress_bar

        if self.current_song:
            if not self.current_song.custom_title:
                result = get_artist_title(self.current_song.title)
                if result:
                    title = f'{result[0]} - {result[1]}'
                else:
                    title = self.current_song.title
            else:
                title = self.current_song.title

            song_type = self.current_song.type
            currently_playing_str = f'**{song_type}:** ' if song_type != 'Youtube' else ''
            currently_playing_str += f'[{title}]({self.current_song.uri})'

            if song_type != 'Twitch':
                formatted_duration = format_time.ms(self.current_song.duration, accuracy=3)
                currently_playing_str += f' | `{formatted_duration}`'

            user = self.bot.get_user(self.current_song.requester)
            if not user:
                try:
                    user = await self.bot.fetch_user(self.current_song.requester)
                except:
                    pass

            if user:
                name = user.display_name if len(user.display_name) <= 13 else f'{user.display_name[:13]}...'
                currently_playing_str += f' - *{name}*'

            if song_type != 'Twitch':
                if not current_progress:
                    if self.progress_bar_task:
                        self.progress_bar_task.cancel()
                    self.progress_bar_task = asyncio.create_task(self.progress_bar(self.current_song.duration))
                    return
                else:
                    currently_playing_str += f'\n{current_progress}'

            music_menu_str += f'{currently_playing_str}\n\n'
        else:
            music_menu_str += '\n'

        music_menu_str += '**Queue:**\n'

        queue_str = []
        for i, song in enumerate(self.queue[10 * (page - 1):10 * page]):
            if not song.custom_title:
                result = get_artist_title(song.title)
                if result:
                    title = f'{result[0]} - {result[1]}'
                else:
                    title = song.title
            else:
                title = song.title

            value = f'`#{(i + 1) + 10 * (page - 1)}` - '
            value += f'**{song.type}:** ' if song.type != 'Youtube' else ''
            value += f'[{title}]({song.uri})'

            if song.type != 'Twitch':
                formatted_duration = format_time.ms(song.duration, accuracy=3)
                value += f' | `{formatted_duration}`'

            user = self.bot.get_user(self.current_song.requester)
            if not user:
                try:
                    user = await self.bot.fetch_user(self.current_song.requester)
                except:
                    pass

            if user:
                name = user.display_name if len(user.display_name) <= 13 else f'{user.display_name[:13]}...'
                value += f' - *{name}*'

            queue_str.append(value)

        music_menu_str += '\n'.join(queue_str) if queue_str else '\u200b'

        total_duration = sum([s.duration for s in self.queue])

        total_duration_formatted = format_time.ms(total_duration, accuracy=4)
        if self.current_song and self.current_song.type == 'Twitch':
            total_duration_formatted = '∞'

        music_menu_str += f'\n\nSongs in queue: **{len(self)}**\nPlaylist duration: **{total_duration_formatted}**\nLoop: **{self.loop}**'

        page_count = math.ceil(len(self) / 10)
        if page_count == 0:
            page_count = 1

        author_name = 'Playlist' + (' - Paused' if player.is_paused or not player.is_connected else '')

        new_embed = self.music_menu.embeds[0]
        new_embed.set_author(name=author_name, icon_url=self.guild.icon_url)
        new_embed.description = music_menu_str
        new_embed.set_footer(text=f'Page {page}/{page_count}')
        await self.music_menu.edit(embed=new_embed)
        return True