music-bot / app.py
not-lain's picture
update cookies
f9c3f45
raw
history blame
5.45 kB
import discord
from discord.ext import commands
import gradio as gr
from dotenv import load_dotenv
import os
import threading
import asyncio
import yt_dlp
# Load environment variables
load_dotenv()
# Check if cookies.txt exists
if not os.path.exists('cookies.txt'):
txt = os.getenv('COOKIES')
with open('cookies.txt', 'w') as f:
f.write(txt)
# Bot configuration
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='!', intents=intents)
class MusicBot:
def __init__(self):
self.is_playing = False
self.voice_client = None
self.queue = []
self.ydl_opts = {
'format': 'bestaudio/best',
'cookiefile': 'cookies.txt',
'cookies': 'cookies.txt',
'quiet': True,
'no_warnings': True,
'extract_flat': 'in_playlist'
}
async def join_voice(self, ctx):
if ctx.author.voice:
channel = ctx.author.voice.channel
if self.voice_client is None:
self.voice_client = await channel.connect()
else:
await self.voice_client.move_to(channel)
return True
return False
async def play_next(self, ctx):
if self.queue and not self.is_playing:
self.is_playing = True
url = self.queue.pop(0)
try:
with yt_dlp.YoutubeDL(self.ydl_opts) as ydl:
info = ydl.extract_info(url, download=False)
audio_url = info['url']
title = info.get('title', 'Unknown title')
# Create FFmpeg audio source
ffmpeg_options = {
'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
'options': '-vn -bufsize 64k'
}
audio_source = discord.FFmpegPCMAudio(audio_url, **ffmpeg_options)
def after_playing(error):
self.is_playing = False
if error:
print(f"Playback error: {error}")
asyncio.run_coroutine_threadsafe(self.play_next(ctx), bot.loop)
# Apply volume transformation and play
transformed_source = discord.PCMVolumeTransformer(audio_source, volume=0.5)
self.voice_client.play(transformed_source, after=after_playing)
await ctx.send(f"Now playing: {title}")
except Exception as e:
print(f"Error playing URL {url}: {e}")
self.is_playing = False
await ctx.send(f"Error playing the song: {str(e)}")
await self.play_next(ctx)
music_bot = MusicBot()
@bot.event
async def on_ready():
print(f'Bot is ready! Logged in as {bot.user}')
print("Syncing commands...")
try:
await bot.tree.sync(guild=None) # Set to None for global sync
print("Successfully synced commands globally!")
except discord.app_commands.errors.CommandSyncFailure as e:
print(f"Failed to sync commands: {e}")
except Exception as e:
print(f"An error occurred while syncing commands: {e}")
@bot.tree.command(name="play", description="Play a YouTube URL")
async def play(interaction: discord.Interaction, url: str):
await interaction.response.defer()
ctx = await commands.Context.from_interaction(interaction)
if not await music_bot.join_voice(ctx):
await interaction.followup.send("You need to be in a voice channel!")
return
try:
with yt_dlp.YoutubeDL(music_bot.ydl_opts) as ydl:
info = ydl.extract_info(url, download=False)
title = info.get('title', 'Unknown title')
music_bot.queue.append(url)
await interaction.followup.send(f'Added to queue: {title}')
if not music_bot.is_playing:
await music_bot.play_next(ctx)
except Exception as e:
await interaction.followup.send(f'Error: {str(e)}')
@bot.tree.command(name="skip", description="Skip the current song")
async def skip(interaction: discord.Interaction):
if music_bot.voice_client:
music_bot.voice_client.stop()
await interaction.response.send_message('Skipped current song!')
else:
await interaction.response.send_message('No song is currently playing!')
@bot.tree.command(name="leave", description="Disconnect bot from voice channel")
async def leave(interaction: discord.Interaction):
if music_bot.voice_client:
await music_bot.voice_client.disconnect()
music_bot.voice_client = None
music_bot.queue = []
music_bot.is_playing = False
await interaction.response.send_message('Bot disconnected!')
else:
await interaction.response.send_message('Bot is not in a voice channel!')
def run_discord_bot():
bot.run(os.getenv('DISCORD_TOKEN'))
# Create the Gradio interface
with gr.Blocks() as iface:
gr.Markdown("# Discord Music Bot Control Panel")
gr.Markdown("Bot is running in background")
if __name__ == "__main__":
# Start the Discord bot in a separate thread
bot_thread = threading.Thread(target=run_discord_bot, daemon=True)
bot_thread.start()
# Run Gradio interface in the main thread
iface.launch(debug=True)