This is my code,
The command executes perfectly, The bot joins the voice channel and also sends the name of the song its about to play, but it doesnt play the song in the voice channel.
This is my first time ever asking a question on stackoverflow so dont mind the format and stuff. But I really need help here.
Discord v13 and latest node module.
const ytsearch = require('yt-search');
const Discord = require('discord.js')
const {
joinVoiceChannel,
createAudioPlayer,
createAudioResource,
NoSubscriberBehavior
} = require('#discordjs/voice');
module.exports = {
name: "play",
description: "test command",
async run(client, message, args) {
const voiceChannel = message.member.voice.channel;
if (!voiceChannel) return message.channel.send('Please connect to a voice channel!');
if (!args.length) return message.channel.send('Please Provide Something To Play!')
const connection = await joinVoiceChannel({
channelId: message.member.voice.channel.id,
guildId: message.guild.id,
adapterCreator: message.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)
await player.play(resource);
connection.subscribe(player);
await message.reply(`:thumbsup: Now Playing ***${video.title}***`)
} else {
message.channel.send('No video results found');
}
}
}```
I would suggest you look at the music bot example at #discordjs/voice.
They do a good job of how to extract the stream from ytdl.
I'm currently still learning how this all works but the part that you will want to look at is in the createAudioResource function.
public createAudioResource(): Promise<AudioResource<Track>> {
return new Promise((resolve, reject) => {
const process = ytdl(
this.url,
{
o: '-',
q: '',
f: 'bestaudio[ext=webm+acodec=opus+asr=48000]/bestaudio',
r: '100K',
},
{ stdio: ['ignore', 'pipe', 'ignore'] },
);
if (!process.stdout) {
reject(new Error('No stdout'));
return;
}
const stream = process.stdout;
const onError = (error: Error) => {
if (!process.killed) process.kill();
stream.resume();
reject(error);
};
process
.once('spawn', () => {
demuxProbe(stream)
.then((probe) => resolve(createAudioResource(probe.stream, { metadata: this, inputType: probe.type })))
.catch(onError);
})
.catch(onError);
});
}
Related
const Discord = require("discord.js");
require('dotenv').config();
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus } = require('#discordjs/voice');
const client = new Discord.Client({ intents: ["GUILDS", "GUILD_MESSAGES"], partials: ["CHANNEL"] });
const player = createAudioPlayer();
var channelsToMonitor = ['902193996355485778'];
function joinChannel(channel) {
const connection = joinVoiceChannel({
channelId: channel.id,
guildId: channel.guild.id,
adapterCreator: channel.guild.voiceAdapterCreator,
});
return connection;
}
function playAudio(connection) {
// Subscribe the connection to the audio player (will play audio on the voice connection)
const resource = createAudioResource('./music/', 'alarm.mp3');
resource.volume = 1;
player.play(resource);
connection.subscribe(player);
player.on(AudioPlayerStatus.Playing, () => {
console.log('ALRM');
});
}
client.on('ready', () => {
console.log('ready');
})
client.on('messageCreate', async msg => {
try {
if (channelsToMonitor.indexOf(msg.channel.id) !== -1) {
if (msg.content == 'GOGOGO') {
const guild = client.guilds.cache.get("857332849119723520");
const channel = guild.channels.cache.get("921415774676058152");
if (!channel) return console.error("The channel does not exist!");
var connection = joinChannel(channel);
await playAudio(connection);
}
} else {
if (msg.author.bot) return;
}
} catch (err) {
console.error(err.message);
}
});
client.login(process.env.DISCORD_TOKEN_2);
I have set this up from the docs
And I cannot find why no audio is coming out! The bot joins the channel and says it's playing when I use console.log(player) but for some reason, it is deafened and doesn't play any sound.
Bots now join with self deaf by default. Provide the selfDeaf field to stop this:
const connection = joinVoiceChannel({
channelId: channel.id,
guildId: channel.guild.id,
adapterCreator: channel.guild.voiceAdapterCreator,
selfDeaf: false,
selfMute: false // this may also be needed
})
Basically, i'm coding a discord bot and i'm trying to code a music bot / command. On line 14 whenever ?play is run (the command) i get TypeError: Cannot read property 'voice' of undefined (NOTE: i AM in a voice channel when i run this command) Im using discord js v.12.4 not sure how to check :/ I've gone over some stack overflow questions and they're all saying to update message.member.voiceChannel to message.member.voice.channel. btw i have tried message.member.voiceChannel it returns the same error.
code:
const ytSearch = require('yt-search');
const queue = new Map();
module.exports = {
name: 'play',
aliases: ['skip', 'stop'],
cooldown: 10,
description: 'Advanced music bot',
async execute(message, args, cmd, client, Discord){
const voice_channel = message.member.voice.channel;
if (!voice_channel) return message.channel.send('You need to be in a channel to execute this command!');
const permissions = voice_channel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT')) return message.channel.send('You dont have the correct permissins');
if (!permissions.has('SPEAK')) return message.channel.send('You dont have the correct permissins');
const server_queue = queue.get(message.guild.id);
if (cmd === 'play'){
if (!args.length) return message.channel.send('You need to send the second argument!');
let song = {};
if (ytdl.validateURL(args[0])) {
const song_info = await ytdl.getInfo(args[0]);
song = { title: song_info.videoDetails.title, url: song_info.videoDetails.video_url }
} else {
const video_finder = async (query) =>{
const video_result = await ytSearch(query);
return (video_result.videos.length > 1) ? video_result.videos[0] : null;
}
const video = await video_finder(args.join(' '));
if (video){
song = { title: video.title, url: video.url }
} else {
message.channel.send('Error finding video.');
}
}
if (!server_queue){
const queue_constructor = {
voice_channel: voice_channel,
text_channel: message.channel,
connection: null,
songs: []
}
queue.set(message.guild.id, queue_constructor);
queue_constructor.songs.push(song);
try {
const connection = await voice_channel.join();
queue_constructor.connection = connection;
video_player(message.guild, queue_constructor.songs[0]);
} catch (err) {
queue.delete(message.guild.id);
message.channel.send('There was an error connecting!');
throw err;
}
} else{
server_queue.songs.push(song);
return message.channel.send(`👍 **${song.title}** added to queue!`);
}
}
else if(cmd === 'skip') skip_song(message, server_queue);
else if(cmd === 'stop') stop_song(message, server_queue);
}
}
const video_player = async (guild, song) => {
const song_queue = queue.get(guild.id);
if (!song) {
song_queue.voice_channel.leave();
queue.delete(guild.id);
return;
}
const stream = ytdl(song.url, { filter: 'audioonly' });
song_queue.connection.play(stream, { seek: 0, volume: 0.5 })
.on('finish', () => {
song_queue.songs.shift();
video_player(guild, song_queue.songs[0]);
});
await song_queue.text_channel.send(`🎶 Now playing **${song.title}**`)
}
const skip_song = (message, server_queue) => {
if (!message.member.voice.channel) return message.channel.send('You need to be in a channel to execute this command!');
if(!server_queue){
return message.channel.send(`There are no songs in queue 😔`);
}
server_queue.connection.dispatcher.end();
}
const stop_song = (message, server_queue) => {
if (!message.member.voice.channel) return message.channel.send('You need to be in a channel to execute this command!');
server_queue.songs = [];
server_queue.connection.dispatcher.end();
}```
I'm trying to learn discord.js so I wanted to learn how music bots work. The code below is my shot and everything works but I'm having an issue with my queue.
I cannot get the player.on "finish" or "end" events. So when the song ends I want to call the recursive method that plays a song but I don't know how to get the correct event.
I have tried using player.on(AudioPlayerStatus.Idle) events and making something out of that but that didn't work out so well.
If anyone has any advice to what am I doing wrong or how to improve the code below, I'd be grateful.
const queue = new Map();
module.exports = {
name: "play",
aliases: ["skip", "stop", "leave"],
async execute(message, args, cmd, client, Discord) {
const voiceChannel = message.member.voice.channel;
if (!voiceChannel) {
return message.channel.send({
content: "You need to be in a channel to execute this command!",
});
}
const permissions = voiceChannel.permissionsFor(message.member);
if (!(permissions.has('CONNECT')) || !(permissions.has('SPEAK'))) {
return message.channel.send({
content: "You don't have the correct permissions!",
});
}
const serverQueue = queue.get(message.guild.id);
if (cmd == "play") {
if (!(args.length)) {
return message.channel.send({
content: "Invalid song link!",
});
}
let song = {};
if (ytdl.validateURL(args[0])) {
const songInfo = await ytdl.getInfo(args[0]);
song = { title: songInfo.videoDetails.title, url: songInfo.videoDetails.video_url }
} else {
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) {
song = { title: video.title, url: video.url }
} else {
message.channel.send({
content: `No video results found!`
})
}
}
if (!(serverQueue)) {
const queueConstructor = {
voiceChannel: voiceChannel,
textChannel: message.channel,
connection: null,
player: null,
songs: [],
}
queue.set(message.guild.id, queueConstructor);
queueConstructor.songs.push(song);
try {
const connection = await joinVoiceChannel({
channelId: message.member.voice.channel.id,
guildId: message.member.voice.channel.guild.id,
adapterCreator: message.member.voice.channel.guild.voiceAdapterCreator,
});
queueConstructor.connection = connection;
const player = createAudioPlayer({
behaviors: {
noSubscriber: NoSubscriberBehavior.Pause
}
});
queueConstructor.player = player;
videoPlayer(message.guild, queueConstructor.songs[0]);
} catch (error) {
queue.delete(message.guild.id);
message.channel.send({
content: `There was an error connecting!`
})
throw error;
}
} else {
serverQueue.songs.push(song);
console.log(serverQueue.songs);
return message.channel.send({
content: `${song.title} added to the queue!`
})
}
} else if (cmd == "skip") {
// TODO
} else if (cmd == "leave") {
// TODO
}
}
}
const videoPlayer = async (guild, song) => {
const songQueue = queue.get(guild.id);
if (!(song)) {
songQueue.player.stop();
songQueue.connection.destroy();
queue.delete(guild.id);
return;
}
const stream = await ytdl(song.url, { filter: "audioonly" });
const songStream = await (createAudioResource(stream));
const subscription = songQueue.connection.subscribe(songQueue.player);
const dispatcher = songQueue.player.play(createAudioResource(stream)).on("finish", () => {
songQueue.songs.shift();
songQueue.playing = false;
videoPlayer(guild, songQueue.songs[0]);
songQueue.textChannel.send({
content: `Now playing: ${song.title}`
});
});
}
player.addListener("stateChange", (oldOne, newOne) => {
if (newOne.status == "idle") {
console.log("The song finished");
}
});
Use event stateChange. It called when voice state change from oldOne to newOne. (ex: playing -> idle)
newOne { status: "playing | idle | buffering | ..." }
I'm trying to make a music bot. It joins the channel and the song search is also working but it won't play it. I have tried with .playFile but it still doesn't work. I saw a post where they said you need await when you declare the connection but it doesn't work here. I'm a beginner so sorry if the question is stupid :D
const ytdl = require('ytdl-core');
const ytSearch = require('yt-search');
const Discord=require('discord.js')
const { joinVoiceChannel } = require('#discordjs/voice');
const { getVoiceConnection } = require('#discordjs/voice');
const client = new Discord.Client({ intents: ["GUILDS","GUILD_MESSAGES"] })
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 correct permissins');
if (!permissions.has('SPEAK')) return message.channel.send('You dont have the correct permissins');
if (!args.length) return message.channel.send('You need to send the second argument!');
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 = joinVoiceChannel({
channelId: message.member.voice.channel.id,
guildId: message.guild.id,
adapterCreator: message.guild.voiceAdapterCreator
})
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(`:thumbsup: Now Playing ***Your Link!***`)
return
}
const connection = joinVoiceChannel({
channelId: message.member.voice.channel.id,
guildId: message.guild.id,
adapterCreator: message.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'});
connection.play(stream, {seek: 0, volume: 1})
.on('finish', () =>{
voiceChannel.leave();
});
await message.reply(`:thumbsup: Now Playing ***${video.title}***`)
} else {
message.channel.send('No video results found');
}
}
}
I'm working on my music bot for my discord server. So my code from a technical perspective works, it can play music, and it has queues, but I'm trying to add embeds to the messages, but I keep getting an error message that my message, channel, author is not defined. How do correctly define properties that I need for my embeds to work?
const ytdl = require('ytdl-core');
const ytSearch = require('yt-search');
const queue = new Map();
module.exports = {
name: 'play',
aliases: ('skip', 'stop'),
cooldown: 0,
description: 'Advanced music bot',
async execute(client, message, args, cmd, Discord){
const voice_channel = message.member.voice.channel;
if (!voice_channel) return message.channel.send('You need to be in a channel to execute this command!');
const permissions = voice_channel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT')) return message.channel.send('You dont have the correct permissins');
if (!permissions.has('SPEAK')) return message.channel.send('You dont have the correct permissins');
const server_queue = queue.get(message.guild.id);
if (cmd === 'play'){
if (!args.length) return message.channel.send('You need to send the second argument!');
let song = {};
if (ytdl.validateURL(args[0])) {
const song_info = await ytdl.getInfo(args[0]);
song = { title: song_info.videoDetails.title, url: song_info.videoDetails.video_url }
} else {
const video_finder = async (query) =>{
const video_result = await ytSearch(query);
return (video_result.videos.length > 1) ? video_result.videos[0] : null;
}
const video = await video_finder(args.join(' '));
if (video){
song = { title: video.title, url: video.url }
} else {
message.channel.send('Error finding video.');
}
}
if (!server_queue){
const queue_constructor = {
voice_channel: voice_channel,
text_channel: message.channel,
connection: null,
songs: []
}
queue.set(message.guild.id, queue_constructor);
queue_constructor.songs.push(song);
try {
const connection = await voice_channel.join();
const Discord = require('discord.js');
queue_constructor.connection = connection;
video_player(message.guild, queue_constructor.songs[0]);
} catch (err) {
queue.delete(message.guild.id);
message.channel.send('There was an error connecting!');
throw err;
}
} else{
server_queue.songs.push(song);
newEmbed = new Discord.MessageEmbed()
.setTitle("**Now adding...**")
.setDescription(`${song.title}\n\`Requested by:\` ${message.author}`)
.setColor("#ff0000")
.setThumbnail('https://i.pinimg.com/474x/db/cd/d0/dbcdd0a38ebdb5f7f32cfda2f671dede.jpg')
return message.channel.send
message.channel.send(newEmbed);
}
}
}
}
const video_player = async (guild, song) => {
const song_queue = queue.get(guild.id);
if (!song) {
song_queue.voice_channel.leave();
queue.delete(guild.id);
return;
}
const stream = ytdl(song.url, { filter: 'audioonly' });
const Discord = require('discord.js');
song_queue.connection.play(stream, { seek: 0, volume: 0.5 })
.on('finish', () => {
song_queue.songs.shift();
video_player(guild, song_queue.songs[0]);
});
await song_queue.text_channel.send
newEmbed = new Discord.MessageEmbed()
.setTitle("**Now playing...**")
.setDescription(`${song.title}\n\`Requested by:\` ${message.author}`)
.setColor("#ff0000")
.setThumbnail('https://i.pinimg.com/236x/a1/57/2c/a1572c4306f27fd644ab62199def8aab.jpg')
message.channel.send(newEmbed);
}
I think you are missing the const before the "newEmbed" and you also can't have "newEmbed" twice, as it will return an error. Change it. E.g.
const newEmbed = new Discord.MessageEmbed()
Or you can have
const songList = new Discord.MessageEmbed()
The songList can be anything but just not the same for the other embeds you want.