not-lain commited on
Commit
f6dc26b
·
verified ·
1 Parent(s): c8aea3c
Files changed (1) hide show
  1. app.py +14 -86
app.py CHANGED
@@ -1,4 +1,3 @@
1
- # Import necessary libraries for Discord bot, HuggingFace integration, and UI
2
  import discord
3
  from discord.ext import commands
4
  from huggingface_hub import hf_hub_download
@@ -7,46 +6,27 @@ from dotenv import load_dotenv
7
  import os
8
  import threading
9
  import asyncio
10
- import spotipy
11
- from spotipy.oauth2 import SpotifyClientCredentials
12
- import yt_dlp
13
 
14
- # Load environment variables from .env file
15
  load_dotenv()
16
 
17
- # Create assets directory and download sample music if not exists
18
  if os.path.exists('assets') is False:
19
  os.makedirs('assets', exist_ok=True)
20
  hf_hub_download("not-lain/assets", "sample.mp3", repo_type="dataset",local_dir="assets")
21
 
22
- # Set up Discord bot with necessary intents
23
  intents = discord.Intents.default()
24
  intents.message_content = True
25
  bot = commands.Bot(command_prefix='!', intents=intents)
26
 
27
- # Initialize Spotify client
28
- spotify = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials(
29
- client_id=os.getenv('SPOTIFY_CLIENT_ID'),
30
- client_secret=os.getenv('SPOTIFY_CLIENT_SECRET')
31
- ))
32
-
33
- # Class to handle music playback functionality
34
  class MusicBot:
35
  def __init__(self):
36
- # Initialize bot state variables
37
  self.is_playing = False
38
  self.voice_client = None
39
- self.ydl_opts = {
40
- 'format': 'bestaudio/best',
41
- 'postprocessors': [{
42
- 'key': 'FFmpegExtractAudio',
43
- 'preferredcodec': 'mp3',
44
- 'preferredquality': '192',
45
- }],
46
- }
47
 
48
  async def join_voice(self, ctx):
49
- # Method to join voice channel or move to user's channel
50
  if ctx.author.voice:
51
  channel = ctx.author.voice.channel
52
  if self.voice_client is None:
@@ -57,18 +37,15 @@ class MusicBot:
57
  await ctx.send("You need to be in a voice channel!")
58
 
59
  async def play_next(self, ctx):
60
- # Method to play audio and handle playback completion
61
  if not self.is_playing:
62
  self.is_playing = True
63
  try:
64
- # Create audio source from local file
65
  audio_source = discord.FFmpegPCMAudio("assets/sample.mp3")
66
  def after_playing(e):
67
- # Callback function when song ends
68
  self.is_playing = False
 
69
  if e:
70
  print(f"Playback error: {e}")
71
- # Test loop by default
72
  asyncio.run_coroutine_threadsafe(self.play_next(ctx), bot.loop)
73
  self.voice_client.play(audio_source, after=after_playing)
74
  except Exception as e:
@@ -76,48 +53,10 @@ class MusicBot:
76
  await ctx.send("Error playing the song.")
77
  self.is_playing = False
78
 
79
- async def play_spotify(self, ctx, track_url):
80
- if not self.is_playing:
81
- self.is_playing = True
82
- try:
83
- # Extract Spotify track ID
84
- track_id = track_url.split('/')[-1].split('?')[0]
85
- track_info = spotify.track(track_id)
86
- search_query = f"{track_info['name']} {track_info['artists'][0]['name']}"
87
-
88
- # Use yt-dlp to find and download the audio
89
- with yt_dlp.YoutubeDL(self.ydl_opts) as ydl:
90
- # Search YouTube for the song
91
- info = ydl.extract_info(f"ytsearch:{search_query}", download=False)
92
- url = info['entries'][0]['url']
93
-
94
- # Play the audio
95
- FFMPEG_OPTIONS = {
96
- 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
97
- 'options': '-vn',
98
- }
99
- audio_source = discord.FFmpegPCMAudio(url, **FFMPEG_OPTIONS)
100
-
101
- def after_playing(e):
102
- self.is_playing = False
103
- if e:
104
- print(f"Playback error: {e}")
105
-
106
- self.voice_client.play(audio_source, after=after_playing)
107
- return track_info['name']
108
-
109
- except Exception as e:
110
- print(f"Error playing Spotify track: {e}")
111
- await ctx.send("Error playing the song.")
112
- self.is_playing = False
113
- return None
114
-
115
- # Create instance of MusicBot
116
  music_bot = MusicBot()
117
 
118
  @bot.event
119
  async def on_ready():
120
- # Event handler for when bot is ready and connected
121
  print(f'Bot is ready! Logged in as {bot.user}')
122
  print("Syncing commands...")
123
  try:
@@ -128,39 +67,30 @@ async def on_ready():
128
  except Exception as e:
129
  print(f"An error occurred while syncing commands: {e}")
130
 
131
- @bot.tree.command(name="play", description="Play a song from Spotify")
132
- async def play(interaction: discord.Interaction, url: str):
133
- # Command to start playing music
134
  await interaction.response.defer()
135
  ctx = await commands.Context.from_interaction(interaction)
136
-
137
- if not url.startswith('https://open.spotify.com/track/'):
138
- await interaction.followup.send('Please provide a valid Spotify track URL!')
139
- return
140
-
141
  await music_bot.join_voice(ctx)
142
 
143
  if not music_bot.is_playing:
144
- song_name = await music_bot.play_spotify(ctx, url)
145
- if song_name:
146
- await interaction.followup.send(f'Playing {song_name} from Spotify!')
147
- else:
148
- await interaction.followup.send('Failed to play the song!')
149
  else:
