Play discord command - node.js

Hello I have been having a problem with a play command with discord. I am unsure of what the problem is and if it is possible please help. I will be honest I got this code from somewhere else but its for a private server. Please help fix this thank you. Anyway I have been trying to create a play, stop, skip, nowplaying command for ages and if this works it would be amazing thank you.
Console Error:
TypeError: Cannot read property 'get' of undefined
Code:
const ytdl = require("ytdl-core");
module.exports = {
name: "play",
description: "Play a song in your channel!",
async execute(message) {
try {
const args = message.content.split(" ");
const queue = message.client.queue;
const serverQueue = message.client.queue.get(message.guild.id);
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 songInfo = await ytdl.getInfo(args[1]);
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;
this.play(message, 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!`
);
}
} catch (error) {
console.log(error);
message.channel.send(error.message);
}
},
play(message, song) {
const queue = message.client.queue;
const guild = message.guild;
const serverQueue = queue.get(message.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();
this.play(message, serverQueue.songs[0]);
})
.on("error", error => console.error(error));
dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
serverQueue.textChannel.send(`Start playing: **${song.title}**`);
}
};

You should look where you got the code from, maybe you missed a part?
specifically where they define client.queue
usually most of the people define it like
client.queue = new Map()
or discord.js collection class (Extended from map)
in your main bot file (index.js, bot.js etc).
You could either check where you got code from or try adding this to where you define client in your main bot file

Related

discord bot doesnt play music

I have a discord bot that im trying to make play music. It will join the voice channel but it wont play anything. I've tried lots of things but nothing seems to be working. Here is the code:
const ytdl = require("ytdl-core")
const ytSearch = require("yt-search")
const {
joinVoiceChannel,
createAudioPlayer,
createAudioResource
} = require('#discordjs/voice')
module.exports = {
name: "play",
description: "Plays a song of your choice.",
async execute(messageCreate, args) {
const voiceChannel = messageCreate.member.voice.channel
if (!voiceChannel) return messageCreate.channel.send("You must be in a voice channel to run this command.")
const permissions = voiceChannel.permissionsFor(messageCreate.client.user)
if (!permissions.has("CONNECT")) return messageCreate.channel.send("You do not have the sufficient permissions to do this.")
if (!permissions.has("SPEAK")) return messageCreate.channel.send("You do not have the sufficient permissions to do this.")
if (!args.length) return messageCreate.channel.send("You must specify some keywords to identify the song you are looking for.")
joinVoiceChannel({
channelId: messageCreate.member.voice.channel.id,
guildId: messageCreate.guild.id,
adapterCreator: messageCreate.guild.voiceAdapterCreator
})
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"})
const player = createAudioPlayer()
const resource = createAudioResource(stream)
async function play() {
await player.play(resource)
connection.subscribe(player)
connection.play(stream, {seek: 0, volume: 1})
.on("finish", () => {
voiceChannel.leave()
})
}
await messageCreate.reply(`:thumbsup: Now playing: ***${video.title}***.`)
} else {
messageCreate.channel.send("No video results found.")
}
}
}
I am using VS Code node.js 18.7.0 and discord.js v13. I really need help with this so anything would be appreciated.
From what I can see, you're never actually playing the video.
You define this function, 'play,' but never call it.
async function play() {
await player.play(resource)
connection.subscribe(player)
connection.play(stream, {seek: 0, volume: 1})
.on("finish", () => {
voiceChannel.leave()
})
}
From what I can tell, you're trying to make an async function so you can use the await keyword, but this isn't necessary. Just put the body of the play function into the code normally, and the stream should play to the channel.
const ytdl = require("ytdl-core")
const ytSearch = require("yt-search")
const {
joinVoiceChannel,
createAudioPlayer,
createAudioResource
} = require('#discordjs/voice')
module.exports = {
name: "play",
description: "Plays a song of your choice.",
async execute(messageCreate, args) {
const voiceChannel = messageCreate.member.voice.channel
if (!voiceChannel) return messageCreate.channel.send("You must be in a voice channel to run this command.")
const permissions = voiceChannel.permissionsFor(messageCreate.client.user)
if (!permissions.has("CONNECT")) return messageCreate.channel.send("You do not have the sufficient permissions to do this.")
if (!permissions.has("SPEAK")) return messageCreate.channel.send("You do not have the sufficient permissions to do this.")
if (!args.length) return messageCreate.channel.send("You must specify some keywords to identify the song you are looking for.")
joinVoiceChannel({
channelId: messageCreate.member.voice.channel.id,
guildId: messageCreate.guild.id,
adapterCreator: messageCreate.guild.voiceAdapterCreator
})
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"})
const player = createAudioPlayer()
const resource = createAudioResource(stream)
async function play() {
await player.play(resource)
connection.subscribe(player)
connection.play(stream, {seek: 0, volume: 1})
.on("finish", () => {
voiceChannel.leave()
})
}
await messageCreate.reply(`:thumbsup: Now playing: ***${video.title}***.`)
} else {
messageCreate.channel.send("No video results found.")
}
}
}
If you really want to keep the play function, you can fix it by calling the function right after defining it.
async function play() {
/*...*/
}
play() // Just add this line here

Music freezes for 1 second when adding a song to the queue then continues playing

My music bot works great but there is a problem that when I add another song to the queue, the currently playing song will freeze for 0.70s - 1s, then will continue playing and add the song earlier in the queue, i want when i add a song to the queue, the song currently playing will continue playing, here is my code in play.js (i don't know where the error comes from)
const { Util, MessageEmbed } = require("discord.js");
const ytdl = require("ytdl-core");
const ytdlDiscord = require("ytdl-core-discord");
const yts = require("yt-search");
const fs = require('fs');
const sendError = require("../util/error")
const sendfact = require("../unti/fact")
module.exports = {
info: {
name: "play",
description: "To play songs",
usage: "<YouTube_URL> | <song_name>",
aliases: ["p"],
},
run: async function (client, message, args) {
let channel = message.member.voice.channel;
if (!channel)return sendError("You need to be in voice channel to use this command!", message.channel);
const permissions = channel.permissionsFor(message.client.user);
if (!permissions.has("CONNECT"))return sendError("I cannot connect to your voice channel, make sure I have [CONNECT] permissions to play!", message.channel);
if (!permissions.has("SPEAK"))return sendError("I cannot speak in this voice channel, make sure I have the [SPEAK] permissions to play!", message.channel);
var searchString = args.join(" ");
if (!searchString)return sendError("There are no songs for me to play yet", message.channel);
const url = args[0] ? args[0].replace(/<(.+)>/g, "$1"): " ";
var serverQueue = message.client.queue.get(message.guild.id);
let songInfo = null;
let song = null;
if (url.match(/^(https?:\/\/)?(www\.)?(m\.)?(youtube\.com|youtu\.?be)\/.+$/gi)) {
try {
songInfo = await ytdl.getInfo(url)
if(!songInfo)return sendError("Can't find the song you want on youtube - is it real?", message.channel);
song = {
id: songInfo.videoDetails.videoId,
title: songInfo.videoDetails.title,
url: songInfo.videoDetails.video_url,
img: songInfo.player_response.videoDetails.thumbnail.thumbnails[0].url,
duration: songInfo.videoDetails.lengthSeconds,
ago: songInfo.videoDetails.publishDate,
views: String(songInfo.videoDetails.viewCount).padStart(10, ' '),
req: message.author
};
} catch (error) {
console.error(error);
return message.reply(error.message).catch(console.error);
}
}else {
try {
var searched = await yts.search(searchString);
if(searched.videos.length === 0)return sendError("Can't find the song you want on youtube - is it real?", message.channel)
songInfo = searched.videos[0]
song = {
id: songInfo.videoId,
title: Util.escapeMarkdown(songInfo.title),
views: String(songInfo.views).padStart(5, ' '),
url: songInfo.url,
ago: songInfo.ago,
duration: songInfo.duration.toString(),
img: songInfo.image,
req: message.author
};
} catch (error) {
console.error(error);
return message.reply(error.message).catch(console.error);
}
}
sendfact("If you want to play a playlist on youtube , try to use `playlist <Playlist url>`", message.channel)
if (serverQueue) {
let thing = new MessageEmbed()
.setAuthor("Song has been added to queue", "https://cdn.discordapp.com/emojis/943352487723827281.gif?size=96&quality=lossless")
.setThumbnail(song.img)
.setColor("WHITE")
.addField("Title", song.url, true)
.addField("Duration", song.duration, true)
.addField("Requested by", song.req.tag, true)
.setFooter(`Views: ${song.views} # ${song.ago}`)
serverQueue.songs.push(song);
return message.channel.send(thing);
}
const queueConstruct = {
textChannel: message.channel,
voiceChannel: channel,
connection: true,
songs: [],
volume: 80,
playing: true,
loop: false
};
message.client.queue.set(message.guild.id, queueConstruct);
queueConstruct.songs.push(song);
const play = async (song) => {
const queue = message.client.queue.get(message.guild.id);
let afk = JSON.parse(fs.readFileSync("./afk.json", "utf8"));
if (!afk[message.guild.id]) afk[message.guild.id] = {
afk: false,
};
var online = afk[message.guild.id]
if (!song){
if (!online.afk) {
sendError("Nothing to play ! If you want to loop , please use `loop`", message.channel)
message.client.queue.delete(message.guild.id);
}
return message.client.queue.delete(message.guild.id);
}
let stream = null;
if (song.url.includes("youtube.com")) {
stream = await ytdl(song.url);
stream.on('error', function(er) {
if (er) {
if (queue) {
queue.songs.shift();
play(queue.songs[0]);
return sendError(`An unexpected error has occurred.\nPossible type \`${er}\``, message.channel)
}
}
});
}
queue.connection.on("disconnect", () => message.client.queue.delete(message.guild.id));
const dispatcher = queue.connection
.play(ytdl(song.url, {quality: 'highestaudio', highWaterMark: 1 << 1 ,type: "opus"}))
.on("finish", () => {
const shiffed = queue.songs.shift();
if (queue.loop === true) {
queue.songs.push(shiffed);
};
play(queue.songs[0])
})
dispatcher.setVolumeLogarithmic(queue.volume / 100);
let thing = new MessageEmbed()
.setAuthor('Started Playing Music!', "https://cdn.discordapp.com/emojis/943352487723827281.gif?size=96&quality=lossless", message.author.name)
.setThumbnail(song.img)
.setColor("WHITE")
.addField("Title", song.title, true)
.addField("Duration", song.duration, true)
.addField("Requested by", song.req.tag, true)
.setFooter(`Views: ${song.views} # ${song.ago}`)
queue.textChannel.send(thing);
};
try {
const connection = await channel.join();
play(queueConstruct.songs[0]);
connection.voice.setSelfDeaf(true);
queueConstruct.connection = connection;
} catch (error) {
console.error(`I could not join the voice channel: ${error}`);
message.client.queue.delete(message.guild.id);
await channel.leave();
return sendError(`I could not join the voice channel: ${error}`, message.channel);
}
},
};

"Cannot read property 'url' of undefined" even though it's already defined

I'm making a Discord music Bot and I'm having trouble with an error saying
TypeError: Cannot read property 'url' of undefined
I tried console logging it and it showed me the url, so I don't understand what is the problem with my code.
Here's my code:
//musicBOT
const Discord = require('discord.js');
const client = new Discord.Client();
const ytdl = require('ytdl-core');
const mcPrefix = '.';
const queue = new Map();
client.on('ready', () => console.log('Music bot ready!'));
client.on('message', async message => {
if(message.author.bot) return;
if(!message.content.startsWith(mcPrefix)) return;
const args = message.content.substring(mcPrefix.length).split(" ");
const serverQueue = queue.get(message.guild.id);
if(message.content.startsWith(`${mcPrefix}play`)) {
const voiceChannel = message.member.voice.channel;
if(!voiceChannel) return message.channel.send("Hang-szobában kell lenned zenelejátszáshoz.");
const permissions = voiceChannel.permissionsFor(message.client.user);
if(!permissions.has('CONNECT')) return message.channel.send("Nincs jogosultságom csatlakozni a hangszobához.");
if(!permissions.has('SPEAK')) return message.channel.send("Nincs jogosultságom megszólalni ebben a hangszobában.");
const songInfo = await ytdl.getInfo(args[1])
const song = {
title: songInfo.title,
url: songInfo.videoDetails.video_url
}
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();
message.channel.send(`${song.title} lejátszása.`)
queueConstruct.connection = connection
play(message.guild, queueConstruct.songs[0])
}catch(e){
console.log(`Hiba csatlakozás közben itt: ${e}`);
queue.delete(message.guild.id)
return message.channel.send(`Hiba volt a csatlakozás közben itt: ${e}`)
}
} else{
serverQueue.songs.push(song)
return message.channel.send(`**${song.title}** hozzáadva a lejátszási listához.`)
}
return undefined
}else if (message.content.startsWith(`${mcPrefix}stop`)) {
if(!message.member.voice.channel) return message.channel.send("Hang-szobában kell lenned ahhoz, hogy leállítsd a zenét.")
if(!serverQueue) return message.channel.send("There is nothing playing")
serverQueue.songs= []
serverQueue.connection.dispatcher.end()
message.channel.send("Sikeresen megálltottad a zenét.")
return undefined
}else if(message.content.startsWith(`${mcPrefix}skip`)){
if(!message.member.voice.channel) return message.channel.send("Hang-szobában kell lenned a skip parancshoz.")
if(!serverQueue) return message.channel.send("There is nothing playing")
serverQueue.connection.dispatcher.end()
message.channel.send("Zene továbbléptetve.")
message.channel.send(`${song.title} játszása.`)
return undefined
}
function play(guild, song) {
const serverQueue = queue.get(guild.id)
if(!serverQueue.songs){
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.log(error)
})
dispatcher.setVolumeLogarithmic(serverQueue.volume / 5)
}
})
//musicBOT
and here is the full error:
const dispatcher = serverQueue.connection.play(ytdl(songInfo.url))
^
TypeError: Cannot read property 'url' of undefined
at play (C:\Users\Levi\Desktop\Discord BOT Javascript\bot.js:97:70)
at StreamDispatcher.<anonymous> (C:\Users\Levi\Desktop\Discord BOT Javascript\bot.js:100:17)
at StreamDispatcher.emit (node:events:388:22)
at finish (node:internal/streams/writable:734:10)
at processTicksAndRejections (node:internal/process/task_queues:80:21)
I started searching on the internet but found nothing about it, I guess my basic javascript knowledge is just not enough.
The empty songs array checking in play function is incorrect:
// This "if" clause will never be run, voice channel won't leave when there's no song
if(!serverQueue.songs){
serverQueue.voiceChannel.leave()
...
}
Fix:
if(serverQueue.songs.length === 0){
...
}

