Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| import discord | |
| from discord.ext import commands | |
| from huggingface_hub import hf_hub_download | |
| import gradio as gr | |
| from dotenv import load_dotenv | |
| import os | |
| import threading | |
| import asyncio | |
| # Load environment variables | |
| load_dotenv() | |
| if os.path.exists("assets") is False: | |
| os.makedirs("assets", exist_ok=True) | |
| hf_hub_download( | |
| "not-lain/assets", "lofi.mp3", repo_type="dataset", local_dir="assets" | |
| ) | |
| song = "assets/lofi.mp3" | |
| # 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.keepalive_task = None | |
| self.last_context = None | |
| async def voice_keepalive(self, voice_client): | |
| """Keeps the voice connection alive by periodically playing audio""" | |
| print("Starting voice keepalive task") | |
| while True: | |
| if voice_client.is_connected() and not self.is_playing: | |
| await self.play_next(self.last_context) | |
| await asyncio.sleep(15) | |
| else: | |
| await asyncio.sleep(1) | |
| 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() | |
| self.last_context = ctx | |
| if self.keepalive_task: | |
| self.keepalive_task.cancel() | |
| self.keepalive_task = asyncio.create_task( | |
| self.voice_keepalive(self.voice_client) | |
| ) | |
| else: | |
| await self.voice_client.move_to(channel) | |
| else: | |
| await ctx.send("You need to be in a voice channel!") | |
| async def play_next(self, ctx): | |
| if not self.is_playing: | |
| self.is_playing = True | |
| try: | |
| audio_source = discord.FFmpegPCMAudio(song) | |
| def after_playing(e): | |
| self.is_playing = False | |
| self.voice_client.play(audio_source, after=after_playing) | |
| except Exception as e: | |
| print(f"Error playing file: {e}") | |
| await ctx.send("Error playing the song.") | |
| self.is_playing = False | |
| async def stop_playing(self, ctx): | |
| try: | |
| if self.keepalive_task: | |
| self.keepalive_task.cancel() | |
| self.keepalive_task = None | |
| if self.voice_client: | |
| if self.voice_client.is_playing(): | |
| self.voice_client.stop() | |
| self.is_playing = False | |
| self.last_context = None | |
| if self.voice_client.is_connected(): | |
| await self.voice_client.disconnect(force=False) | |
| self.voice_client = None | |
| return True | |
| return False | |
| except Exception as e: | |
| print(f"Error during cleanup: {e}") | |
| self.is_playing = False | |
| self.voice_client = None | |
| self.last_context = None | |
| self.keepalive_task = None | |
| return False | |
| music_bot = MusicBot() | |
| 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}") | |
| async def play(interaction: discord.Interaction): | |
| await interaction.response.defer() | |
| ctx = await bot.get_context(interaction) | |
| await music_bot.join_voice(ctx) | |
| if not music_bot.is_playing: | |
| await music_bot.play_next(ctx) | |
| await interaction.followup.send("Playing sample music!") | |
| else: | |
| await interaction.followup.send("Already playing!") | |
| async def skip(interaction: discord.Interaction): | |
| # Check if user is in a voice channel | |
| if not interaction.user.voice: | |
| await interaction.response.send_message( | |
| "You must be in a voice channel to use this command!" | |
| ) | |
| return | |
| # Check if bot is in a voice channel | |
| if not music_bot.voice_client: | |
| await interaction.response.send_message("No song is currently playing!") | |
| return | |
| # Check if user is in the same channel as the bot | |
| if interaction.user.voice.channel != music_bot.voice_client.channel: | |
| await interaction.response.send_message( | |
| "You must be in the same voice channel as the bot!" | |
| ) | |
| return | |
| if music_bot.voice_client and music_bot.is_playing: | |
| music_bot.is_playing = False # Reset playing state | |
| music_bot.voice_client.stop() | |
| await interaction.response.send_message("Skipped current song!") | |
| else: | |
| await interaction.response.send_message("No song is currently playing!") | |
| async def leave(interaction: discord.Interaction): | |
| # Check if user is in a voice channel | |
| if not interaction.user.voice: | |
| await interaction.response.send_message( | |
| "You must be in a voice channel to use this command!" | |
| ) | |
| return | |
| # Check if bot is in a voice channel | |
| if not music_bot.voice_client: | |
| await interaction.response.send_message("I'm not in any voice channel!") | |
| return | |
| # Check if user is in the same channel as the bot | |
| if interaction.user.voice.channel != music_bot.voice_client.channel: | |
| await interaction.response.send_message( | |
| "You must be in the same voice channel as the bot!" | |
| ) | |
| return | |
| await interaction.response.defer() | |
| ctx = await bot.get_context(interaction) | |
| try: | |
| success = await music_bot.stop_playing(ctx) | |
| if success: | |
| await interaction.followup.send("Successfully disconnected! 👋") | |
| else: | |
| await interaction.followup.send( | |
| "Failed to disconnect properly. Please try again." | |
| ) | |
| except Exception as e: | |
| print(f"Error during leave command: {e}") | |
| await interaction.followup.send("An error occurred while trying to disconnect.") | |
| 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) | |