150
  await interaction.followup.send('Already playing!')
151
 
 
152
  @bot.tree.command(name="skip", description="Skip the current song")
153
  async def skip(interaction: discord.Interaction):
154
- # Command to skip current playing song
155
  if music_bot.voice_client:
156
  music_bot.voice_client.stop()
157
  await interaction.response.send_message('Skipped current song!')
158
  else:
159
  await interaction.response.send_message('No song is currently playing!')
160
 
 
161
  @bot.tree.command(name="leave", description="Disconnect bot from voice channel")
162
  async def leave(interaction: discord.Interaction):
163
- # Command to disconnect bot from voice channel
164
  if music_bot.voice_client:
165
  await music_bot.voice_client.disconnect()
166
  music_bot.voice_client = None
@@ -171,19 +101,17 @@ async def leave(interaction: discord.Interaction):
171
  await interaction.response.send_message('Bot is not in a voice channel!')
172
 
173
  def run_discord_bot():
174
- # Function to start the Discord bot
175
  bot.run(os.getenv('DISCORD_TOKEN'))
176
 
177
- # Create Gradio interface for web control
178
  with gr.Blocks() as iface:
179
- # Set up simple web interface
180
  gr.Markdown("# Discord Music Bot Control Panel")
181
  gr.Markdown("Bot is running in background")
182
 
183
  if __name__ == "__main__":
184
- # Main entry point: start bot in background thread and launch web interface
185
  bot_thread = threading.Thread(target=run_discord_bot, daemon=True)
186
  bot_thread.start()
187
 
188
- # Launch Gradio interface in main thread
189
  iface.launch(debug=True)
 
 
1
  import discord
2
  from discord.ext import commands
3
  from huggingface_hub import hf_hub_download
 
6
  import os
7
  import threading
8
  import asyncio
 
 
 
9
 
10
+ # Load environment variables
11
  load_dotenv()
12
 
13
+ # Download song
14
  if os.path.exists('assets') is False:
15
  os.makedirs('assets', exist_ok=True)
16
  hf_hub_download("not-lain/assets", "sample.mp3", repo_type="dataset",local_dir="assets")
17
 
18
+ # Bot configuration
19
  intents = discord.Intents.default()
20
  intents.message_content = True
21
  bot = commands.Bot(command_prefix='!', intents=intents)
22
 
23
+ # Music bot class
 
 
 
 
 
 
24
  class MusicBot:
25
  def __init__(self):
 
26
  self.is_playing = False
27
  self.voice_client = None
 
 
 
 
 
 
 
 
28
 
29
  async def join_voice(self, ctx):
 
30
  if ctx.author.voice:
31
  channel = ctx.author.voice.channel
32
  if self.voice_client is None:
 
37
  await ctx.send("You need to be in a voice channel!")
38
 
39
  async def play_next(self, ctx):
 
40
  if not self.is_playing:
41
  self.is_playing = True
42
  try:
 
43
  audio_source = discord.FFmpegPCMAudio("assets/sample.mp3")
44
  def after_playing(e):
 
45
  self.is_playing = False
46
+ # test loop by default
47
  if e:
48
  print(f"Playback error: {e}")
 
49
  asyncio.run_coroutine_threadsafe(self.play_next(ctx), bot.loop)
50
  self.voice_client.play(audio_source, after=after_playing)
51
  except Exception as e:
 
53
  await ctx.send("Error playing the song.")
54
  self.is_playing = False
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  music_bot = MusicBot()
57
 
58
  @bot.event
59
  async def on_ready():
 
60
  print(f'Bot is ready! Logged in as {bot.user}')
61
  print("Syncing commands...")
62
  try:
 
67
  except Exception as e:
68
  print(f"An error occurred while syncing commands: {e}")
69
 
70
+ @bot.tree.command(name="play", description="Play the sample music")
71
+ async def play(interaction: discord.Interaction):
 
72
  await interaction.response.defer()
73
  ctx = await commands.Context.from_interaction(interaction)
 
 
 
 
 
74
  await music_bot.join_voice(ctx)
75
 
76
  if not music_bot.is_playing:
77
+ await music_bot.play_next(ctx)
78
+ await interaction.followup.send('Playing sample music!')
 
 
 
79
  else:
80
  await interaction.followup.send('Already playing!')
81
 
82
+ # Replace the existing skip command with this version
83
  @bot.tree.command(name="skip", description="Skip the current song")
84
  async def skip(interaction: discord.Interaction):
 
85
  if music_bot.voice_client:
86
  music_bot.voice_client.stop()
87
  await interaction.response.send_message('Skipped current song!')
88
  else:
89
  await interaction.response.send_message('No song is currently playing!')
90
 
91
+ # Replace the existing leave command with this version
92
  @bot.tree.command(name="leave", description="Disconnect bot from voice channel")
93
  async def leave(interaction: discord.Interaction):
 
94
  if music_bot.voice_client:
95
  await music_bot.voice_client.disconnect()
96
  music_bot.voice_client = None
 
101
  await interaction.response.send_message('Bot is not in a voice channel!')
102
 
103
  def run_discord_bot():
 
104
  bot.run(os.getenv('DISCORD_TOKEN'))
105
 
106
+ # Create the Gradio interface
107
  with gr.Blocks() as iface:
 
108
  gr.Markdown("# Discord Music Bot Control Panel")
109
  gr.Markdown("Bot is running in background")
110
 
111
  if __name__ == "__main__":
112
+ # Start the Discord bot in a separate thread
113
  bot_thread = threading.Thread(target=run_discord_bot, daemon=True)
114
  bot_thread.start()
115
 
116
+ # Run Gradio interface in the main thread
117
  iface.launch(debug=True)