How to implement a queue array for music bot - javascript

I'm an amateur and I have this music bot setup but not sure how to implement a queue feature which would add videos in an array to be played after one song is finished. Do I have to reformat the code so that there is a queue function before everything or is there a simple fix?
Below is my code,
module.exports = {
name: 'play',
description: 'Joins and plays video from youtube',
async execute(message, args) {
const voiceChannel = message.member.voice.channel;
if(!voiceChannel) return message.channel.send('Join a channel to play a song');
const permissions = voiceChannel.permissionsFor(message.client.user);
if(!permissions.has('CONNECT')) return message.channel.send('You dont have permission to use this function');
if(!permissions.has('SPEAK')) return message.channel.send('You dont have permission to use this function');
if(!args.length) return message.channel.send('You need to send a second argument');
//Set up play function for link
const validURL = (str) =>{
var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
if(!regex.test(str)){
return false;
} else {
return true;
}
}
if(validURL(args[0])){
const connection = await voiceChannel.join();
const stream = ytdl(args[0], {filter: 'audioonly'});
connection.play(stream, {seek: 0, volume: 1})
.on('finish', () =>{
voiceChannel.leave();
message.channel.send('Leaving Channel!');
});
await message.reply('Now Playing Link')
return
}
//Set up play function for youtube search w/ keywords
const connection = await voiceChannel.join();
const videoFinder = async (query) => {
const videoResult = await ytSearch(query);
return (videoResult.videos.length > 1)? videoResult.videos[0] : null;
}
const video = await videoFinder(args.join(' '));
if(video){
const stream = ytdl(video.url, {filter: 'audioonly'});
connection.play(stream, {seek: 0, volume: 1})
.on('finish', () =>{
voiceChannel.leave();
});
await message.reply(`Now Playing ***${video.title}*** ${video.duration}*** ${video.thumbnail}`)
} else {
message.channel.send('No video results found.');
}
}
}

