const { addToQueue, playNextInQueue } = require('../utils/queueManager'); const ytDlpExec = require('yt-dlp-exec'); const { v4: uuidv4 } = require('uuid'); const path = require('path'); const { EmbedBuilder } = require('discord.js'); module.exports = { name: 'play', description: 'Play a song from YouTube', async execute(message, args) { const searchQuery = args.join(' '); const voiceChannel = message.member.voice.channel; if (!voiceChannel) { return message.reply('You need to be in a voice channel to play music!'); } if (!searchQuery) { return message.reply('Please provide a YouTube link or a song name.'); } let url, title; try { if (isValidURL(searchQuery)) { url = searchQuery; const info = await ytDlpExec(url, { dumpSingleJson: true }); title = info.title; } else { const searchResult = await ytDlpExec(`ytsearch:${searchQuery}`, { dumpSingleJson: true, noPlaylist: true, format: 'bestaudio/best', quiet: true, }); url = searchResult.entries[0].webpage_url; title = searchResult.entries[0].title; } const embed = new EmbedBuilder() .setColor('#0099ff') .setTitle('Now Playing') .setDescription(`**${title}**`) .setFooter({ text: `Requested by ${message.author.username}`, iconURL: message.author.displayAvatarURL() }) .setTimestamp() message.channel.send({ embeds: [embed] }); const tempFilePath = path.join(__dirname, '../utils/tmp', `${uuidv4()}.mp3`); await ytDlpExec(url, { cookies: path.join(__dirname, '../cookies.txt'), format: 'bestaudio', output: tempFilePath, quiet: true, }); addToQueue(message.guild.id, tempFilePath); playNextInQueue(message.guild.id, voiceChannel); } catch (error) { console.error('yt-dlp error:', error); message.reply('Failed to retrieve or download video. Please try again.'); } }, }; function isValidURL(string) { try { new URL(string); return true; } catch (_) { return false; } }