Amber/audio.py

152 lines
5.2 KiB
Python
Raw Permalink Normal View History

2025-01-18 21:45:25 -05:00
import discord
import yt_dlp
import asyncio
2025-01-18 21:45:25 -05:00
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%)
2025-01-18 21:45:25 -05:00
async def play_audio(interaction: discord.Interaction, query: str):
guild_id = interaction.guild.id
2025-01-18 21:45:25 -05:00
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]
2025-01-18 21:45:25 -05:00
if not voice_client.is_connected():
await interaction.response.send_message("Amber is not in a voice channel.")
return
await interaction.response.defer()
2025-01-18 21:45:25 -05:00
# Search for the song on YouTube
2025-01-18 21:45:25 -05:00
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']
2025-01-18 21:45:25 -05:00
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
2025-01-18 21:45:25 -05:00
ffmpeg_options = {
'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
2025-01-18 21:45:25 -05:00
'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.**")