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()
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('👍')
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)
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')
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