Error wtf UnMute Command: Cannot read property 'id' of undefined

const { MessageEmbed } = require("discord.js");
module.exports = {
name: 'unmute',
async execute (client, message, args) {
let user = message.guild.member(message.mentions.users.first());
let muteRole = message.guild.roles.cache.find(r => r.name === 'Muted');
if (!user.roles.cache.has(muteRole.id)) return message.reply("Is not Muted");
user.roles.remove(muteRole.id);
}
};
This code worked 2 weeks ago and now there is a bug, please help me!
It seems that there isn't any Muted role. The error clearly says Cannot find 'id' of undefined, and the only place I see .id used is on the Muted role.
Just saying, you also need to say where the console says the error is. Just saying, "This is the error" doesn't help.
You may want to use this:
const { MessageEmbed } = require("discord.js")
module.exports = {
name: 'unmute',
async execute(message, args) {
var user_to_mute = message.mentions.user.first()
.catch(err) {
console.error(err)
return message.reply("Could not find user in cache!")
}
var muted_role = message.guild.roles.cache.find(x => x.name == "Muted")
.catch(err) {
console.error(err)
return message.reply("Could not find role in cache!")
}
if (user_to_mute.has(muted_role)) return message.reply("User isn't muted!")
user_to_mute.removeRole(muted_role).catch(console.error)
}
};

