not-lain commited on
Commit
96f3285
·
1 Parent(s): adfd0c7

add youtube support

Browse files
Files changed (3) hide show
  1. .gitignore +3 -1
  2. app.py +63 -29
  3. requirements.txt +3 -3
.gitignore CHANGED
@@ -1,3 +1,5 @@
1
  .env
2
  assets/
3
- .cache
 
 
 
1
  .env
2
  assets/
3
+ .cache
4
+ test*
5
+ cookies.txt
app.py CHANGED
@@ -1,31 +1,38 @@
1
  import discord
2
  from discord.ext import commands
3
- from huggingface_hub import hf_hub_download
4
- import gradio as gr
5
  from dotenv import load_dotenv
6
  import os
7
  import threading
8
  import asyncio
9
-
10
 
11
  # Load environment variables
12
  load_dotenv()
13
 
14
- # Download song
15
- if os.path.exists('assets') is False:
16
- os.makedirs('assets', exist_ok=True)
17
- hf_hub_download("not-lain/assets", "sample.mp3", repo_type="dataset",local_dir="assets")
 
18
 
19
  # Bot configuration
20
  intents = discord.Intents.default()
21
  intents.message_content = True
22
  bot = commands.Bot(command_prefix='!', intents=intents)
23
 
24
- # Music bot class
25
  class MusicBot:
26
  def __init__(self):
27
  self.is_playing = False
28
  self.voice_client = None
 
 
 
 
 
 
 
 
29
 
30
  async def join_voice(self, ctx):
31
  if ctx.author.voice:
@@ -34,25 +41,44 @@ class MusicBot:
34
  self.voice_client = await channel.connect()
35
  else:
36
  await self.voice_client.move_to(channel)
37
- else:
38
- await ctx.send("You need to be in a voice channel!")
39
 
40
  async def play_next(self, ctx):
41
- if not self.is_playing:
42
  self.is_playing = True
 
 
43
  try:
44
- audio_source = discord.FFmpegPCMAudio("assets/sample.mp3")
45
- def after_playing(e):
 
 
 
 
 
 
 
 
 
 
 
46
  self.is_playing = False
47
- # test loop by default
48
- if e:
49
- print(f"Playback error: {e}")
50
  asyncio.run_coroutine_threadsafe(self.play_next(ctx), bot.loop)
51
- self.voice_client.play(audio_source, after=after_playing)
 
 
 
 
 
 
52
  except Exception as e:
53
- print(f"Error playing file: {e}")
54
- await ctx.send("Error playing the song.")
55
  self.is_playing = False
 
 
56
 
57
  music_bot = MusicBot()
58
 
@@ -68,19 +94,28 @@ async def on_ready():
68
  except Exception as e:
69
  print(f"An error occurred while syncing commands: {e}")
70
 
71
- @bot.tree.command(name="play", description="Play the sample music")
72
- async def play(interaction: discord.Interaction):
73
  await interaction.response.defer()
74
  ctx = await commands.Context.from_interaction(interaction)
75
- await music_bot.join_voice(ctx)
76
 
77
- if not music_bot.is_playing:
78
- await music_bot.play_next(ctx)
79
- await interaction.followup.send('Playing sample music!')
80
- else:
81
- await interaction.followup.send('Already playing!')
 
 
 
 
 
 
 
 
 
 
 
82
 
83
- # Replace the existing skip command with this version
84
  @bot.tree.command(name="skip", description="Skip the current song")
85
  async def skip(interaction: discord.Interaction):
86
  if music_bot.voice_client:
@@ -89,7 +124,6 @@ async def skip(interaction: discord.Interaction):
89
  else:
90
  await interaction.response.send_message('No song is currently playing!')
91
 
92
- # Replace the existing leave command with this version
93
  @bot.tree.command(name="leave", description="Disconnect bot from voice channel")
94
  async def leave(interaction: discord.Interaction):
95
  if music_bot.voice_client:
 
1
  import discord
2
  from discord.ext import commands
3
+ import gradio as gr
 
4
  from dotenv import load_dotenv
5
  import os
6
  import threading
7
  import asyncio
8
+ import yt_dlp
9
 
10
  # Load environment variables
11
  load_dotenv()
12
 
13
+ # Check if cookies.txt exists
14
+ if not os.path.exists('cookies.txt'):
15
+ txt = os.getenv('COOKIES')
16
+ with open('cookies.txt', 'w') as f:
17
+ f.write(txt)
18
 