module.exports = {
name: 'play',
description: 'Joins and plays video from youtube',
queues: {},
voiceConnections: {},
execute() {
if (!this.voiceConnections[guildId]) {
// setup voiceConnections[guildId]
this.voiceConnections[guildId].on('finish', () => {
this.voiceConnections[guildId].play(this.queues[guildId].pop())
}
}
if (track already playing in voice connection) {
this.queues[guildId].push(newTrackDetails);
} else {
// play the track
}
}
}
Some pseudocode. Idea: Each guild has its own queue and voice channel connection. The queue object format looks something like {'guildId1': [...queue tracks details here]}

Related

voiceChannel.join() isn't a function node v16 discord.js

I made a bot that plays music. I upgraded to NodeJS v16.6.1 and voiceChannel.join doesn't work anymore.
I already tried using const { voiceChannel } = require('#discord.js/voice'); but it just says module not found.
Code:
const ytdl = require("ytdl-core");
const ytSearch = require("yt-search");
module.exports = {
name: 'play',
description: 'Joins and plays a video from youtube',
async execute(message, args) {
const voiceChannel = message.member.voice.channel;
if (!voiceChannel) return message.channel.send('You need to be in a channel to execute this command');
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT')) return message.channel.send('You dont have the neccesary permissions');
if (!permissions.has("SPEAK")) return message.channel.send('You dont have the neccesary permissions');
if (!args.length) return message.channel.send('Define Video');
const connection = await voiceChannel.join();
const videoFinder = async (query) => {
const videoResult = await ytSearch(query);
return (videoResult.videos.length > 1) ? videoResult.videos[0] : null;
}
const video = await videoFinder(args.join(' '));
if (video) {
const stream = ytdl(video.url, {
filter: 'audioonly'
});
connection.play(stream, {
seek: 0,
volume: 1
})
.on('finish', () => {
voiceChannel.leave();
});
await message.reply(`Now Playing **${video.title}**`)
} else {
message.channel.send('No videos found');
}
}
}```
As the error says, voiceChannel#join is not, in fact, a function. While it did exist on Discord.js v12, which I assume you were using before updating your Node.js version, note that it is nowhere to be found in the Discord.js v13 documentation on VoiceChannel. Instead, you are to migrate to #discordjs/voice, whose joinVoiceChannel function can be used as a replacement.

Discord Bot leave the VC after X Seconds with Discord.js

Heyy,
Im building a Discord Bot for do some practice with Node.js and Discord.js. With this bot you can do the command ?audio audio and it will reproduce a audio.
I want to set that the bot after 20 seconds of not playing anything leave the Voice Channel. I did it with the function setTimeout() but when I want to listen another audio the bot leave the channel before the audio finish.
The problem is obv the setTimeout() but idk how to fix it.
Here's my code.
execute(message, args, CanaleVocale, AudioFiles) {
let inactive
let name = args[1] + ".mp3";
console.log("[Command] ?audio " + message.author.id)
if (!CanaleVocale) {
message.channel.send("Il Koala e' confuso, non ti vede in nessun canale vocale :( ")
console.log(`[Voice] The user ${message.author.id} isn't in a voice channel` )
} else {
if (AudioFiles.includes(name)) {
CanaleVocale.join()
.then(connection => {
clearTimeout(inactive)
inactive = undefined
connection.voice.setSelfDeaf(true);
connection.play(`./audio/${name}`)
console.log(`[Voice] Played the sound ${name} for the user ${message.author} `)
inactive = setTimeout(function(){
CanaleVocale.leave()
console.log(`[Voice] Left from the channel of ${message.author.id}`)
message.channel.send("Il Koala e' annoiato e quindi esce dalla chat vocale")
}, 20*1000)
})
} else {
message.channel.send(`L'audio ${name} non esiste!`)
console.log(`[Voice] The user ${message.author} tried to play ${name} but it doesn't exist!`)
}
}
}
}
If you need the entire project, it is uploaded on GitHub, "KoalaBot" by EnderF5027
(Probably the code is ugly, im learning and if you want to, you can give me some suggestions :D )
Can someone help me ?
Thank you
I attach my code for example.
I handle not file base, only youtube with ytdl.
So, It could be differect with questions.
I handle joined channels with Map() Object.
// message.guild.id = '1234567812345678'
const queue = new Map();
// 1. set new queue
const queueContruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
search: [],
volume: 5,
playing: true,
leaveTimer: null /* 20 seconds in question */
};
queue.set('1234567812345678', queueContruct);
// 2. get queueContruct from queue
const serverQueue = queue.get('1234567812345678');
if(!serverQueue) { /* not exist */ }
// 3. delete from queue
queue.delete('1234567812345678');
I set timer with setTimeout when play-list is empty
and unset with clearTimeout when new play-list is come in.
Under is a piece of my code.
I wish this will be helpful.
const Discord = require('discord.js');
const bot = new Discord.Client();
const queue = new Map();
const prefix = "?"; // this prefix is in Question.
bot.on("message", async message => {
// if direct-message received, message.guild could be null
// Not handle that case.
const serverQueue = queue.get(message.guild.id);
if(message.content.startsWith(`${prefix}audio`)) {
execute(message, serverQueue);
}
});
// I assume user message is "?audio audioName"
function execute(message, serverQueue) {
const audioName = message.content.split(' ')[1]; // "audioName"
// check user who send message is in voiceChannel
const voiceChannel = message.member.voice.channel;
if(!voiceChannel) {
return message.channel.send("YOU ARE NOT IN VOICE CHANNEL");
}
// check permission
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has("CONNECT") || !permissions.has("SPEAK")) {
return message.channel.send("PERMISSION ERROR");
}
/*
I handle only songs with google youtube api
So, I skip how to get & push song information
*/
if(!serverQueue) {
// create new serverQueue
const queueContruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
search: [],
volume: 5,
playing: true
};
queue.set(message.guild.id, queueContruct);
// "song" value is one of play list in my case
// var song = {title: 'audioName', url: 'youtube-url'};
queueContruct.songs.push(song);
try {
var connection = await voiceChannel.join();
queueContruct.connection = connection;
playStart(message.guild, queueContruct.songs[0]);
} catch (err) {
queue.delete(message.guild.id);
return message.channel.send(err);
}
}
else { // exist serverQueue
// "song" value is one of play list in my case
// var song = {title: 'audioName', url: 'youtube-url'};
serverQueue.songs.push(song);
if(serverQueue.songs.length == 1) {
playStart(message.guild, serverQueue.songs[0]);
}
}
}
function play(guild, song) {
const serverQueue = queue.get(guild.id);
if(!song) {
if(serverQueue.songs.length == 0) {
serverQueue.leaveTimer = setTimeout(function() {
leave_with_timeout(guild.id);
}, 20 * 1000); // 20 seconds is for follow question
}
return;
}
// clear timer before set
try {
clearTimeout(serverQueue.leaveTimer);
} catch(e) {
// there's no leaveTimer
}
const dispatcher = serverQueue.connection
.play(ytdl(song.url))
.on('finish', () => {
serverQueue.songs.shift(); // pop front
play(guild, serverQueue.songs[0]); // play next
})
.on('error' error => console.log(error));
dispatcher.setVolumeLogarithmic( 1 );
serverQueue.textChannel.send(`Play Start ${song.title}`);
}
function leave_with_timeout(guild_id) {
const serverQueue = queue.get(guild_id);
if(serverQueue) {
serverQueue.textChannel.send(`20 seconds left. Bye!`);
serverQueue.voiceChannel.leave();
queue.delete(guild_id);
}
}

