So I've been trying to make a command for my discord bot in which my bot should write the name of the target (the person I'm mentioning) in an embed, but unfortunately, nothing has been working.
bot.on("message", (msg) => {
if (msg.content === "R!kill") {
const embed = new Discord.MessageEmbed();
const yoyoyo = msg.author.username;
const target = msg.mentions.members.first();
embed.setTitle(`**OKAY, LES KILL ${target}**`);
embed.setImage("https://i.redd.it/ijh28d8tw0d11.jpg"), embed.setColor("RANDOM"), embed.setFooter(`mission complete`), msg.channel.send(embed);
}
});
I have even tried changing const target = msg.mentions.members.first(); to const target = msg.mentions.members.first.username(); but it's still not working.
If you want to mention someone in the message along with the command, the content of the message (Message.content) won't be equal to only R!kill.
It will be something like R!kill <#!524243315319898133>. With the number being the id of the user you mentioned.
You more likely want to check if the content .startsWith() the command. (As Tyler2P said in their comment.)
And to get a username of the user, you can use GuildMember.user, which has property username. In your case, target is an instance of GuildMember.
if (msg.content.startsWith("R!kill")) {
const embed = new Discord.MessageEmbed();
const target = msg.mentions.members.first();
// Add check if no one is mentioned, we return from the function
if (!target) {
msg.channel.send("Who should I kill?");
return;
}
embed.setTitle(`**OKAY, LES KILL ${target.user.username}**`);
embed.setImage("https://i.redd.it/ijh28d8tw0d11.jpg"), embed.setColor("RANDOM"), embed.setFooter(`mission complete`), msg.channel.send(embed);
}
msg.mentions.members.first(); returns a <GuildMember> object, from which you can access its #displayName property to get its respective guild member name. So transform that into: msg.mentions.members.first().displayName.
The main problem is that you put only target, when you should obtain first the user, and then the username, as the following: target.user.username
bot.on("message", (msg) => {
if (msg.content === "R!kill") {
if (!target) return; // If no mention return.
const embed = new Discord.MessageEmbed();
const yoyoyo = msg.author.username;
const target = msg.mentions.members.first();
embed.setTitle(`**OKAY, LES KILL ${target.user.username}**`);
embed.setImage("https://i.redd.it/ijh28d8tw0d11.jpg"), embed.setColor("RANDOM"), embed.setFooter(`mission complete`), msg.channel.send(embed);
}
});
Related
Edit: I found the issue. I was checking if a user already has the role and was jumping out of the function call if we were attempting to remove a role they did not have. The function checked the cache, which was likely what was not being updated, and removing the check altogether has resolved the issue. I'll leave this here in case anyone else creates this problem for themselves in the future :)
I am trying to code a Discord bot with DiscordJS that allows users to react to a specific message with a specific emoji to have roles assigned or removed. Currently, reacting to the tracked message with the appropriate emoji assigns the role as expected every time. The error is that when a user with the assigned role removes their emoji reaction from the message, it does not remove the role until they react/unreact a second time.
Here is the code in my index.js that handles running events. This calls messageReactionAdd.js and messageReactionRemove.js to listen for their corresponding events.
const fs = require('node:fs');
const { Client, Intents, Collection } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MESSAGE_REACTIONS], partials: ['MESSAGE', 'CHANNEL', 'REACTION']});
// Handle Events
for (const file of eventFiles){
const event = require(`../src/events/${file}`);
if (event.once){
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
An example of my messageReactionAdd.js. There is also a messageReactionRemove.js file that mirrors this except its name is messageReactionRemove and calls the applyRemoveRole helper function with false. These listeners check to see if the message being reacted to is listed in our trackedRoleMessages object, which stores the message id and other data as key/value pairs.
const trackedRoleMessages = require('../util/trackedRoleMessages');
const applyRemoveRole = require('../util/applyRemoveRole');
module.exports = {
name: 'messageReactionAdd',
execute(reaction, user){
const messageID = reaction.message.id;
if (trackedRoleMessages[messageID]){
applyRemoveRole(reaction, user, true);
}
},
};
The applyRemoveRole.js helper function that handles the applying and removing of roles from users when they react to a message we are listening for. The direction param is a boolean that distinguishes between which event we're responding to, add or remove (true or false). The roles object stores emoji unicode values and role ID's as key/value pairs to form an association between them.
const roles = require('./roles');
/*
param1 reaction: reaction object
param2 user: user object
param3 direction: boolean, True = add role, False = remove role
*/
const applyRemoveRole = async (reaction, user, direction) => {
const emojiUnicode = reaction.emoji.name.codePointAt(0).toString(16);
const role = reaction.message.guild.roles.cache.find;
const member = await reaction.message.guild.members.cache.find(member => member.id == user.id);
const targetRole = roles[emojiUnicode];
const hasRole = doesMemberHaveRole(member, targetRole)
console.log(user)
console.log(hasRole)
console.log(member._roles)
try {
if (role && member) {
if (!hasRole && direction) {
console.log("adding role")
addRemoveRole(member, roles[emojiUnicode], direction)
} else if (hasRole && !direction) {
console.log("removing role")
addRemoveRole(member, roles[emojiUnicode], direction)
}
}
} catch (e) {
console.error(e);
return
}
}
// Checks if the passed member has the passed roleID
// Returns True or False
const doesMemberHaveRole = (member, roleID) => {
return member.roles.cache.some(role => role.id === roleID)
}
// Handles the actual applying/removing of roles.
const addRemoveRole = async (member, role, addRemove) => {
(addRemove) ? await member.roles.add(role) : await member.roles.remove(role);
}
module.exports = applyRemoveRole;
This has me thinking it could be an async/await error where the role is attempting to be removed before it is ever saved in the member's roles. I have a console.log spitting out the members roles that is reacting to the message and it isn't until the second reaction sequence that the expected role is populating in their roles array (and then removed as the code executes). I have tried combing through many StackOverflow questions and YouTube videos, but a lot of the questions/answers aren't specific to this issue or dated and use deprecated code.
Here is the current flow based on console.logging member._roles at the start of each call, if it helps make it more clear what the error is.
Add Reaction, roles: [no role], member does not have role, add it (this works).
Remove Reaction, roles: [no role], role is not removed because it isn't there
Add reaction, roles: [role], role is not added because you already have it.
Remove Reaction, roles: [role], member has role, removes it from them.
The const hasRole = doesMemberHaveRole(member, targetRole) check was redundant and likely due to checking the user cache wasn't picking up the new user data with the new role, keeping the block of code to remove the role until the cache was updated. Removing this check altogether and simply checking to add/remove the role and executing, whether they have the role or not, cleared it right up.
I am trying to send a message to my audit logs every time someone gets banned from the server. This command works when someone joins the server, but it does not work when someone is banned, or unbanned.
This is the current code in the index.js file:
bot.on('guildBanAdd', async (member) => {
let channels = JSON.parse(
fs.readFileSync("././database/moderationChannel.json", "utf8")
);
let modchannel = channels[member.guild.id].channel;
let modChannel = bot.channels.cache.find(channel => channel.id === `${modchannel}`);
modChannel.send(`${member} was banned!`);
});
What I want to happen is when the member is banned the message is sent to the modCannel. Is there anyway that this can happen?
As Caramiriel mentioned in their comment, guildAddBan first parameter is the guild the ban occurred in and the second one is the user that was banned. There is no member parameter.
Another thing, as you store the channel IDs in the moderationChannel.json file. you can use channels.cache.get() instead of .find(). .get() should be preferred, as it gets an element with the specified key (the channel ID in this case).
You'll also need to replace member with user in modChannel.send() and check if modChannel exists. Check the snippet below:
bot.on('guildBanAdd', async (guild, user) => {
let channels = JSON.parse(
fs.readFileSync('././database/moderationChannel.json', 'utf8')
);
let channelId = channels[guild.id].channel;
let modChannel = bot.channels.cache.get(channelId);
if (!modChannel) {
return console.log(`No moderation channel found with ID ${channelId}`);
}
modChannel.send(`${user} was banned!`);
});
I'm trying to create a discord js bot which can send a random message by a specified user.
Here's my attept:
const ch = client.channels.cache.get("12345");
const soma = client.users.cache.get("4321");
if(message.content.startsWith(prefix+'test')){
console.log(`${ch}`);
ch.messages.fetch({ limit: 100 }).then(messages => {
console.log(`Received ${messages.size} messages`);
messages.forEach(message => message.author.id)
messages.forEach(function (message){
if (message.author.id === {soma}){
console.log(message.content);
}
})
})
};
I just can't figure out how to put the author id and the message content into an array or just go thru it when the command is executed.
Ok i read ur script and at the const soma = client.users.cache.get("4321"); part i noticed that ur trying to get the id from the users of the bot which isnot needed u can just use the id instantly so all u ahve to do is making soma defined as ur id no need for client.cache.get just like this const soma = "332036461669122048" for example, and for the channel you can just make it into const ch = message.channel.id instead of getting the channel from the client cuz ur getting it in a wrong way
Edit: and at the if (message.author.id === {soma}) you dont need to add the "{","}" its not needed
bot.on('messageReactionAdd', async (reaction, user) => {
// Define the emoji user add
let role = message.guild.roles.find(role => role.name === 'Alerts');
if (message.channel.name !== 'alerts') return message.reply(':x: You must go to the channel #alerts');
message.member.addRole(role);
});
Thats the part of my bot.js. I want the user to react in a certain channel and receive role Alerts
You haven't really stated what the problem is, what works and what doesn't work but I'll take a wild stab at some parts which catch my eye.
For starters you are calling properties on the variable message whilst in the code you supplied, you didn't create/set a variable named message. My guess is that you want the message to which a reaction has been added. To do that you have to use the MessageReaction parameter which is supplied in the messageReactionAdd event as reaction.
From there you can replace message.<something> with reaction.message.<something> everywhere in the code you supplied.
Something also to note is that you add the role Alerts to message.member. This won't work how you want it to, since it will give the Alerts role to the author of the original message.
What (I think) you want to do, is fetch the user who just reacted with the emoji and assign them the Alerts role. You'll have to find the member in the guild first and then assign them the Alerts role. To do this you'll have to use the User parameter and find the correct Member because you can't add a role to a User object but you can to a Member object. Below is some code which should hopefully put you on the right track.
// Fetch and store the guild (the server) in which the message was send.
const guild = reaction.message.guild;
const memberWhoReacted = guild.members.find(member => member.id === user.id);
memberWhoReacted.addRole(role);
You are using message.member variable despite not defining message.
Any of these methods won't really work in v12 so I updated it for someone else searching.
If you find any mistakes be sure to make me aware of it.
const Discord = require('discord.js');
const client = new Discord.Client({ partials: ['MESSAGE', 'CHANNEL', 'REACTION'] }); //partials arent really needed but I woudld reccomend using them because not every reaction is stored in the cache (it's new in v12)
const prefix = "-";
client.on('messageReactionAdd', async (reaction, user) => {
if (reaction.partial) { //this whole section just checks if the reaction is partial
try {
await reaction.fetch(); //fetches reaction because not every reaction is stored in the cache
} catch (error) {
console.error('Fetching message failed: ', error);
return;
}
}
if (!user.bot) {
if (reaction.emoji.id == yourEmojID) { //if the user reacted with the right emoji
const role = reaction.message.guild.roles.cache.find(r => r.id === yourRoleID); //finds role you want to assign (you could also user .name instead of .id)
const { guild } = reaction.message //store the guild of the reaction in variable
const member = guild.members.cache.find(member => member.id === user.id); //find the member who reacted (because user and member are seperate things)
member.roles.add(role); //assign selected role to member
}
}
})
Here's a quick answer, though way too late. So I'll be updating the answer with Discord.js v.12.x (or the same as Discord.js Master)
bot.on('messageReactionAdd', async (reaction, user) => {
//Filter the reaction
if (reaction.id === '<The ID of the Reaction>') {
// Define the emoji user add
let role = message.guild.roles.cache.find((role) => role.name === 'Alerts');
if (message.channel.name !== 'alerts') {
message.reply(':x: You must go to the channel #alerts');
} else {
message.member.addRole(role.id);
}
}
});
I am looking to create a command in order to tag certain users automatically using their username eg. "#RYAN#9602" whenever a switch statement case is executed. Currently the problem that I'm experiencing in that whenever I do try to tag users, it just writes "#RYAN#9602" into the text channel and doesn't actually tag them.
This is what I have tried:
var players = [
"#RYAN#9602"
]
switch(args[0].toLowerCase()){
case "play":
message.channel.send(players.join('\n'));
break;
}
So in summary, using Discord.JS, how do I make the bot actually tag the user so that they will get 'pinged' instead of just sending a message of their name into the text channel?
You have two options.
You can either use the toString method on the User object, or form the mention yourself using the user's ID.
Here's an example using toString:
client.on("message", => {
const channel = message.channel;
channel.send(message.author.toString());
});
And here's an example using the ID
client.on("message", => {
const channel = message.channel;
channel.send("<#" + message.author.id + ">");
});
Try using the toString method.
client.on("message", => {
const channel = message.channel;
channel.send(message.author.toString());
});
Update 2023: Now you can use userMention()
const { Client, userMention } = require('discord.js');
client.on('interactionCreate', async interaction => {
if (!interaction.isChatInputCommand()) return;
...
interaction.reply(userMention(member.id));
});