discord.js client.user.setPresence() breaks bot - javascript

My bot currently runs fine. I decided to add a 'playing ' status to it. This is the relevant code:
// Import the discord.js modules required
const Discord = require('discord.js');
// Create an instance of a Discord client
const client = new Discord.Client();
// Load config properties from 'config.json'
const config = require("./config.json");
const contest = config.contest;
// Set bots status to playing 'contest' defined in 'config.json'
client.user.setPresence({
game:{
name:contest
},
status:'online'
});
In 'config.json':
{
"contest": "Example Game"
}
When I add this, the bot no longer works, and appears offline. Any ideas?
EDIT:
Source of the information:
https://discord.js.org/#/docs/main/stable/class/ClientUser?scrollTo=setPresence
In the example section:
// Set the client user's presence
client.user.setPresence({ game: { name: 'with discord.js' }, status: 'idle' })
.then(console.log)
.catch(console.error);

You need to read the config, instead of
const config = require(...)
You need
const fs = require("fs");
const config = JSON.parse(fs.readFileSync("config.json"));
const contest = config.contest;
Then
game:{
name:contest
}

Figured it out - this needs to be placed inside an event, otherwise it's just floating code. For example, I placed this inside a
client.on('ready) event.

Related

problem trying to send a client.reply as an embed Message with discord.js

actually i´m working and learning about discord.js and node.js to make a bot, but i have a simple issue, and i don´t know why the embed messages doesn´t work, i tried with the documentarion examples and code of other devs, but in all cases when i try to send the message to a channel, using client.reply(embed) throws me an error saying me that can send an empty message.
i´m using the last version of discord.js (v13.3.1) and i´m using the basic documentation event and the command handlers (works perfectly if i don´t try to send embeds).
This is my index.js and my help.js files:
//This is my index.js i don´t have problem with this but i include it if there are an issue related with this topic.
const fs = require('fs');
const { Client, Collection, Intents } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
const { token } = require('./config.json');
client.commands = new Collection();
const commandFiles = fs.readdirSync('./Commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./Commands/${file}`);
client.commands.set(command.data.name, command);
}
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
return interaction.reply({ content: 'Parece que ha ocurrido algun problema con el comando.', ephemeral: true });
}
});
const eventFiles = fs.readdirSync('./Events').filter(file => file.endsWith('.js'));
for (const file of eventFiles) {
const event = require(`./Events/${file}`);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
client.login(token);
Now the help.js , this is going to be a Command, but i don´t wanna only to code the commands using the SlashCommands, because of it i´m triying to create this as an event:
//This is the help command using an event
const { clientId } = require("../config.json");
const { MessageEmbed } = require("discord.js");
//testx is going to store the embed message
const testx = new MessageEmbed().setTitle('Test').setDescription('Test');
module.exports = {
name: 'messageCreate',
execute(client) {
//This condition determines if isn´t a message of the bot, and if the written command is !!help
if (client.author.id !== clientId && client.content === '!!help') {
//if the condition is true, send the embed message
//client.reply(testx); //the problem is here.
console.log(testx);
}
},
};
And this is the error i got from the terminal:
DiscordAPIError: Cannot send an empty message
at RequestHandler.execute (C:\Users\ //...and more info of my dirs
if i print the testx const in my console, i can see the two values i setted in the const filled with the text "Test", i don´t know why isn´t work or what i need to take this to work.
Thanks and i appreciate any help.
In V13, embeds must be sent differently.
client.reply({embeds: [testx]});
I also recommend editing client to interaction in your command files as it may be misleading, or to actually pass the client and interaction, as you'll most likely need to access the client at some point.
Also, you seem to be confusing interactions with messages.
Interactions do not have an author property, you must use user or member.
They also do not have a content property, to get an argument you must use interaction.options
You also, as far as I can see, are not actually deploying your commands. It looks like you've merged the V12 and V13 command handler tutorial together. I reccomend reading this tutorial again, and making sure you're doing it properly for V13.

Importing variables from other files

I am trying to import a variable from one of my files (File 1) and use it in File 2. I have imported File 2 into File 1 but I am receiving error. My channel ID is correct, in this case you would have to choose the channel so the channel ID is not the issue here.
TypeError: setr.send is not a function
File 1
const Discord = require("discord.js");
const axios = require("axios");
let config = require("../config.json");
module.exports = {
name: "setrestart",
description: "sets the restart channel",
async execute(message, args) {
const perm = new Discord.MessageEmbed()
.setDescription(":x: You do not have permission to use this command.")
.setColor("#E74C3C");
if (!message.guild.me.hasPermission("ADMINISTRATOR"))
return message.channel.send(perm);
if (message.author.id !== "ID")
return message.channel.send(perm);
const channelx =
message.mentions.channels.first() ||
message.guild.channels.cache.find((c) => c.id === args[0]);
if (!channelx)
return message.channel.send(
`:x: Please specify the channel where server restarts will go!`
);
message.reply(`All server restart logs will now go to ${channelx}.`)
},
};
File 2
const Discord = require("discord.js");
const axios = require("axios");
let config = require("../config.json");
let setr = require("./setrestart"); // This is importing file 1
module.exports = {
name: "restart",
description: "send a restart message in status channel",
async execute(message, args) {
const perm = new Discord.MessageEmbed()
.setDescription(":x: You do not have permission to use this command.")
.setColor("#E74C3C");
if (!message.guild.me.hasPermission("ADMINISTRATOR"))
return message.channel.send(perm);
if (message.author.id !== "ID")
return message.channel.send(perm);
const restart = new Discord.MessageEmbed()
.setTitle(" Server Restarted! ")
.setDescription(`F8 connect to ${config.SERVER_URL} `)
.setColor("RANDOM")
.setTimestamp()
.setFooter(`${config.SERVER_LOGO}`);
setr.channelx.send(restart) // This does not work.
},
};
Help is much appreciated.
Edit: I left out the most crucial thing about what I am trying to import.
I am trying to import channelx which is in File 1 and I am trying to use the variable in File 2.
Output
User: /setrestart #channel
Bot: All server restart logs will now go to ${channelx}.
User: /restart
Bot: Embed sent in channelx
The variable channelx is accessible only in the function scope of execute(), you can't import it. Basically after the function goes out of scope the variable is lost. Use a global object, note that the object is destroyed when the program exits. So if you are trying to make some kind of bot's configuration, you want to save the object to a file.
Here is an example of how to properly implement what you are trying to do.
File 1 (file1.js):
// ... Load storage from a JSON file ...
const storage = {};
module.exports = {
name: "setrestart",
description: "sets the restart channel",
async execute(message, args) {
// ... Permission checking ...
const channelx = message.mentions.channels.first() ||
message.guild.channels.cache.find((c) => c.id === args[0]);
if (!channelx) {
return message.channel.send(
`:x: Please specify the channel where server restarts will go!`
);
}
// Store restart channel id per guild
storage[message.guild.id] = channelx.id;
message.reply(`All server restart logs will now go to ${channelx}.`);
// ... Write to the storage JSON file and update it with new data ...
},
};
module.exports.storage = storage;
File 2 (file2.js):
const Discord = require("discord.js");
const file1 = require("./file1.js");
module.exports = {
name: "restart",
description: "send a restart message in status channel",
async execute(message, args) {
// ... Permission checking ...
const restart = new Discord.MessageEmbed()
.setTitle(" Server Restarted! ")
.setColor("RANDOM")
.setTimestamp();
const channelId = file1.storage[message.guild.id];
// If there is no restart channel set, default to the system channel
if (!channelId) channelId = message.guild.systemChannelID;
const channel = await message.client.channels.fetch(channelId);
channel.send(restart);
},
};
Note that I have remove some parts of your code, to make it work on my machine.
Using discord.js ^12.5.3.
I am pretty sure you can't use the module.exports in that way. You should just add the channelx to the exports instead.
using this.channelx = channelx.
This is not how importing and exporting works. Your channelx variable is defined within the execution of a function, and you are not returning it.
I am not sure how the whole Discord API works and what are the shapes that get returned, but you should be able to do something like this:
File 1
module.exports = {
name: "setrestart",
description: "sets the restart channel",
async execute(message, args) {
// ... everything as per your file
message.reply(`All server restart logs will now go to ${channelx}.`);
return channelx;
},
};
File 2
module.exports = {
name: "restart",
description: "send a restart message in status channel",
async execute(message, args) {
// ... everything the same as per your file
const channelx = await setr.execute(message, args);
channelx.send(restart);
},
};
Basically, what is happening here is that the first module exposes a function that figures out your target channel and then returns it.
Once you return it, you can do whatever you want with that.
Please be aware that your first function might not need to be async as you don't have any await instruction.
Read more about scope: https://developer.mozilla.org/en-US/docs/Glossary/Scope

JS Discord buttons error : 'Cannot send empty message'

Hi I'm making a Javascript based Discord bot, and I really wanted to implement the new Discord Buttons feature, the problem is, even using the documentation examples, I get the same error, again and again :
(node:6184) UnhandledPromiseRejectionWarning: DiscordAPIError: Cannot send an empty message
Here is the code (I am using module.exports with separated files for each commands) :
const { MessageButton } = require('discord-buttons')
module.exports = {
name: 'invite',
descritipion: 'test command',
async execute(client, message, args) {
let button = new MessageButton()
.setStyle('url')
.setURL('https://npmjs.com/discord-buttons')
.setLabel('Click me !')
await message.channel.send('Hey, I am powered by npm discord-buttons : https://npmjs.com/discord-buttons');
await message.channel.send(button);
}
}
You cannot just send a button on its own. Instead, try adding the button to the previous message so they both get sent in one message as shown below
The official documentation for this is here
// Replace these
const { MessageButton } = require('discord-buttons')
await message.channel.send('Hey, I am powered by npm discord-buttons : https://npmjs.com/discord-buttons');
await message.channel.send(button);
// With these
const { MessageButton, MessageActionRow } = require('discord-buttons')
await message.channel.send('Hey, I am powered by npm discord-buttons : https://npmjs.com/discord-buttons', {
component: new MessageActionRow().addComponent(button)
});
Also, did you forget to initialize DiscordButtons? Do it when you initialize your discord bot
// Where you initialized your discord bot
const bot = new Discord.Client()
// Add this line
require("discord-button")(bot)

Sending more then one mp4 attachment

I'm trying to create a bot where it sends song snippets, and I am wondering how I would go about sending more than one mp4 with a single command.
const Discord = require('discord.js');
const fs = require('fs');
const { Client, MessageAttachment } = require('discord.js');
const config = require('./config.json');
const { prefix, token } = require('./config.json');
const client = new Client();
const { MessageEmbed } = require('discord.js');
client.commands = new Discord.Collection();
const { Menu } = require('discord.js-menu')
const EventEmitter = require('events');
const { content, author, channel } = message
if (author.bot) {
return const embeds = {
[`${prefix}snip attention`]: {
title: 'attention whore prod. fortune swan',
attachmentPath: './ericsnip/attention_whore/attention.mp4',
[`${prefix}snip attention`]: {
title: 'attention whore prod. fortune swan',
attachmentPath: './ericsnip/attention_whore/attw.mp4',
},
}```
This is what I currently have, I tried to experiment by having the bot go through the file and to send every file that ends with .mp4
[`${prefix}snip hot seat`]: {
title: 'hot seat prod. Alice Gas',
attachmentPath: {const :musicFiles = fs.readdirSync('./ericsnip/hot_seat/').filter(file => file.endsWith(".mp4")),
}
},
But now it doesn't even send anything.
If you take a look at the discord.js documentation, and go to the message options, it tells you that you can provide an array of file options to the message, which means you can attach multiple files.
It is also outlined at the <Channel>.send() method in the documentation.
For example, to send multiple attachments in a message you can do something like:
<Channel>.send({
files: [{
name: "file name here",
attachment: "./path/to/attachment"
},
{
name: "file name here 2",
attachment: "./path/to/attachment_2"
}]
});
I suggest you try relying on the documentation a little more in future. Once you get the hang of it, it is really easy to understand and find what you're looking for, and it gives you all your discord.js related answers.

Google cloud dialogflow intent detection nodejs example not working

I am trying to implement a very simple dialogflow agent integration with nodejs.
Here is what I did so far
I followed the code from Intent detection
I added the service account private key file .json to my server.
I added the environment variable GOOGLE_APPLICATION_CREDENTIALS with the path to my .json private key file.
Here is the code I am trying to run right now:
require('dotenv').config()
const projectId = 'gg-chatbot-216808';
const sessionId = 'quickstart-session-id';
const query = 'hello';
const languageCode = 'en-US';
// Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient();
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
};
// This prints the private key path correctly.
console.log(process.env.GOOGLE_APPLICATION_CREDENTIALS);
// Send request and log result
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
})
.catch(err => {
console.error('ERROR:', err);
});
Then I get this error in the console when I run this file
Auth error:Error: invalid_user: Robot is disabled.
ERROR: { Error: 14 UNAVAILABLE: Getting metadata from plugin failed with error: invalid_user: Robot is disabled.
at Object.exports.createStatusError (/var/www/html/google_auth/node_modules/grpc/src/common.js:87:15)
at Object.onReceiveStatus (/var/www/html/google_auth/node_modules/grpc/src/client_interceptors.js:1188:28)
at InterceptingListener._callNext (/var/www/html/google_auth/node_modules/grpc/src/client_interceptors.js:564:42)
at InterceptingListener.onReceiveStatus (/var/www/html/google_auth/node_modules/grpc/src/client_interceptors.js:614:8)
at callback (/var/www/html/google_auth/node_modules/grpc/src/client_interceptors.js:841:24)
code: 14,
metadata: Metadata { _internal_repr: {} },
details: 'Getting metadata from plugin failed with error: invalid_user: Robot is disabled.' }
i also faced a similar issue for my angular bot.
What i did was, instead of using using the google_credentials from the json file, i created an object with private_key,client_email {these values can be taken from the service account private key file .json}, and passed the object while setting up the session client.
var config = {
credentials: {
private_key: "YOUR_PRIVATE_KEY",
client_email: "YOUR_CLIENT_EMAIL"
}
}
const sessionClient = new dialogflow.SessionsClient(config);
note: do copy the full private_key string from .json. It will start as "-----BEGIN PRIVATE KEY-----\n......" .
Also, in GCP go to the project->IAM then try setting role for the service as DIALOGLOW API ADMIN. Check if this works.
If this has not been resolved yet , the solution is to provide "fileKey" inside sessionClient.
const sessionClient = new dialogflow.SessionsClient({
fileKey:" path of your credentials.json file"
});
or
let filePath = process.env.GOOGLE_APPLICATION_CREDENTIALS ="Location of credentials file".
const sessionClient = new dialogflow.SessionsClient({
fileKey:filePath
});
this will even work if there is no system env variable is set as GOOGLE_APPLICATION_CREDENTIALS.
Hope this is helpful.

Categories

Resources