undefined song when I run the play command

I'm trying to build a music discord bot with yt-search but it gives me undefined whenever I play the song and it joins the voice channel without playing the song. I'm trying to use yt-search to find the video I want or only the URL then pass it to ytdl to run it with the URL given from yt-search but I think I'm wrong in some points. I don't know where, could you please fix my code ?
Image to show the problem:
My code:
const Discord = require("discord.js");
const { prefix, token } = require("./config.json");
const ytdl = require("ytdl-core");
const yts = require("yt-search");
const client = new Discord.Client();
const queue = new Map();
client.once("ready", () => {
console.log("Ready!");
});
client.once("reconnecting", () => {
console.log("Reconnecting!");
});
client.once("disconnect", () => {
console.log("Disconnect!");
});
client.on("message", async message => {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
const serverQueue = queue.get(message.guild.id);
if (message.content.startsWith(`${prefix}play`)) {
execute(message, serverQueue);
return;
} else if (message.content.startsWith(`${prefix}skip`)) {
skip(message, serverQueue);
return;
} else if (message.content.startsWith(`${prefix}stop`)) {
stop(message, serverQueue);
return;
} else {
message.channel.send("You need to enter a valid command!");
}
});
async function execute(message, serverQueue) {
const args = message.content.split(" ");
const voiceChannel = message.member.voice.channel;
if (!voiceChannel)
return message.channel.send(
"You need to be in a voice channel to play music!"
);
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has("CONNECT") || !permissions.has("SPEAK")) {
return message.channel.send(
"I need the permissions to join and speak in your voice channel!"
);
}
const r = await yts(args[1,2]);
const video = r.videos.slice( 0, 1 );
console.log(video);
const songInfo = await ytdl.getInfo(video.url);
const song = {
title: songInfo.videoDetails.title,
url: songInfo.videoDetails.video_url,
};
if (!serverQueue) {
const queueContruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
volume: 5,
playing: true
};
queue.set(message.guild.id, queueContruct);
queueContruct.songs.push(song);
try {
var connection = await voiceChannel.join();
queueContruct.connection = connection;
play(message.guild, queueContruct.songs[0]);
} catch (err) {
console.log(err);
queue.delete(message.guild.id);
return message.channel.send(err);
}
} else {
serverQueue.songs.push(song);
return message.channel.send(`${song.title} has been added to the queue!`);
}
}
function skip(message, serverQueue) {
if (!message.member.voice.channel)
return message.channel.send(
"You have to be in a voice channel to stop the music!"
);
if (!serverQueue)
return message.channel.send("There is no song that I could skip!");
serverQueue.connection.dispatcher.end();
}
function stop(message, serverQueue) {
if (!message.member.voice.channel)
return message.channel.send(
"You have to be in a voice channel to stop the music!"
);
if (!serverQueue)
return message.channel.send("There is no song that I could stop!");
serverQueue.songs = [];
serverQueue.connection.dispatcher.end();
}
function play(guild, song) {
const serverQueue = queue.get(guild.id);
if (!song) {
serverQueue.voiceChannel.leave();
queue.delete(guild.id);
return;
}
const dispatcher = serverQueue.connection
.play(ytdl(song.url))
.on("finish", () => {
serverQueue.songs.shift();
play(guild, serverQueue.songs[0]);
})
.on("error", error => console.error(error));
dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
serverQueue.textChannel.send(`Start playing: **${song.title}**`);
}
client.login(token);
There are two errors. I'm not sure what you think args[1,2] is but it's the same as args[2] which is the third item of the args array. By reading your code, I think you want to use a string here, the search term. By removing the first item (the command) from the args array and joining the rest of them, you will receive a string you can use as keywords. Check out the example below:
const message = { content: '!play some music I want'}
const args = message.content.split(' ')
console.log({ args })
// => ["!play", "some", "music", "I", "want"]
console.log({ 'args[1, 2]': args[1, 2] })
// => "music"
console.log({ 'search': args.slice(1).join(' ') })
// => "some music I want"
The other error is that await yts(query) returns an array of results and when you define the video variable you use r.videos.slice(0, 1). The .slice() method returns a new array with the first item of r.videos.
As the video variable is an array, video.url is undefined. You could fix it by using the first item instead as it will have a url property. You should also check if there are any search results.
Check out the updated code below:
async function execute(message, serverQueue) {
const args = message.content.split(' ');
const voiceChannel = message.member.voice.channel;
if (!voiceChannel)
return message.channel.send(
'You need to be in a voice channel to play music!',
);
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT') || !permissions.has('SPEAK')) {
return message.channel.send(
'I need the permissions to join and speak in your voice channel!',
);
}
const query = args.slice(1).join(' ');
const results = await yts(query);
if (!results.videos.length)
return message.channel.send(`No results for \`${query}\``);
const firstVideo = results.videos[0];
const songInfo = await ytdl.getInfo(firstVideo.url);
const song = {
title: songInfo.videoDetails.title,
url: songInfo.videoDetails.video_url,
};
console.log(song);
if (!serverQueue) {
// ...
// ...

How do I fix Seek Command making song go back to beginning - Discord.js

I am making a Seek command with YTDL-Core and Discord.js as part of my updated music commands and I am having issues with how I am seeking the song playing in the Voice Call.
What my seek command should exactly do is if I specify n!seek 2:00 for example, it should go to 2:00 timestamp from where the song is currently played to that specified timestamp.
Instead of that, the issue I am getting is if I specify any song timestamp (2:00 etc.) it will go back to the beginning of when the song is played, 0:00. There are no errors in the Console that I am aware of when I execute the command.
Seek.js: (Command used to seek song)
//Problem is seek will keep going back to start of song whenever it does.
const {handleVideo, queue, youtube}= require('../../util/music/handleVideo');
const { RichEmbed } = require("discord.js");
exports.run = async (client, msg, args) => {
const serverQueue = queue.get(msg.guild.id);
if (!msg.member.voiceChannel) return msg.channel.send("Join voice channel first");
if (!serverQueue) return msg.channel.send("No songs to seek");
if (serverQueue.voiceChannel.id !== msg.member.voiceChannel.id) return msg.chanel.send(`You must in **${serverQueue.voiceChannel.name}** to seek the song`);
try {
const curDuration = (serverQueue.songs[0].durationm * 60000) + ((serverQueue.songs[0].durations % 60000) * 1000);
const choiceDur = args.join(" ").split(":");
if (choiceDur.length < 2) return msg.channel.send("No duration provided or invalid ?");
const optDurr = (parseInt(choiceDur[0], 10) * 60000) + ((parseInt(choiceDur[1], 10) % 60000) * 1000);
if (optDurr > curDuration) return msg.channel.send("Your duration is too big");
serverQueue.songs.splice(1, 0, serverQueue.songs[0]);
return serverQueue.connection.dispatcher.end()
} catch (e) {
return msg.channel.send(`Oh no an error occured :( \`${e.message}\` try again later`);
}
};
exports.conf = {
aliases: [],
clientPerm: "",
authorPerm: ""
};
exports.help = {
name: "seek",
description: "Seek current songs",
usage: "seek <duration>",
example: ["seek 00:00"]
};
handleVideo.js: (How the music commands are handled)
const YouTube = require('simple-youtube-api');
const ytdl = require('ytdl-core');
const moment = require("moment");
let config = require('../../config.json');
const youtube = new YouTube(config.youtube_api);
const { Client, Util, RichEmbed} = require('discord.js');
var queue = new Map();
async function handleVideo(video, msg, voiceChannel, playlist = false) {
if (video.durationSeconds === 0) {
let livestreamembed = new RichEmbed()
.setTitle(`**Music 🎵**`)
.setDescription(`**Cannot play Livestreams...** ❌\n\nPlease use YouTube Links only instead.`)
.setColor(`#e05e7c`)
return msg.channel.send(livestreamembed);
return undefined;
}
const serverQueue = queue.get(msg.guild.id);
//console.log(video)
const song = {
id: video.id,
title: Util.escapeMarkdown(video.title),
url: `https://www.youtube.com/watch?v=${video.id}`,
durationmm: video.durationSeconds ? video.durationSeconds : video.duration / 1000,
channel: msg.member.voiceChannel.name,
uploadedby: video.channel.title,
channelurl: `https://www.youtube.com/channel/${video.channel.id}`,
author: msg.author,
durationh: video.duration.hours,
durationm: video.duration.minutes,
durations: video.duration.seconds,
duration: video.duration,
};
if (!serverQueue) {
const queueConstruct = {
textChannel: msg.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
volume: 100,
playing: true,
loop: false,
};
queue.set(msg.guild.id, queueConstruct);
queueConstruct.songs.push(song);
try {
var connection = await voiceChannel.join();
queueConstruct.connection = connection;
play(msg.guild, queueConstruct.songs[0])
} catch (error) {
console.error(`NateBot » Cannot join Voice Channel: ${error}`);
queue.delete(msg.guild.id);
return msg.channel.send(`**NateBot |** Could not join the voice channel: ${error}`);
}
} else {
if (serverQueue.songs.some(song => song.id === video.id)) {
msg.channel.send(`**NateBot |** **Error Queuing this song...**\n\n**\`${Util.escapeMarkdown(video.title)}\`** is already queued/playing!\nCheck \`n!queue\` for Music Queue`);
return;
}
serverQueue.songs.push(song);
if (playlist) return undefined;
//Queue Message (Sent When song is requested 2nd time or more)
var queueembed = new RichEmbed()
.setTitle(`**Music 🎵**`)
.setColor(`#0xd677ff`)
.setDescription(`
__**Successfully Queued!**__ 👍🏻
**[${song.title}](https://www.youtube.com/watch?v=${song.id}})**
**Uploaded by »** **[${song.uploadedby}](${song.channelurl})**
**Video ID »** ${song.id}
**Duration »** **\`${require('../../util/util.js').timeString(song.durationmm)}\`**
**Published »** ${moment.utc(song.publishedAt).format('LLLL')}
`)
.setFooter(`Requested by » ${song.author.username}`, `${song.author.displayAvatarURL}`)
.setTimestamp()
.setImage(`https://i.ytimg.com/vi/${song.id}/maxresdefault.jpg`)
return msg.channel.send(queueembed);
}
return undefined;
}
function play(guild, song, msg) {
const serverQueue = queue.get(guild.id);
if (!song) {
queue.delete(guild.id);
return;
}
const dispatcher = serverQueue.connection.playStream(ytdl(song.url, { quality: 'highestaudio', filter: "audioonly", highWaterMark: 2000 }))
.on('end', reason => {
if (reason === 'Stream is not generating quickly enough.') console.log('NateBot » Song ended.');
else console.log(reason);
const shifed = serverQueue.songs.shift();
if(serverQueue.loop) serverQueue.songs.push(shifed);
play(guild, serverQueue.songs[0]);
})
.on('error', error => console.error(error));
dispatcher.setVolumeLogarithmic(serverQueue.volume / 100);
//Now Playing Embed (Sent when Bot starts playing music)
var pleyembed = new RichEmbed()
.setTitle(`**Music 🎵**`)
.setColor(`0x76d6ff`)
.setDescription(`
__**Now Playing!**__ 🎶
**[${song.title}](https://www.youtube.com/watch?v=${song.id}})**
**Uploaded by »** **[${song.uploadedby}](${song.channelurl})**
**Video ID »** ${song.id}
**Duration »** **\`${require('../../util/util.js').timeString(song.durationmm)}\`**
**Published »** ${moment.utc(song.publishedAt).format('LLLL')}
`)
.setImage(`https://i.ytimg.com/vi/${song.id}/maxresdefault.jpg`)
serverQueue.textChannel.send(pleyembed);
}
module.exports = {handleVideo, queue, youtube};
What i've tried to do is to change the following in seek.js
return serverQueue.connection.dispatcher.end()
to
return serverQueue.connection.dispatcher.seek()
As this was noted in https://discord.js.org/#/docs/main/stable/typedef/StreamOptions, I tried to do this method but to no avail...
I am not 100% sure why this is causing the issue. Perhaps its probably a discord.js version change. I currently use 11.5.1 as Discord.JS version.

My Discord Music bot executes an object instead of text

I tried to make a music bot, but it wont execute the song. Below is the code for the section which should gather the information and execute the song.
Can someone help me get this right? I'm not sure how to fix this issue as I don't know where the error starts.
I pasted also the handleVideo and the play class in the end so you know what happens there.
if (command === 'play') {
const voiceChannel = message.member.voiceChannel;
if (!voiceChannel) return message.channel.send('I\'m sorry but you need to be in a voice channel to play music!');
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT')) {
return message.channel.send('I cannot connect to your voice channel, make sure I have the proper permissions!');
}
if (!permissions.has('SPEAK')) {
return message.channel.send('I cannot speak in this voice channel, make sure I have the proper permissions!');
}
if (url.match(/^https?:\/\/(www.youtube.com|youtube.com)\/playlist(.*)$/)) {
const playlist = await youtube.getPlaylist(url);
const videos = await playlist.getVideos();
for (const video of Object.values(videos)) {
const video2 = await youtube.getVideoByID(video.id); // eslint-disable-line no-await-in-loop
await handleVideo(video2, message, voiceChannel, true); // eslint-disable-line no-await-in-loop
}
return message.channel.send(`✅ Playlist: **${playlist.title}** has been added to the queue!`);
} else {
try {
var video = await youtube.getVideo(url);
} catch (error) {
try {
var videos = await youtube.searchVideos(searchString, 10);
let index = 0;
message.channel.send(`
__**Song selection:**__
${videos.map(video2 => `**${++index} -** ${video2.title}`).join('\n')}
Please provide a value to select one of the search results ranging from 1-10.
`);
// eslint-disable-next-line max-depth
try {
var response = await message.channel.awaitMessages(msg2 => msg2.content > 0 && msg2.content < 11, {
maxMatches: 1,
time: 10000,
errors: ['time']
});
} catch (err) {
console.error(err);
return message.channel.send('No or invalid value entered, cancelling video selection.');
}
const videoIndex = parseInt(response.first().content);
var video = await youtube.getVideoByID(videos[videoIndex - 1].id);
} catch (err) {
console.error(err);
return message.channel.send('🆘 I could not obtain any search results.');
}
}
return handleVideo(video, message, voiceChannel);
}
}
async function handleVideo(video, message, voiceChannel, playlist = false) {
const serverQueue = queue.get(message.guild.id);
console.log(video);
const song = {
id: video.id,
title: Util.escapeMarkdown(video.title),
url: `https://www.youtube.com/watch?v=${video.id}`
};
if (!serverQueue) {
const queueConstruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
volume: 5,
playing: true
};
queue.set(message.guild.id, queueConstruct);
queueConstruct.songs.push(song);
try {
var connection = await voiceChannel.join();
queueConstruct.connection = connection;
play(message.guild, queueConstruct.songs[0]);
} catch (error) {
console.error(`I could not join the voice channel: ${error}`);
queue.delete(message.guild.id);
return message.channel.send(`I could not join the voice channel: ${error}`);
}
} else {
serverQueue.songs.push(song);
console.log(serverQueue.songs);
if (playlist) return undefined;
else return message.channel.send(`✅ **${song.title}** has been added to the queue!`);
}
return undefined;
});
function play(guild, song) {
const serverQueue = queue.get(guild.id);
if (!song) {
serverQueue.voiceChannel.leave();
queue.delete(guild.id);
return;
}
console.log(serverQueue.songs);
const dispatcher = serverQueue.connection.playStream(ytdl(song.url))
.on('end', reason => {
if (reason === 'Stream is not generating quickly enough.') console.log('Song ended.');
else console.log(reason);
serverQueue.songs.shift();
play(guild, serverQueue.songs[0]);
})
.on('error', error => console.error(error));
dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
serverQueue.textChannel.send(`🎶 Start playing: **${song.title}**`);
}
The error message:
TypeError [ERR_INVALID_ARG_TYPE]: The "file" argument must be of type string. Received type object
at validateString (internal/validators.js:125:11)
at normalizeSpawnArguments (child_process.js:411:3)
at Object.spawn (child_process.js:545:16)
at new FfmpegProcess (C:\Users\user\Desktop\ExoBot-master\node_modules\prism-media\src\transcoders\ffmpeg\FfmpegProcess.js:14:33)
at FfmpegTranscoder.transcode (C:\Users\user\Desktop\ExoBot-master\node_modules\prism-media\src\transcoders\ffmpeg\Ffmpeg.js:34:18)
at MediaTranscoder.transcode (C:\Users\user\Desktop\ExoBot-master\node_modules\prism-media\src\transcoders\MediaTranscoder.js:27:31)
at Prism.transcode (C:\Users\user\Desktop\ExoBot-master\node_modules\prism-media\src\Prism.js:13:28)
at AudioPlayer.playUnknownStream (C:\Users\user\Desktop\ExoBot-master\node_modules\discord.js\src\client\voice\player\AudioPlayer.js:97:35)
at VoiceConnection.playStream (C:\Users\user\Desktop\ExoBot-master\node_modules\discord.js\src\client\voice\VoiceConnection.js:478:24)
at play (C:\Users\user\Desktop\ExoBot-master\bot.js:322:44)

Categories

Resources