discord bot doesnt play music - node.js

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

Related

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);
}
},
};

DiscordJS v13 Music Bot

I'm having a problem trying to get my discord bot to play songs.
It is able to enter the voice channel and search for the song, but when it enters it does not play anything, I look at the status of the player and it comes out 'buffering'.
const { joinVoiceChannel, createAudioPlayer, createAudioResource, StreamType, AudioPlayerStatus, NoSubscriberBehavior } = require('#discordjs/voice');
const { Client, Intents, Interaction } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
const ytdl = require('ytdl-core');
const yrS = require('yt-search');
async function vdSearch(cancion){
const vdE = await yrS(cancion);
return vdE.videos.length > 0 ? vdE.videos[0] : null;
}
client.on('messageCreate', async(message) =>{
switch(args[0]){
case 'play':
const vdRepro = await vdSearch(args[1]);
if(!vdRepro){
message.channel.send("No se ha encontrado esa cancion");
}else{
message.channel.send("Reproduciendo: "+ vdRepro.title);
}
//CONEXION
const stream = ytdl(vdRepro.url, { filter:'audioonly' });
const connection = joinVoiceChannel({
channelId: message.member.voice.channel.id,
guildId: message.guild.id,
adapterCreator: message.guild.voiceAdapterCreator
})
var resource = createAudioResource(stream, {inputType:StreamType.Arbitrary,});
const player = createAudioPlayer({
behaviors: {
noSubscriber: NoSubscriberBehavior.Pause,
},
});
player.play(resource);
connection.subscribe(player);
console.log(player.state);
break;
}
})
Does anyone know how I could solve it?
Thanks for taking the time to read
I would recommend that you use "Distube". Its really easy to use and great for Musik Bots.
https://distube.js.org/#/docs/JS-DisTube/v2/class/DisTube
For example the play() command in Distube is distube.play(message, "searchQuery")

Play discord command

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

async function doesn't wait of inside await in nodejs

I am implementing function monthlyRevenue.
Simply, it will return total monthly revenue,and it takes arguments of station array which will make revenues, month and year.
Problem
Inside of this function I have getStationPortion which will fetch the revenue portion of user's.
So I would like to make it return object like this.
stationsPortion = {station1 : 30, station2 : 20}
In the monthlyRevenue
const stationPortions = await getStationPortions(stations)
console.log("portion map", stationPortions //it will be shown very beginning with empty
getStationPortions
const getStationPortions = async (stations) => {
let stationPortions = {}
stations.map(async (value) => {
const doc = await fdb.collection('Stations').doc(value).get()
if (!doc.exists) {
console.log("NO DOC")
} else {
stationPortions[value] = doc.data().salesPortion
console.log(stationPortions) //it will be shown at the last.
}
})
return stationPortions
}
I thought that async function should wait for the result, but it does not.
I am kind of confusing if my understanding is wrong.
Thank you
(by the way, fdb is firebase admin(firestore)
Working code
const getStationPortions = async (stations) => {
let stationPortions = {}
await Promise.all(stations.map(async (value) => {
const doc = await fdb.collection('Stations').doc(value).get()
if (!doc.exists) {
console.log("NO DOC")
} else {
stationPortions[value] = doc.data().salesPortion
console.log(stationPortions)
}
}))
return stationPortions
}
module.exports = router;

"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){
...
}

Resources