From 215fad0471ba7d59ac77597b739f3d1a990c1e51 Mon Sep 17 00:00:00 2001 From: Dan Date: Sat, 18 Jan 2025 21:45:25 -0500 Subject: [PATCH] Added Music Support, albeit basic. --- audio.py | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++ commands.py | 20 +++++++++++++++ main.py | 35 +++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 audio.py create mode 100644 commands.py create mode 100644 main.py diff --git a/audio.py b/audio.py new file mode 100644 index 0000000..fab900a --- /dev/null +++ b/audio.py @@ -0,0 +1,70 @@ +import discord +import yt_dlp + +voice_clients = {} # Track active voice connections + + +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 must be in a voice channel to use this command.", ephemeral=True) + return + + channel = interaction.user.voice.channel + if interaction.guild.id in voice_clients: + await interaction.response.send_message("Amber is already in a voice channel.") + else: + voice_client = await channel.connect() + voice_clients[interaction.guild.id] = voice_client + await interaction.response.send_message(f"Amber joined {channel.name}!") + + +async def leave_voice(interaction: discord.Interaction): + 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] + await voice_client.disconnect() + voice_clients.pop(guild_id, None) + await interaction.response.send_message("Amber has left the voice channel.") + + +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() # Indicate the bot is processing the request + + # yt-dlp options + ydl_opts = { + 'format': 'bestaudio/best', + 'quiet': True, + } + + # Search for the query on YouTube + 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 + + # Extract the audio URL and metadata + url2 = info['url'] + title = info.get('title', 'Unknown Title') + + # Stop any existing audio and play the new one + voice_client.stop() + ffmpeg_options = { + 'options': '-vn', + } + voice_client.play(discord.FFmpegPCMAudio(url2, **ffmpeg_options)) + await interaction.followup.send(f"Now playing: {title}") diff --git a/commands.py b/commands.py new file mode 100644 index 0000000..09084b5 --- /dev/null +++ b/commands.py @@ -0,0 +1,20 @@ +import discord +from discord import app_commands +from audio import join_voice, leave_voice, play_audio + + +async def setup_commands(client): + @client.tree.command(name="join", description="Amber joins the voice channel you're in.") + async def join(interaction: discord.Interaction): + await join_voice(interaction) + + @client.tree.command(name="leave", description="Amber leaves the current voice channel.") + async def leave(interaction: discord.Interaction): + await leave_voice(interaction) + + @client.tree.command(name="play", description="Search and play a song by name or YouTube URL.") + @app_commands.describe(query="The name or YouTube URL of the song.") + async def play(interaction: discord.Interaction, query: str): + await play_audio(interaction, query) + + await client.tree.sync() diff --git a/main.py b/main.py new file mode 100644 index 0000000..6ef389b --- /dev/null +++ b/main.py @@ -0,0 +1,35 @@ +import discord +from discord.ext import commands +from commands import setup_commands +from dotenv import load_dotenv +import os + +load_dotenv() + +intents = discord.Intents.default() +intents.messages = True +intents.message_content = True +intents.guilds = True +intents.voice_states = True + + +class AmberClient(discord.Client): + def __init__(self): + super().__init__(intents=intents) + self.tree = discord.app_commands.CommandTree(self) + + async def setup_hook(self): + # Register commands + await setup_commands(self) + + async def on_ready(self): + print(f"Amber is online as {self.user}") + + +# Initialize the bot +client = AmberClient() + + +# Run the bot +TOKEN = os.getenv("DISCORD_TOKEN") +client.run(TOKEN)