Discord.js music bot: TypeError: this.inputMedia.pipe is not a function

I'm writing a music Discord bot using Discord.js. The bot uses ytdl-core, node-opus, and I have installed ffmpeg on my OS (Ubuntu 19.04). When I try to make the bot join a voice channel and start playing a YouTube URL, it throws the following error:
TypeError: this.inputMedia.pipe is not a function
at FfmpegProcess.connectStream (/home/ivan/.../node_modules/discord.js/node_modules/prism-media/src/transcoders/ffmpeg/FfmpegProcess.js:73:21)
at new FfmpegProcess (/home/ivan/.../node_modules/discord.js/node_modules/prism-media/src/transcoders/ffmpeg/FfmpegProcess.js:28:14)
at FfmpegTranscoder.transcode (/home/ivan/.../node_modules/discord.js/node_modules/prism-media/src/transcoders/ffmpeg/Ffmpeg.js:34:18)
at MediaTranscoder.transcode (/home/ivan/.../node_modules/discord.js/node_modules/prism-media/src/transcoders/MediaTranscoder.js:27:31)
at Prism.transcode (/home/ivan/.../node_modules/discord.js/node_modules/prism-media/src/Prism.js:13:28)
at AudioPlayer.playUnknownStream (/home/ivan/.../node_modules/discord.js/src/client/voice/player/AudioPlayer.js:97:35)
at VoiceConnection.playStream (/home/ivan/.../node_modules/discord.js/src/client/voice/VoiceConnection.js:478:24)
at voiceChannel.join.then.connection (/home/ivan/.../commands/play.js:32:47)
at process._tickCallback (internal/process/next_tick.js:68:7)
Here is my code:
const ytdl = require("ytdl-core");
exports.run = (client, message, args, config) => {
return new Promise((resolve, reject) => {
if (args.length !== 1) {
message.channel.send("Play command takes 1 YouTube link.");
reject("Wrong number of arguments");
return;
}
const voiceChannel = message.member.voiceChannel;
if(!voiceChannel) {
message.channel.send("You need to connect to a voice channel first");
reject("Not connected to voice channel");
return;
}
const perms = voiceChannel.permissionsFor(message.client.user);
if (!perms.has("CONNECT")) {
message.channel.send("You need to add the 'connect' permission for this bot");
reject("NO CONNECT PERMISSION");
return;
}
if (!perms.has("SPEAK")) {
message.channel.send("You need to add the 'speak' permission for this bot");
reject("NO SPEAK PERMISSION");
return;
}
const streamOptions = { seek: 0, volume: 1, passes: 2 };
voiceChannel.join()
.then(connection => {
const stream = ytdl(args[0], {filter: 'audioonly'});
const dispatcher = connection.playStream(ytdl, streamOptions);
dispatcher.on("end", reason => {
console.log("reason: " + reason);
voiceChannel.leave();
})
dispatcher.on("error", err => {
console.log(err);
})
})
.catch(err => console.log(err));
});
}
I have tried reinstalling ffmpeg, node and npm, discord.js and node-opus. I have the newest version of Discord.js installed, and ffmpeg version 4.1.3-0ubuntu1. Anyone have any suggestions?
Thanks.
Found the issue, it was in these lines:
const stream = ytdl(args[0], {filter: 'audioonly'});
const dispatcher = connection.playStream(ytdl, streamOptions);
The correct code is
const stream = ytdl(args[0], {filter: 'audioonly'});
const dispatcher = connection.playStream(stream, streamOptions);
Edit: corrected steam to stream

Resources