""" Example usage of Pomice's new advanced features. This example demonstrates: - Track History - Queue Statistics - Playlist Export/Import - Track Filtering and Search """ import asyncio import discord from discord.ext import commands import pomice # Initialize bot bot = commands.Bot(command_prefix='!', intents=discord.Intents.all()) class AdvancedMusic(commands.Cog): """Music cog with advanced features.""" def __init__(self, bot): self.bot = bot self.pomice = pomice.NodePool() # Track history for each guild self.track_histories = {} async def start_nodes(self): """Start Lavalink nodes.""" await self.pomice.create_node( bot=self.bot, host='127.0.0.1', port='3030', password='youshallnotpass', identifier='MAIN' ) @commands.Cog.listener() async def on_pomice_track_end(self, player, track, _): """Add track to history when it ends.""" if player.guild.id not in self.track_histories: self.track_histories[player.guild.id] = pomice.TrackHistory(max_size=100) self.track_histories[player.guild.id].add(track) @commands.command(name='play') async def play(self, ctx, *, search: str): """Play a track.""" if not ctx.voice_client: await ctx.author.voice.channel.connect(cls=pomice.Player) player = ctx.voice_client results = await player.get_tracks(query=search, ctx=ctx) if not results: return await ctx.send('No results found.') if isinstance(results, pomice.Playlist): await player.queue.put(results.tracks) await ctx.send(f'Added playlist **{results.name}** with {len(results.tracks)} tracks.') else: track = results[0] await player.queue.put(track) await ctx.send(f'Added **{track.title}** to queue.') if not player.is_playing: await player.do_next() @commands.command(name='history') async def history(self, ctx, limit: int = 10): """Show recently played tracks.""" if ctx.guild.id not in self.track_histories: return await ctx.send('No history available.') history = self.track_histories[ctx.guild.id] if history.is_empty: return await ctx.send('No tracks in history.') tracks = history.get_last(limit) embed = discord.Embed( title='🎵 Recently Played', color=discord.Color.blue() ) for i, track in enumerate(tracks, 1): embed.add_field( name=f'{i}. {track.title}', value=f'by {track.author}', inline=False ) await ctx.send(embed=embed) @commands.command(name='stats') async def queue_stats(self, ctx): """Show detailed queue statistics.""" if not ctx.voice_client: return await ctx.send('Not connected to voice.') player = ctx.voice_client stats = pomice.QueueStats(player.queue) summary = stats.get_summary() embed = discord.Embed( title='📊 Queue Statistics', color=discord.Color.green() ) embed.add_field( name='Total Tracks', value=summary['total_tracks'], inline=True ) embed.add_field( name='Total Duration', value=summary['total_duration_formatted'], inline=True ) embed.add_field( name='Average Duration', value=summary['average_duration_formatted'], inline=True ) if summary['longest_track']: embed.add_field( name='Longest Track', value=f"{summary['longest_track'].title} ({stats.format_duration(summary['longest_track'].length)})", inline=False ) # Duration breakdown breakdown = summary['duration_breakdown'] embed.add_field( name='Duration Breakdown', value=f"Short (<3min): {breakdown['short']}\n" f"Medium (3-6min): {breakdown['medium']}\n" f"Long (6-10min): {breakdown['long']}\n" f"Very Long (>10min): {breakdown['very_long']}", inline=False ) # Top requesters top_requesters = stats.get_top_requesters(3) if top_requesters: requesters_text = '\n'.join( f'{i}. {req.display_name}: {count} tracks' for i, (req, count) in enumerate(top_requesters, 1) ) embed.add_field( name='Top Requesters', value=requesters_text, inline=False ) await ctx.send(embed=embed) @commands.command(name='export') async def export_queue(self, ctx, filename: str = 'playlist.json'): """Export current queue to a file.""" if not ctx.voice_client: return await ctx.send('Not connected to voice.') player = ctx.voice_client if player.queue.is_empty: return await ctx.send('Queue is empty.') try: pomice.PlaylistManager.export_queue( player.queue, f'playlists/{filename}', name=f"{ctx.guild.name}'s Playlist", description=f'Exported from {ctx.guild.name}' ) await ctx.send(f'✅ Queue exported to `playlists/{filename}`') except Exception as e: await ctx.send(f'❌ Error exporting queue: {e}') @commands.command(name='import') async def import_playlist(self, ctx, filename: str): """Import a playlist from a file.""" if not ctx.voice_client: await ctx.author.voice.channel.connect(cls=pomice.Player) player = ctx.voice_client try: data = pomice.PlaylistManager.import_playlist(f'playlists/{filename}') # Get URIs and search for tracks uris = [track['uri'] for track in data['tracks'] if track.get('uri')] added = 0 for uri in uris: try: results = await player.get_tracks(query=uri, ctx=ctx) if results: if isinstance(results, pomice.Playlist): await player.queue.put(results.tracks) added += len(results.tracks) else: await player.queue.put(results[0]) added += 1 except: continue await ctx.send(f'✅ Imported {added} tracks from `{data["name"]}`') if not player.is_playing: await player.do_next() except FileNotFoundError: await ctx.send(f'❌ Playlist file `{filename}` not found.') except Exception as e: await ctx.send(f'❌ Error importing playlist: {e}') @commands.command(name='filter') async def filter_queue(self, ctx, filter_type: str, *, value: str): """Filter queue by various criteria. Examples: !filter author Imagine Dragons !filter duration 180000-300000 (3-5 minutes in ms) !filter title Thunder """ if not ctx.voice_client: return await ctx.send('Not connected to voice.') player = ctx.voice_client queue_tracks = list(player.queue) if filter_type == 'author': filtered = pomice.TrackFilter.by_author(queue_tracks, value) elif filter_type == 'title': filtered = pomice.TrackFilter.by_title(queue_tracks, value) elif filter_type == 'duration': # Parse duration range (e.g., "180000-300000") if '-' in value: min_dur, max_dur = map(int, value.split('-')) filtered = pomice.TrackFilter.by_duration( queue_tracks, min_duration=min_dur, max_duration=max_dur ) else: return await ctx.send('Duration format: min-max (in milliseconds)') else: return await ctx.send('Valid filters: author, title, duration') if not filtered: return await ctx.send('No tracks match the filter.') embed = discord.Embed( title=f'🔍 Filtered Results ({len(filtered)} tracks)', color=discord.Color.purple() ) for i, track in enumerate(filtered[:10], 1): stats = pomice.QueueStats(player.queue) embed.add_field( name=f'{i}. {track.title}', value=f'by {track.author} - {stats.format_duration(track.length)}', inline=False ) if len(filtered) > 10: embed.set_footer(text=f'Showing 10 of {len(filtered)} results') await ctx.send(embed=embed) @commands.command(name='search_history') async def search_history(self, ctx, *, query: str): """Search through play history.""" if ctx.guild.id not in self.track_histories: return await ctx.send('No history available.') history = self.track_histories[ctx.guild.id] results = history.search(query) if not results: return await ctx.send(f'No tracks found matching "{query}"') embed = discord.Embed( title=f'🔍 History Search: "{query}"', description=f'Found {len(results)} tracks', color=discord.Color.gold() ) for i, track in enumerate(results[:10], 1): embed.add_field( name=f'{i}. {track.title}', value=f'by {track.author}', inline=False ) if len(results) > 10: embed.set_footer(text=f'Showing 10 of {len(results)} results') await ctx.send(embed=embed) @commands.command(name='sort') async def sort_queue(self, ctx, sort_by: str = 'duration'): """Sort the queue. Options: duration, title, author """ if not ctx.voice_client: return await ctx.send('Not connected to voice.') player = ctx.voice_client if player.queue.is_empty: return await ctx.send('Queue is empty.') queue_tracks = list(player.queue) if sort_by == 'duration': sorted_tracks = pomice.SearchHelper.sort_by_duration(queue_tracks) elif sort_by == 'title': sorted_tracks = pomice.SearchHelper.sort_by_title(queue_tracks) elif sort_by == 'author': sorted_tracks = pomice.SearchHelper.sort_by_author(queue_tracks) else: return await ctx.send('Valid options: duration, title, author') # Clear and refill queue player.queue._queue.clear() for track in sorted_tracks: await player.queue.put(track) await ctx.send(f'✅ Queue sorted by {sort_by}') @bot.event async def on_ready(): print(f'{bot.user} is ready!') await bot.get_cog('AdvancedMusic').start_nodes() # Add cog bot.add_cog(AdvancedMusic(bot)) # Run bot bot.run('YOUR_BOT_TOKEN')