When I run the following script ("node musicbot.js" in cmd) and "!play ytlink" within discord itself, the bot joins the voice channel and logs both the command and the link in the console. Yet, the music does not start playing. I have installed ffmpeg, ytdl-core, and discord.js.
Can someone help me out? I do not know which part is messing it up.
const Discord = require("discord.js");
const ytdl = require("ytdl-core");
const config = require("./config.json");
const bot = new Discord.Client();
let queue = [];
function play(connection, message) {
let audio = ytdl(queue[0], {filter: "audioonly"});
let dispatcher = connection.playStream(audio);
dispatcher.on("end", function() {
queue.shift();
if (queue[0]) play(connection, message);
else {
connection.disconnect();
message.channel.send("The queue has ended");
}
});
}
bot.on("message", function(message) {
if (message.channel.type === "dm") return;
if (!message.content.startsWith(config.prefix) || message.author.bot)
return;
let arguments = message.content.split(" ");
let command = arguments[0].toLowerCase();
arguments.shift();
console.log(command);
console.log(arguments);
if (command == "!play") {
if (!arguments[0]) {
message.channel.send("Please provide a YouTube link!");
message.delete();
return;
}
if (!message.member.voiceChannel) {
message.channel.send("Please join a Voice Channel first!");
message.delete();
return;
}
queue.push(arguments[0]);
message.member.voiceChannel.join()
.then(connection => {
play(connection, message);
});
}
});
bot.on("ready", function() {
console.log("Ready");
});
bot.login(config.token);
Ok, I have two solutions for you. This first one is a block of code I have used and I can say it works from experience.
It requires ffmpeg, opusscript and ytdl:
function play(connection, message){
var server = servers[message.guild.id];
server.dispatcher = connection.playStream(ytdl(server.queue[0], {filter:
"audioonly"}));
server.queue.shift();
server.dispatcher.on("end", function() {
if(server.queue[0]) play(connection, message);
else connection.disconnect();
});
}
This second option which I would highly recommend is a node module that has many more advanced features that are hard to implement such as:
musichelp [command]: Displays help text for commands by this addon, or help for a specific command.
play |: Play audio from YouTube.
skip [number]: Skip a song or multi songs with skip [some number],
queue: Display the current queue.
pause: Pause music playback.
resume: Resume music playback.
volume: Adjust the playback volume between 1 and 200.
leave: Clears the song queue and leaves the channel.
clearqueue: Clears the song queue.
owner: Various owner commands/actions. (W.I.P)
It is easy to install and get started, here is the node page with all the information about installation etc.
Related
Okay so I am trying to make an announcement command for my server, but when I try to run this it says: ReferenceError: msg is not defined
I am not sure on what it is that I am doing incorrectly.
Here is the code in question:
'use strict';
//require discord.js package
const Discord = require("discord.js");
const config = require("./config.json")
//Create an instance of a Discord client
const client = new Discord.Client();
//The ready event is vital, only after this will your bot start reacting and responding
client.on('ready', () => {
console.log('I am ready!');
});
//create an event listener for messages
client.on('message', message => {
if (message.content === 'ping') {
message.channel.send('pong');
}
});
if (msg.content === "^ann"){
let channel = client.channels.cache.get('channel id');
msg.channel.send("What is your announcement? (^cancel to cancel)");
const collector = msg.channel.createMessageCollector(m => m.author.id === msg.author.id, { time: 100000000 });
collector.once('collect', m => {
if (m.content == "^cancel") {
m.author.send("Announcement cancelled.");
return;
} else {
var announcement = m.content;
channel.send(announcement);
msg.channel.send("Announcement made!");
return;
}
});
//Do stuff
client.on("message", function (msg) {
if (msg.content.indexOf("^mirror") === 0) {
let item = new Discord.MessageEmbed()
.setImage(msg.author.displayAvatarURL())
.setColor("#E6E6FA")
.setFooter("OMG! WHEW~");
msg.channel.send(item);
}
})
//Bot Token
client.login('token')}
This is what i have for the code that I am working on
The error appears because you have your code outside the message event. So all the code about the message etc. has to be in the message event.
The second thing, I suggest to create 1 message event. I see you have created 2 message events. That is not a big problem, but it will clean your code en is more effective. Now, if someone sends a message, he will check this message 2 times. I hope I made it a little bit clear!
I'm creating a Discord bot, but have some problems catching the errors that my bot sends.
I'm using a custom command handler, that is working pretty well.
Fs.readFile(`./database/prefixes/prefixes.json`, "utf8", (err: Error, data): void => {
data = JSON.parse(data);
const prefix: string = data[message.author.id] == undefined ? "ma!" : data[message.author.id];
const msg: string = message.content;
const args: string[] = message.content.slice(prefix.length).trim().split(" ");
const cmd: string = args.shift().toLowerCase();
if (!msg.startsWith(prefix)) {
return checkCustomCommands();
}
let ops: {} = {
queue: queue
}
try {
require(checkFolders(cmd)).run(Client, message, args, ops); // maybe catching just there?
Logger.log(`${message.author.tag} just used the ${cmd} power in ${message.guild.name}.`);
} catch (err) {
Logger.log(`The command ${message.author.tag} tried to call in ${message.guild.name} doesen't seem to exist.`);
}
});
function checkCustomCommands() {
let content = JSON.parse(Fs.readFileSync('./database/commands/commands.json', 'utf8'));
try {
if (content[message.guild.id][message.content] == undefined) {
return;
} else {
message.channel.send(content[message.guild.id][message.content]);
}
} catch (err) {
return;
}
}
function checkFolders(command) {
let folders = ["moderation", "fun", "music", "info", "game"];
var files: string[];
var finalPath: string;
folders.forEach(folder => {
files = Fs.readdirSync(`./src/commands/${folder}`);
files.forEach(file => {
if (file.split(".")[0] == command) {
return finalPath = `./../commands/${folder}/${file.split(".")[0]}.js`;
}
});
});
return finalPath;
}
But sometimes, my bot sends various errors that I can't catch into the commands files, resulting in my bot being shutdown. Is there any way to prevent that inside the command handler, or anything I can do to catch these errors?
Thanks a lot, I can provide more code if needed, even though the biggest chunk of the command handler is just there ^
I'm quite late to this, but I feel like I should answer my own question, now that I'm able to do so haha
The main way to catch these errors is by listening to the unhandledRejection event, via Node process.
Here's how I did it:
async function handleRejections() {
process.on("unhandledRejection", (error: Error) => {
const errorEmbed: Discord.MessageEmbed = new Discord.MessageEmbed()
.setDescription("<:no:835565213322575963> An error has been detected... \n" + `\`\`\`${error.stack}\`\`\``)
.setTimestamp()
.setFooter(client.user.username, client.user.displayAvatarURL())
.setColor("DARK_RED")
logError(client, errorEmbed);
});
}
Be sure to call the function at the very beginning of the project code, even before the bot starts.
I personally log these errors into a Discord channel, on my server, so that I can check them easily. That's it! Hope that helps. Keep on coding :D
I want to make my slackbot app to answer at the channel that the user mentioned, without manually writing the channel name inside the code.
-example-
problem : I invited my bot into channel #hello, #hi.I mentioned my bot at Channel #hello writing #mybot hi there, but it only replies to channel #hi which I manually wrote down in my code.
I want my bot to automatically find which channel the message came from, and answer back at the same channel that user mentioned.
Not like the code I wrote bot.postMessageToChannel('everyone', `Chuck Norris: ${joke}`,params);
Here is the link of the module that I used and my code
https://github.com/mishk0/slack-bot-api
const SlackBot = require('slackbots');
const axios = require('axios');
const bot = new SlackBot({
token : "",
name : ""
});
// Start Handler
bot.on('start', () =>{
const params = {
icon_emoji: ':)'
};
bot.postMessageToChannel('everyone', 'Feeling tired??? Have some fun with #Joker!'
, params);
});
// Error Handler
bot.on('error', (err) => console.log(err));
//Message Handler
bot.on('message', (data) => {
if(data.type !== 'message'){
return;
}
console.log(data);
handleMessage(data.text);
});
// Responding to Data
function handleMessage(message){
if(message.includes('chucknorris')){
chuckJoke();
}
else if(message.includes(' yomama')){
yoMamaJoke();
}
else if(message.includes(' random')){
randomJoke();
}
else if(message.includes(' help')){
runHelp();
}
}
// Tell a Chuck Norris Joke
function chuckJoke(){
axios.get('http://api.icndb.com/jokes/random/')
.then(res =>{
const joke = res.data.value.joke;
const params = {
icon_emoji: ':laughing:'
};
bot.postMessageToChannel('everyone', `Chuck Norris: ${joke}`,params);
});
}
From here you will find on message it returns you the data object whith channel id
then
you can use postMessage() from the api you have used
postMessage(id, text, params) (return: promise) - posts a message to channel | group | user by ID,
bot.on('message', (data) => {
bot.postMessage(data.channel, 'Feeling tired??? Have some fun with #Joker!'
, params);
console.log(data);
handleMessage(data.text);
});
I was making a discord.js bot and stumbled upon a problem with playing streams from youtube.
After the first stream finished playing dispatcher errors with "Stream is not generating quickly enough" and won't play any other streams until I restart the bot.
I'm using these modules:
discord.js#11.4.0
ffmpeg#0.0.4
ffmped-binaries#3.2.2-3
opusscript#0.0.6
ytdl-core#0.25.0
I tried installing other versions of ytdl-core but that didn't help me.
Here's my code so far:
const yt = require("ytdl-core");
function play(bot, msg) {
if (msg.guild.queue.songs.length < 1) {
msg.guild.queue.playing = false;
return msg.channel.send("Queue is empty");
}
if (!msg.guild.voiceConnection) {
msg.member.voiceChannel.join().then(con => {
let song = msg.guild.queue.songs.shift();
msg.channel.send(`Playing: **${song.title}**!`);
msg.guild.queue.playing = true;
msg.guild.queue.dispatcher = con.playStream(yt(song.url))
.on("end", reason => {
console.log(reason);
bot.queue[msg.guild.id].dispatcher.stop();
setTimeout(play, 500, bot, msg);
})
.on("error", err => {
console.log(err);
bot.queue[msg.guild.id].dispatcher = null;
setTimeout(play, 500, bot, msg);
});
});
}
}
exports.run = async(bot, msg, args, ops) => {
if (!msg.member.voiceChannel) return msg.channel.send("Connect to a voice channel first!");
if (!args[0]) return msg.channel.send("Specify youtube url first!");
yt.getInfo(args[0], (err, info) => {
if (err) return msg.channel.send(err);
if (!msg.guild.queue) {
msg.guild.queue = {};
msg.guild.queue.playing = false;
msg.guild.queue.songs = [];
msg.guild.queue.dispatcher = null;
}
msg.guild.queue.songs.push({
url: info.video_url,
title: info.title,
requester: msg.author.username
});
if (msg.guild.queue.playing) {
msg.channel.send(`Added **${info.title}** to queue list!`);
} else {
play(bot, msg);
}
});
}
I guess easiest fix would be to use discord.js master / v12-dev wich can be installed by doing npm i discordjs/discord.js the master version has a full rewrite of the Voice Functions, wich of course has some breaking changes with it, but overall the issue with stream is not generating fast enough from ytdl is fixed in master.
i have problem with createReceiver. I have code:
client.on('message', message => {
// Voice only works in guilds, if the message does not come from a guild,
// we ignore it
if (!message.guild) return;
if (message.content === '/q') {
// Only try to join the sender's voice channel if they are in one themselves
const voiceChannel = message.member.voiceChannel;
if (message.member.voiceChannel) {
message.member.voiceChannel.join()
.then(connection => { // Connection is an instance of VoiceConnection
connection.on('error', console.error);
// const dispatcher = connection.playFile('C:/Denwer/ddradio/lyubov.mp3');
connection.on('speaking', (user, speaking) => {
if(speaking) {
const receiver = connection.createReceiver();
const stream = receiver.createPCMStream(user);
stream.on('data', chunk => {
console.log(chunk.length);
});
}
});
})
.catch(console.log);
} else {
message.reply('');
}
}
})
console.log(chunk.length); working only when playing music, those. only when the bot speaking. He does not hear other members. Please tell me what the problem is
I had this same problem, I don't know how to completely fix it forever, but if you play a short audio file, like a beep, when the bot joins the channel, your code should work.