I'm trying to code a discord bot that send a message to all users in a list. I am having problems using the client.users.fetch(); method on discord.js. The error message says something about DiscordAPIError: Unknown user, Unhandled promise rejection, and DiscordAPIError: Cannot send messages to this user, even though I am in the same guild as the bot.
Here is the code I have so far:
const Discord = require('discord.js');
const client = new Discord.Client();
const ownerId = 'YOUR-ID'
const users = ['YOUR-ID']
client.on('ready', () => {
console.log('Bot is online!');
});
client.on('message', async message => {
if (message.content.includes("test")) {
if (message.author.id == ownerId) {
message.channel.send("ok!")
var userID
var user
for (let i = 0; i < users.length; i++) {
userID = users[i];
user = client.users.fetch(userID.toString(), true);
client.user.send('works');
}
}
}
});
client.login('YOUR-TOKEN');
There are several issues in your code.
Firstly, client.users.fetch(...) is an asynchronous function therefore it requires an await.
Secondly, client.user.send(...) will actually send a message to the bot which is impossible. So you'll want to replace it with either message.channel.send(...) which will send the message in the same channel the message was received in or message.author.send(...) which will send a message to the author of the message.
Below is an example fix:
const Discord = require('discord.js'); // Define Discord
const client = new Discord.Client(); // Define client
const ownerId = 'your-discord-user-id';
const users = [] // Array of user ID's
client.on('ready', () => { // Ready event listener
console.log('Bot is online!'); // Log that the bot is online
});
client.on('message', async message => { // Message event listener
if (message.content.includes("test")) { // If the message includes "test"
if (message.author.id == ownerId) { // If the author of the message is the bot owner
message.channel.send("ok!"); // Send a message
// Define variables
let userID;
let user;
for (let i = 0; i < users.length; i++) { // Loop through the users array
userID = users[i]; // Get the user ID from the array
user = await client.users.fetch(userID.toString()); // Await for the user to be fetched
message.channel.send('works'); // Send a message to tell the message author the command worked
}
}
}
});
client.login('YOUR-TOKEN'); // Login your bot
Related
I am currently developing a Discord bot for replit, and I am able to get it to post and even get it to send an intro message when joining a server, however whenever I try to get it to respond to a command I type it won't respond. The message for the first one client.on guild create works. However the client.on for async message will not work.
This is what I have so far.
const { Client } = require('discord.js');
const client = new Client({ intents: 32767 });
//const Discord = require('discord.js');
const keepAlive = require('./server');
require("dotenv").config();
//const client = new Discord.Client();
//const fetch = require('node-fetch');
const config = require('./package.json');
const prefix = '!';
const guild = "";
client.once('ready', () => {
console.log('Jp Learn Online');
});
// let defaultChannel = "";
// guild.channels.cache.forEach((channel) => {
// if(channel.type == "text" && defaultChannel == "") {
// if(channel.permissionsFor(guild.me).has("SEND_MESSAGES")) {
// defaultChannel = channel;
// }
// }
// })
//defaultChannel.send("This is a test message I should say this message when I join");
//if(guild.systemChannelId != null) return guild.systemChannel.send("This is a test message I should say this message when I join"), console.log('Bot entered new Server.')
// client.on('guildCreate', (g) => {
// const channel = g.channels.cache.find(channel => channel.type === 'GUILD_TEXT' && channel.permissionsFor(g.me).has('SEND_MESSAGES'))
// channel.send("This is a test message I should say this message when I join");
// });
client.on('guildCreate', guild => {
guild.systemChannel.send('this message wil print')
});
client.on('message', async message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/); // This splits our code into to allow multiple commands.
const command = args.shift().toLowerCase();
if (command === 'jhelp') {
message.channel.send('こんにちは、私はDiscordロボットです。始めたいなら、!jhelp タイプしてください。 \n\n Hello I am a discord bot built to help learn the Japanese language! \n\n If you want to access a japanese dictionary type !dictionary \n\n If you would like to learn a random Japanese Phrase type !teachme \n\n If you would like to answer a challenge question type !challenge1 through 5 each different numbered challnege will ask a different question \n (ie. !challenge1) this will ask the first question.')
}
please note. the lower parts of the code are simply commands. That expand further from jhelp I want to know mainly why my second client.on with messages wont work specifically in the context of working with replit.
Thanks for the help in advance.
I expected that maybe changing intents might work, I even went into the discord developer portal, and enabled options, and am still not able to get it working.
After Discord separated out the message intent as a privileged one, the bit field you need to use for all intents has changed. You need to use 131071.
I.e.
const { Client } = require('discord.js');
const client = new Client({ intents: 131071 });
//const Discord = require('discord.js');
const keepAlive = require('./server');
require("dotenv").config();
//const client = new Discord.Client();
//const fetch = require('node-fetch');
const config = require('./package.json');
const prefix = '!';
const guild = "";
client.once('ready', () => {
console.log('Jp Learn Online');
});
// let defaultChannel = "";
// guild.channels.cache.forEach((channel) => {
// if(channel.type == "text" && defaultChannel == "") {
// if(channel.permissionsFor(guild.me).has("SEND_MESSAGES")) {
// defaultChannel = channel;
// }
// }
// })
//defaultChannel.send("This is a test message I should say this message when I join");
//if(guild.systemChannelId != null) return guild.systemChannel.send("This is a test message I should say this message when I join"), console.log('Bot entered new Server.')
// client.on('guildCreate', (g) => {
// const channel = g.channels.cache.find(channel => channel.type === 'GUILD_TEXT' && channel.permissionsFor(g.me).has('SEND_MESSAGES'))
// channel.send("This is a test message I should say this message when I join");
// });
client.on('guildCreate', guild => {
guild.systemChannel.send('this message wil print')
});
client.on('messageCreate', async message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/); // This splits our code into to allow multiple commands.
const command = args.shift().toLowerCase();
if (command === 'jhelp') {
message.channel.send('こんにちは、私はDiscordロボットです。始めたいなら、!jhelp タイプしてください。 \n\n Hello I am a discord bot built to help learn the Japanese language! \n\n If you want to access a japanese dictionary type !dictionary \n\n If you would like to learn a random Japanese Phrase type !teachme \n\n If you would like to answer a challenge question type !challenge1 through 5 each different numbered challnege will ask a different question \n (ie. !challenge1) this will ask the first question.')
}
Yes! its the problem with your intents, for guildMemberAdd/Remove you require GuildMembers intents
This is the code, I want it to write user's name and then auction word (p.s I am new to this)
const Discord = require('discord.js')
const client = new Discord.Client()
const { MessageEmbed } = require('discord.js');
const channel = client.channels.cache.get('889459156782833714');
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`)
})
client.on("message", msg => {
var message = new Discord.MessageEmbed()
.setColor('#FF0000')
.setTitle() // want user's name + "Auction"
.addField('Golden Poliwag', 'Very Pog', true)
.setImage('https://graphics.tppcrpg.net/xy/golden/060M.gif')
.setFooter('Poliwag Auction')
if (msg.content === "d.test") {
msg.reply(message)
}
})
You can access the user's username by using msg.author.tag. So. the way to use the user's tag in an embed would be:
const { MessageEmbed, Client } = require("discord.js");
const client = new Client();
const channel = client.channels.cache.get("889459156782833714");
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on("message", (msg) => {
var message = new Discord.MessageEmbed()
.setColor("#FF0000")
.setTitle(`${msg.author.tag} Auction`)
.addField("Golden Poliwag", "Very Pog", true)
.setImage("https://graphics.tppcrpg.net/xy/golden/060M.gif")
.setFooter("Poliwag Auction");
if (msg.content === "d.test") {
msg.reply(message);
}
});
I suggest you to read the discord.js documentation, almost all you need to interact with Discord API is from there.
You can't control the bot if you don't login to it. Get the bot's token from Developer Portal and login to your bot by adding client.login('<Your token goes here>') in your project.
You can't get the channel if it's not cached in the client. You need to fetch it by using fetch() method from client's channels manager:
const channel = await client.channels.fetch('Channel ID goes here');
P/s: await is only available in async function
message event is deprecated if you are using discord.js v13. Please use messageCreate event instead.
You are able to access user who sent the message through msg object: msg.author. If you want their tag, you can get the tag property from user: msg.author.tag, or username: msg.author.username or even user ID: msg.author.id. For more information about discord message class read here.
The reply options for message is not a message. You are trying to reply the message of the author with another message which is wrong. Please replace the reply options with an object that includes embeds:
msg.reply({
embeds: [
// Your array of embeds goes here
]
});
From all of that, we now have the final code:
const { Client, MessageEmbed } = require('discord.js');
const client = new Client();
client.on("ready", () => {console.log(`Logged in as ${client.user.tag}!`)});
client.on("messageCreate", async (msg) => {
const channel = await client.channels.fetch('889459156782833714');
const embed = new Discord.MessageEmbed()
.setColor('#FF0000')
.setTitle(`${msg.author.tag} Auction`)
.addField('Golden Poliwag','Very Pog',true)
.setImage('https://graphics.tppcrpg.net/xy/golden/060M.gif')
.setFooter('Poliwag Auction');
if (msg.content === "d.test") {
msg.reply({
embeds: [ embed ],
});
}
});
client.login('Your bot token goes here');
Now your bot can reply to command user with an rich embed.
I am making bot to manage my multiple Discord guilds. And I'd like to make confirmation system, like:
User does X thing,
Bot sends message in sufficient channel,
Bot waits for user to react with :thumbdsup: or :thumbsdown: up to 60 seconds
If thumbs up, do A, else - do B. If time is up, do C action
How can I build system like that, due to I have no idea.
Adding and Setting Up the Event Listener
First we start by defining discord.js & adding an event listener:
const Discord = require('discord.js'); //defining discord
const client = new Discord.Client(); //getting your bot
client.on('message', async message => { //when a user sends a message
});
Then you would need to tell the bot what it does after that:
const Discord = require('discord.js'); //defining discord
const client = new Discord.Client(); //getting your bot
client.on('message', async message => { //when a user sends a message
if (message.author.bot) return; //If a bot sent the message we want to ignore it.
if (message.content.toLowerCase() === 'what message your looking for' { //what your looking for (make sure this string is all in lower case)
//what you want the bot to do after the message you are looking for has been sent
}
});
Now, if you want the bot to add the reaction to the message you will do the following:
const Discord = require('discord.js'); //defining discord
const client = new Discord.Client(); //getting your bot
client.on('message', async message => { //when a user sends a message
if (message.author.bot) return; //If a bot sent the message we want to ignore it.
if (message.content.toLowerCase() === 'what message your looking for' { //what your looking for (make sure this string is all in lower case)
await message.react('👍'); //reacting to the message with a thumbs up emoji
await message.react('👎'); //reacting to the message with a thumbs down emoji
}
});
If you wanted the bot to reply to the message use:
const Discord = require('discord.js'); //defining discord
const client = new Discord.Client(); //getting your bot
client.on('message', async message => { //when a user sends a message
if (message.author.bot) return; //If a bot sent the message we want to ignore it.
if (message.content.toLowerCase() === 'what message your looking for' { //what your looking for (make sure this string is all in lower case)
message.channel.send('The bots message here') //what you want the bot to reply with
}
});
Awaiting Reactions
Here it all depends on if you want to await reactions on the bot's message or the user's message.
If you would like to await reactions from the bot's message use:
const Discord = require('discord.js'); //defining discord
const client = new Discord.Client(); //getting your bot
client.on('message', async message => { //when a user sends a message
if (message.author.bot) return; //If a bot sent the message we want to ignore it.
if (message.content.toLowerCase() === 'what message your looking for' { //what your looking for (make sure this string is all in lower case)
message = await message.channel.send('The bots message here') //waiting for the message to be sent
const filter = (reaction, user) => { //filtering the reactions from the user
return (
['👎', '👍'].includes(reaction.emoji.name) && user.id === message.author.id
);
}
message.awaitReactions(filter, { max: 1, time: 60000, errors: ['time'] }) //awaiting the reactions - remember the time is in milliseconds
.then((collected) => {
const reaction = collected.first();
if (reaction.emoji.name === '👍') { //if the reaction was a thumbs up
//A action
reaction.users.remove(message.author.id) //If you wanted to remove the reaction
} else { //if the reaction was a thumbs down
//B action
reaction.users.remove(message.author.id) //If you wanted to remove the reaction
}
}).catch((collected) => { //when time is up
//C action
});
}
});
If you wanted to await message from the user's message you would do the same thing except change:
if (message.content.toLowerCase() === 'what message your looking for' { //what your looking for (make sure this string is all in lower case)
message.channel.send('The bots message here') //sending the message but not awaiting reactions from it
I have a function that send messages, but it doesn't work because it's not inside
client.on('message', msg => {
How can I do?
You can send messages from outside client.on('message'..., All you need is channel ID and then you can simply do:
const myChannel = client.channels.get('CHANNEL_ID');
myChannel.send(`your message here!`);
EDIT
You can use this inside a function by passing it as a parameter:
const myChannel = client.channels.get('CHANNEL_ID');
function myFunc(channel) {
channel.send('MESSAGE');
}
Now you can call your function using myChannel:
myFunc(myChannel);
client.on("message") is an event that will trigger each time a new message is sent in a channel the bot can see. (DMs included.)
To send a message to a channel id, first you have to find the channel using the client.channels collection.
const Discord = require("discord.js");
const Client = new Discord.Client(); // Creating a new Discord Client.
Client.on("ready", () => {
const Channel = Client.channels.get("your channel id"); // Searching the channel in the collection channels.
if (!Channel) {
return console.error("No channel found!"); // If the channels does not exist or the bot cannot see it, it will return an error.
} else {
return Channel.send("Your message to send here!"); // We found the channel. Sending a message to it.
};
}); // Making sure the client is ready before sending anything.
Client.login("your bot token here"); // Logging into Discord with the bot's token.
When a user joins the server, the bot sends a welcome message, i want to take that welcome message's ID and make the bot delete it if the users leaves after he joins. I tried to save the message's id in a variable and make the bot delete the message when the user leaves but without success. I already took a look at the docs, but I really can't understand how to make it.
Define an object to hold the welcome messages by guild and user. You may want to use a JSON file or database (I'd highly recommend the latter) to store them more reliably.
When a user joins a guild...
Send your welcome message.
Pair the the message's ID with the user within the guild inside of the object.
When a member leaves the guild...
Fetch their welcome message.
Delete the message from Discord and the object.
Example setup:
const welcomeMessages = {};
client.on('guildMemberAdd', async member => {
const welcomeChannel = client.channels.get('channelIDHere');
if (!welcomeChannel) return console.error('Unable to find welcome channel.');
try {
const message = await welcomeChannel.send(`Welcome, ${member}.`);
if (!welcomeMessages[member.guild.id]) welcomeMessages[member.guild.id] = {};
welcomeMessages[member.guild.id][member.id] = message.id;
} catch(err) {
console.error('Error while sending welcome message...\n', err);
}
});
client.on('guildMemberRemove', async member => {
const welcomeChannel = client.channels.get('channelIDHere');
if (!welcomeChannel) return console.error('Unable to find welcome channel.');
try {
const message = await welcomeChannel.fetchMessage(welcomeMessages[member.guild.id][member.id]);
if (!message) return;
await message.delete();
delete welcomeMessages[member.guild.id][member.id];
} catch(err) {
console.error('Error while deleting existing welcome message...\n', err);
}
});
To do this you would have to store the id of the welcome message and the user that it is tied to (ideally put this in an object). And when the user leaves you would use those values to delete that message.
Example code:
const Discord = require('discord.js');
const client = new Discord.Client();
const welcomeChannel = client.channels.find("name","welcome"); // Welcome is just an example
let welcomes = [];
client.on('message', (message) => {
if(message.channel.name === 'welcome') {
const welcomeObj = { id: message.id, user: message.mentions.users.first().username };
welcomes.push(welcomeObj);
}
});
client.on('guildMemberRemove', (member) => {
welcomes.forEach(welcome, () => {
if(welcome.user === member.user.username) {
welcomeChannel.fetchMessage(welcome.id).delete();
}
});
});
This only works if the welcome message includes a mention to the user so make sure that's in the welcome message.
Also I can't test this code myself at the moment so let me know if you encounter any problems.