19
  # Bot configuration
20
  intents = discord.Intents.default()
21
  intents.message_content = True
22
  bot = commands.Bot(command_prefix='!', intents=intents)
23
 
 
24
  class MusicBot:
25
  def __init__(self):
26
  self.is_playing = False
27
  self.voice_client = None
28
+ self.queue = []
29
+ self.ydl_opts = {
30
+ 'format': 'bestaudio/best',
31
+ 'cookiefile': 'cookies.txt',
32
+ 'quiet': True,
33
+ 'no_warnings': True,
34
+ 'extract_flat': 'in_playlist'
35
+ }
36
 
37
  async def join_voice(self, ctx):
38
  if ctx.author.voice:
 
41
  self.voice_client = await channel.connect()
42
  else:
43
  await self.voice_client.move_to(channel)
44
+ return True
45
+ return False
46
 
47
  async def play_next(self, ctx):
48
+ if self.queue and not self.is_playing:
49
  self.is_playing = True
50
+ url = self.queue.pop(0)
51
+
52
  try:
53
+ with yt_dlp.YoutubeDL(self.ydl_opts) as ydl:
54
+ info = ydl.extract_info(url, download=False)
55
+ audio_url = info['url']
56
+ title = info.get('title', 'Unknown title')
57
+
58
+ # Create FFmpeg audio source
59
+ ffmpeg_options = {
60
+ 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
61
+ 'options': '-vn -bufsize 64k'
62
+ }
63
+ audio_source = discord.FFmpegPCMAudio(audio_url, **ffmpeg_options)
64
+
65
+ def after_playing(error):
66
  self.is_playing = False
67
+ if error:
68
+ print(f"Playback error: {error}")
 
69
  asyncio.run_coroutine_threadsafe(self.play_next(ctx), bot.loop)
70
+
71
+ # Apply volume transformation and play
72
+ transformed_source = discord.PCMVolumeTransformer(audio_source, volume=0.5)
73
+ self.voice_client.play(transformed_source, after=after_playing)
74
+
75
+ await ctx.send(f"Now playing: {title}")
76
+
77
  except Exception as e:
78
+ print(f"Error playing URL {url}: {e}")
 
79
  self.is_playing = False
80
+ await ctx.send(f"Error playing the song: {str(e)}")
81
+ await self.play_next(ctx)
82
 
83
  music_bot = MusicBot()
84
 
 
94
  except Exception as e:
95
  print(f"An error occurred while syncing commands: {e}")
96
 
97
+ @bot.tree.command(name="play", description="Play a YouTube URL")
98
+ async def play(interaction: discord.Interaction, url: str):
99
  await interaction.response.defer()
100
  ctx = await commands.Context.from_interaction(interaction)
 
101
 
102
+ if not await music_bot.join_voice(ctx):
103
+ await interaction.followup.send("You need to be in a voice channel!")
104
+ return
105
+
106
+ try:
107
+ with yt_dlp.YoutubeDL(music_bot.ydl_opts) as ydl:
108
+ info = ydl.extract_info(url, download=False)
109
+ title = info.get('title', 'Unknown title')
110
+
111
+ music_bot.queue.append(url)
112
+ await interaction.followup.send(f'Added to queue: {title}')
113
+
114
+ if not music_bot.is_playing:
115
+ await music_bot.play_next(ctx)
116
+ except Exception as e:
117
+ await interaction.followup.send(f'Error: {str(e)}')
118
 
 
119
  @bot.tree.command(name="skip", description="Skip the current song")
120
  async def skip(interaction: discord.Interaction):
121
  if music_bot.voice_client:
 
124
  else:
125
  await interaction.response.send_message('No song is currently playing!')
126
 
 
127
  @bot.tree.command(name="leave", description="Disconnect bot from voice channel")
128
  async def leave(interaction: discord.Interaction):
129
  if music_bot.voice_client:
requirements.txt CHANGED
@@ -1,7 +1,7 @@
1
  discord.py
2
- youtube_dl
3
  PyNaCl
4
  ffmpeg-python
5
- yt-dlp
6
  python-dotenv
7
- spotipy
 
 
 
1
  discord.py
 
2
  PyNaCl
3
  ffmpeg-python
 
4
  python-dotenv
5
+ spotipy
6
+ gradio
7
+ yt-dlp