I want to edit the message over and over again.
So I made variable
this.msgRef = await channel.send({ embeds: [embedMessage] });
If I want to edit I use
this.msgRef.edit(...)
If the bot for some reason disconnects, he will lose msgReference.
Because of that, I saved it to DB.
How to create a message again because Message (object) in Discord.JS have a private constructor?
If you want to get the message again, you can simply fetch the channel's messages every time you bot connects (on the ready event for example) like so
client.on('ready', () =>{
const messages = await channel.messages.fetch()
client.msgRef = messages.find(msg => msg.author.id === client.user.id
&& msg.embeds[0]
// Etc.. Add as many conditions to make sure you choose the right message
);
})
This way, use client.msgRef.edit(...) whenever you want.
Related
There are a lot of to ban a user in a server, you can do it manually or with another bot. I want my bot to scan a banlist, and if someone will get banned, it will send a message "user (id) has been banned
I started writing smt but now, I had no idea what can I do to check it.
EDIT: It's working now, but it still need to find this user id.
client.on('guildBanAdd', message => {
client.user.cache.find() //idk how to define it
const channel1 = client.channels.cache.find(channel => channel.id === "158751278127895");
channel1.send('12512');
})
You don't have to fetch bans because the guildBanAdd event parses a GuildBan object,which als includes a User object.
client.on('guildBanAdd', ban => {
console.log(ban.user.username); // Username
})
message.channel won't work because there isn't a message object.
If you want to get the executor (moderator) who performed the ban, kick etc.
There is a good guide for this Working with Audit Logs
I have this verification system on my server, in which a new member must react to a message to obtain a role that gives permission to see the other channels. So, I wanted to make my bot send a message on a specific channel, greeting them, only when a member gets a specific role (verified)
The problem is: anyone can react in the message to get the verified role over and over again, causing the bot to spam, and I still haven't figured out a way to make this welcome message be sent only once per user
Here is my code:
client.on('guildMemberUpdate', (oldMember, newMember) => {
const channel = client.channels.cache.get('channelID');
// If the role(s) are present on the old member object but no longer on the new one (i.e role(s) were removed)
const removedRoles = oldMember.roles.cache.filter(role => !newMember.roles.cache.has(role.id));
if (removedRoles.size > 0) console.log(`The roles ${removedRoles.map(r => r.name)} were removed from ${oldMember.displayName}.`);
// If the role(s) are present on the new member object but are not on the old one (i.e role(s) were added)
const addedRoles = newMember.roles.cache.filter(role => !oldMember.roles.cache.has(role.id));
if (addedRoles.size > 0){
if (newMember.roles.cache.some(role => role.name === 'teste')) {
let embed = new Discord.MessageEmbed()
.setTitle("♡﹕welcome!")
.setDescription("lalalala")
.setColor("#FFB6C1")
.setThumbnail("https://cdn.discordapp.com/attachments/806974794461216813/817737054745526304/giffy_2.gif")
channel.send(`Welcome ${oldMember.user}`, embed)
}
console.log(`The roles ${addedRoles.map(r => r.name)} were added to ${oldMember.displayName}.`);
}
});
The code you have added to the guildMemberUpdate event listener is being used to send a welcome message when a verified role is added to a member. It is not running any checks to see if the member has already triggered a welcome message.
It sounds like when a member removes their reaction from the message, it also removes their verified role. You should look at where in your code you are removing roles, and change it so the verified role isn't removed after being added.
If this isn't possible, then consider saving a state in a file or database that can be checked before sending a welcome message.
I'm trying to make a starboard code with my bot, and everything else is working good. But I'm trying to make it to where the bot ignores reactions from the author of the actual message.
This is my current code:
client.on('messageReactionAdd', (reaction_orig, message, user) => {
if (message.author.id === reaction_orig.users.id) return
manageBoard(reaction_orig)
})
It returns the following error:
if (message.author.id === reaction_orig.users.id) return;
^
TypeError: Cannot read property 'id' of undefined
The problem is that messageReactionAdd takes two parameters; the message reaction as the first one, and the user that applied the emoji as the second one. When you write reaction_orig, message, user, reaction_orig is the reaction (which is correct), but message is the user who reacted as it's the second parameter. The user variable will be undefined.
Another issue is that reaction_orig.users returns a ReactionUserManager that doesn't have an id property. Luckily, the user is already passed down to your callback so you can use its ID.
Also, reaction_orig has a message property, the original message that this reaction refers to so you can get its authors' ID from it.
You can change your code to this to work:
client.on('messageReactionAdd', (reaction_orig, user) => {
if (reaction_orig.message.author.id === user.id) {
// the reaction is coming from the same user who posted the message
return;
}
manageBoard(reaction_orig);
});
However, the code above only works on cached messages, ones posted after the bot is connected. Reacting on older messages won't fire the messageReactionAdd event. If you also want to listen to reactions on old messages you need to enable partial structures for MESSAGE, CHANNEL and REACTION when instantiating your client, like this:
const client = new Discord.Client({
partials: ['MESSAGE', 'CHANNEL', 'REACTION'],
});
You can check if the message is cached by e.g. checking if its author property is not null. If it's null, you can fetch the message. Now, you have both the message author and the user who reacted, so you can compare their IDs:
// make sure it's an async function
client.on('messageReactionAdd', async (reaction_orig, user) => {
// fetch the message if it's not cached
const message = !reaction_orig.message.author
? await reaction_orig.message.fetch()
: reaction_orig.message;
if (message.author.id === user.id) {
// the reaction is coming from the same user who posted the message
return;
}
// the reaction is coming from a different user
manageBoard(reaction_orig);
});
Try doing this :
client.on('messageReactionAdd', (reaction, user) => {
if (!reaction.message.author.id === user.id){
//Do whatever you like with it
console.log(reaction.name)
}
});
Note: The message must be cached. For that you'll need to do this
Client.channels.cache.get("ChannelID").messages.fetch("MessageID");
I'm guessing you're using discord.js v12
I've a problem with a reaction reply System.
I want that when a user adds a reaction, that replies to a message, except that when the bot reboots it is no longer detected by the bot.
Do you know how to fix this problem?
Here is my current code :
bot.on("messageReactionAdd", function(messageReaction, user){
if(messageReaction.message.content === "Message"){
if(user.bot){return}
messageReaction.message.reply("It works.")
}
})
bot.on("message", function(message){
if(message.content.startsWith(prefix + "test")){
message.delete()
message.member.createDM().then(m => m.send("Message").then(m => m.react("✅")))
}
}
on the latest version of discord.js, you can use the Partial Events to accomplish this.
According to the doc (https://discord.js.org/#/docs/main/master/topics/partials):
Partials allow you to receive events that contain uncached instances, providing structures that contain very minimal data. For example, if you were to receive a messageDelete event with an uncached message, normally Discord.js would discard the event. With partials, you're able to receive the event, with a Message object that contains just an ID.
What you need to do is
const Discord = require('discord.js');
// add "partials" in the bot options to enable partial events
const client = new Discord.Client({"partials": ['CHANNEL', 'MESSAGE']});
[...]
client.on("messageReactionAdd", async function(messageReaction, user){
// fetch message data if we got a partial event
if (messageReaction.message.partial) await messageReaction.message.fetch();
if(messageReaction.message.content === "Message"){
if(user.bot){return}
messageReaction.message.reply("It works.")
}
})
Doing this, you must be careful on your client.on("message", ...) calls, to avoid accessing data or method that are not available.
there is a boolean message.partial that you can use to discard partial message when you don't need them.
I'm trying to create a command that allows users to create their password following prompts through DM. I'm able to send a message to the user, but not able to read a message sent back with a MessageCollector because I cannot find a way to reference the DM channel.
I have tried using another instance of bot.on("message", message) here, but that creates a leak in the system causing the second instance to never disappear.
I also can't let users use a command say !CreatePassword *** because this function is linked with many others in a strict order.
Maybe I'm doing something fundamentally wrong, or approaching the problem in a bad way, but I need a way to reference a DM channel.
This is the best iteration of my code so far.
function createAccount(receivedMessage, embedMessage)
{
const chan = new Discord.DMChannel(bot, receivedMessage.author);
const msgCollector = new Discord.MessageCollector(chan , m => m.author.id == receivedMessage.author.id);
msgCollector.on("collect", (message) =>
{
// Other Code
msgCollector.stop();
// Removing an embed message on the server, which doesn't have a problem.
embedMessage.delete();
})
}
I can show the rest of my code if necessary.
Thank you for your time. I've lost an entire night of sleep over this.
I would do it like this (I'll assume that receivedMessage is the message that triggered the command, correct me if I'm wrong)
async function createAccount(receivedMessage, embedMessage) {
// first send a message to the user, so that you're sure that the DM channel exists.
let firstMsg = await receivedMessage.author.send("Type your password here");
let filter = () => true; // you don't need it, since it's a DM.
let collected = await firstMsg.channel.awaitMessages(filter, {
maxMatches: 1, // you only need one message
time: 60000 // the time you want it to run for
}).catch(console.log);
if (collected && collected.size > 0) {
let password = collected.first().content.split(' ')[0]; // grab the password
collected.forEach(msg => msg.delete()); // delete every collected message (and so the password)
await firstMsg.edit("Password saved!"); // edit the first message you sent
} else await firstMsg.edit("Command timed out :("); // no message has been received
firstMsg.delete(30000); // delete it after 30 seconds
}