import discord import yt_dlp import asyncio voice_clients = {} # Track active voice connections music_queues = {} # Per-guild song queue current_tracks = {} # Currently playing tracks volumes = {} # Volume levels per guild default_volume = 0.5 # Default volume (50%) async def play_audio(interaction: discord.Interaction, query: str): guild_id = interaction.guild.id if guild_id not in voice_clients: await interaction.response.send_message("Amber is not connected to a voice channel.") return voice_client = voice_clients[guild_id] if not voice_client.is_connected(): await interaction.response.send_message("Amber is not in a voice channel.") return await interaction.response.defer() # Search for the song on YouTube ydl_opts = { 'format': 'bestaudio/best', 'quiet': True, } with yt_dlp.YoutubeDL(ydl_opts) as ydl: try: info = ydl.extract_info(f"ytsearch:{query}", download=False)['entries'][0] except Exception as e: await interaction.followup.send(f"Failed to find or play the requested audio. Error: {str(e)}") return song_url = info['url'] title = info.get('title', 'Unknown Title') # Add the song to the queue if guild_id not in music_queues: music_queues[guild_id] = [] music_queues[guild_id].append((song_url, title)) await interaction.followup.send(f"✅ **Added to queue:** {title}") # If nothing is playing, start playback if not voice_client.is_playing(): await play_next(interaction) async def play_next(interaction: discord.Interaction): guild_id = interaction.guild.id if guild_id not in music_queues or not music_queues[guild_id]: await interaction.followup.send("❌ **No songs in the queue.**") return voice_client = voice_clients[guild_id] song_url, title = music_queues[guild_id].pop(0) current_tracks[guild_id] = title # Prepare FFmpeg options ffmpeg_options = { 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn', } try: source = discord.FFmpegPCMAudio(song_url, **ffmpeg_options) volume = volumes.get(guild_id, default_volume) source = discord.PCMVolumeTransformer(source, volume=volume) # Play the audio voice_client.play( source, after=lambda e: asyncio.run_coroutine_threadsafe( play_next(interaction), interaction.client.loop ), ) await interaction.followup.send(f"🎵 **Now playing:** {title}") except Exception as e: await interaction.followup.send(f"Failed to play the next song. Error: {str(e)}") async def stop_audio(interaction: discord.Interaction): guild_id = interaction.guild.id if guild_id in voice_clients: voice_client = voice_clients[guild_id] if voice_client.is_playing(): voice_client.stop() music_queues[guild_id] = [] # Clear the queue current_tracks.pop(guild_id, None) # Remove the current track await interaction.response.send_message("🛑 **Playback stopped and queue cleared.**") else: await interaction.response.send_message("❌ **No music is playing.**") async def set_volume(interaction: discord.Interaction, level: int): guild_id = interaction.guild.id if level < 0 or level > 100: await interaction.response.send_message("❌ **Volume must be between 0 and 100.**") return # Set the volume volume = level / 100 volumes[guild_id] = volume # Adjust volume for the current source if playing if guild_id in voice_clients and voice_clients[guild_id].is_playing(): source = voice_clients[guild_id].source if isinstance(source, discord.PCMVolumeTransformer): source.volume = volume await interaction.response.send_message(f"🔊 **Volume set to {level}%**.") async def join_voice(interaction: discord.Interaction): if interaction.user.voice is None or interaction.user.voice.channel is None: await interaction.response.send_message("You need to be in a voice channel for me to join.") return channel = interaction.user.voice.channel guild_id = interaction.guild.id # Connect to the voice channel if guild_id not in voice_clients: voice_clients[guild_id] = await channel.connect() await interaction.response.send_message(f"✅ **Joined {channel.name}.**") else: await interaction.response.send_message("❌ **I am already in a voice channel.**") async def leave_voice(interaction: discord.Interaction): guild_id = interaction.guild.id if guild_id in voice_clients: voice_client = voice_clients[guild_id] if voice_client.is_connected(): await voice_client.disconnect() voice_clients.pop(guild_id, None) await interaction.response.send_message("👋 **Left the voice channel.**") else: await interaction.response.send_message("❌ **I am not connected to any voice channel.**") else: await interaction.response.send_message("❌ **I am not connected to any voice channel.**")