play from yt
This commit is contained in:
parent
ba1ec53753
commit
f693dd07ff
2 changed files with 64 additions and 31 deletions
|
@ -5,6 +5,7 @@
|
||||||
. ./bin/activate ;
|
. ./bin/activate ;
|
||||||
pip install discord ;
|
pip install discord ;
|
||||||
pip install PyNaCl ;
|
pip install PyNaCl ;
|
||||||
pip install fuzzywuzzy ;
|
|
||||||
pip install python-dotenv ;
|
pip install python-dotenv ;
|
||||||
|
pip install ytmusicapi ;
|
||||||
|
pip install yt_dlp ;
|
||||||
)
|
)
|
||||||
|
|
92
main.py
92
main.py
|
@ -2,39 +2,65 @@ import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
import asyncio
|
import asyncio
|
||||||
import os
|
import os
|
||||||
from fuzzywuzzy import process
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
import yt_dlp
|
||||||
|
from ytmusicapi import YTMusic
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
songs_dir = os.getenv("SONGS_DIR")
|
||||||
intents = discord.Intents.default()
|
intents = discord.Intents.default()
|
||||||
intents.message_content = True
|
intents.message_content = True
|
||||||
intents.voice_states = True
|
intents.voice_states = True
|
||||||
bot = commands.Bot(command_prefix='!', intents=intents)
|
bot = commands.Bot(command_prefix='!', intents=intents)
|
||||||
queued_songs = []
|
queued_songs = []
|
||||||
voice_client = None # Global variable to track voice client
|
voice_client = None
|
||||||
|
|
||||||
def find_song(query, songs_dir):
|
def search_song(query):
|
||||||
best_match = None
|
ytmusic = YTMusic()
|
||||||
best_confidence = 0
|
search_results = ytmusic.search(query, filter='songs', limit=1)
|
||||||
|
if search_results:
|
||||||
|
song_id = search_results[0]['videoId']
|
||||||
|
return song_id
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def search_video(query):
|
||||||
|
ydl_opts = {
|
||||||
|
'default_search': 'auto',
|
||||||
|
'format': 'best',
|
||||||
|
'quiet': True
|
||||||
|
}
|
||||||
|
|
||||||
for root, dirs, files in os.walk(songs_dir):
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||||
for file in files:
|
try:
|
||||||
if file.endswith(".mp3"):
|
result = ydl.extract_info(query, download=False)
|
||||||
song_path = os.path.join(root, file)
|
if 'entries' in result:
|
||||||
song_name = os.path.splitext(file)[0]
|
# Take the first result
|
||||||
full_song_name = os.path.relpath(song_path, start=songs_dir)
|
video_id = result['entries'][0]['id']
|
||||||
|
return video_id
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except yt_dlp.DownloadError:
|
||||||
|
return None
|
||||||
|
|
||||||
confidence = process.extractOne(query, [song_name.replace("_", " ")])[1]
|
def download_song(query):
|
||||||
if confidence > best_confidence:
|
song_id = search_video(query)
|
||||||
best_match = song_path
|
ydl_opts = {
|
||||||
best_confidence = confidence
|
'format': 'bestaudio/best',
|
||||||
|
'outtmpl': f'{songs_dir}/%(title)s.%(ext)s',
|
||||||
confidence = process.extractOne(query, [full_song_name.replace("_", " ")])[1]
|
'postprocessors': [{
|
||||||
if confidence > best_confidence:
|
'key': 'FFmpegExtractAudio',
|
||||||
best_match = song_path
|
'preferredcodec': 'mp3',
|
||||||
best_confidence = confidence
|
'preferredquality': '192',
|
||||||
|
}],
|
||||||
return best_match, best_confidence
|
}
|
||||||
|
if not os.path.exists(songs_dir):
|
||||||
|
os.makedirs(songs_dir)
|
||||||
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||||
|
info = ydl.extract_info(f'https://music.youtube.com/watch?v={song_id}', download=True)
|
||||||
|
filename = ydl.prepare_filename(info)
|
||||||
|
filename = os.path.splitext(filename)[0] + '.mp3'
|
||||||
|
return filename
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def play(ctx, *, query):
|
async def play(ctx, *, query):
|
||||||
|
@ -53,6 +79,10 @@ async def skip(ctx):
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def stop(ctx):
|
async def stop(ctx):
|
||||||
global voice_client
|
global voice_client
|
||||||
|
for file in os.listdir(songs_dir):
|
||||||
|
file_path = os.path.join(songs_dir, file)
|
||||||
|
if os.path.isfile(file_path):
|
||||||
|
os.unlink(file_path)
|
||||||
if voice_client and voice_client.is_connected():
|
if voice_client and voice_client.is_connected():
|
||||||
queued_songs.clear()
|
queued_songs.clear()
|
||||||
if voice_client.is_playing():
|
if voice_client.is_playing():
|
||||||
|
@ -63,11 +93,10 @@ async def stop(ctx):
|
||||||
|
|
||||||
async def add_to_queue(ctx, query):
|
async def add_to_queue(ctx, query):
|
||||||
global voice_client
|
global voice_client
|
||||||
songs_dir = os.getenv("SONGS_DIR")
|
song_path = download_song(query)
|
||||||
# Find the closest match to the query
|
print(song_path)
|
||||||
song_path, confidence = find_song(query, songs_dir)
|
|
||||||
|
|
||||||
if confidence >= 70 and song_path: # Adjust confidence threshold as needed
|
if song_path:
|
||||||
song_name = os.path.relpath(song_path, start=songs_dir) # Get the song name relative to songs_dir
|
song_name = os.path.relpath(song_path, start=songs_dir) # Get the song name relative to songs_dir
|
||||||
queued_songs.append((song_path, song_name))
|
queued_songs.append((song_path, song_name))
|
||||||
await ctx.send(f"**Added to queue:** `{song_name}`")
|
await ctx.send(f"**Added to queue:** `{song_name}`")
|
||||||
|
@ -78,11 +107,10 @@ async def connect_and_play(ctx, query):
|
||||||
global voice_client
|
global voice_client
|
||||||
voice_channel = ctx.author.voice.channel
|
voice_channel = ctx.author.voice.channel
|
||||||
if voice_channel:
|
if voice_channel:
|
||||||
songs_dir = os.getenv("SONGS_DIR")
|
song_path = download_song(query)
|
||||||
# Find the closest match to the query
|
print(song_path)
|
||||||
song_path, confidence = find_song(query, songs_dir)
|
|
||||||
|
|
||||||
if confidence >= 70 and song_path: # Adjust confidence threshold as needed
|
if song_path:
|
||||||
song_name = os.path.relpath(song_path, start=songs_dir) # Get the song name relative to songs_dir
|
song_name = os.path.relpath(song_path, start=songs_dir) # Get the song name relative to songs_dir
|
||||||
queued_songs.append((song_path, song_name))
|
queued_songs.append((song_path, song_name))
|
||||||
voice_client = await play_queued_songs(ctx, voice_channel)
|
voice_client = await play_queued_songs(ctx, voice_channel)
|
||||||
|
@ -99,6 +127,10 @@ async def play_queued_songs(ctx, voice_channel):
|
||||||
while voice_client and voice_client.is_playing(): # Check if voice_client is not None
|
while voice_client and voice_client.is_playing(): # Check if voice_client is not None
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
if voice_client:
|
if voice_client:
|
||||||
|
for file in os.listdir(songs_dir):
|
||||||
|
file_path = os.path.join(songs_dir, file)
|
||||||
|
if os.path.isfile(file_path):
|
||||||
|
os.unlink(file_path)
|
||||||
await voice_client.disconnect()
|
await voice_client.disconnect()
|
||||||
|
|
||||||
bot.run(os.getenv("DISCORD_TOKEN"))
|
bot.run(os.getenv("DISCORD_TOKEN"))
|
||||||
|
|
Loading…
Reference in a new issue