guildBanAdd can not read property 'id' of undefined - javascript

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!`);
});

Related

Discord, Mention someone when gets a role

Is there a way to mention someone immediately after getting a specific role in a specific channel?
For example when I, or any other admin, give someone a specific role the bot mentions them in a specific channel.
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("roleid"));
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("roleid"));
if (addedRoles.size > 0) {
if (newMember.roles.cache.some((role) => role.name === "testing")) {
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}.`);
}
});
This is assuming your code is exactly as shown in the question, and not using placeholder strings.
Firstly, "roleid" should be role.id without the "" when you're filtering. This will filter it properly, as should channelId where channel is defined, which I'm guessing are placeholders, but just in case.
Secondly, you'll probably want to check using addedRoles.has("roleIdToSend") as opposed to newMember.roles.cache.some(). This will DM them every time they're updated if they have the role, not if they only just got the role on that update.
Lastly, assuming you're using discord.js v13, you'll need to correct your send() method. It should look something like
channel.send({
content: `Welcome, ${oldMember.toString()}`,
embeds: [embed]
});

Issues with the Documents in Mongoose (JavaScript)

So I'm making a bot for discord but I'm having some issues with Mongoose. So what I want is basically, the user sends a message to save a Document with some of his info, but if there is already a Document with his info it will stop the process with return. So I tried this:
function main(message){
// So first user sends a message to store some data about him
let author = message.author //this is discord.js syntax, basically it returns the author of a message
let id = author.id //also discord.js syntax, returns the id from the user, in this case the author variable above
let check = logUser.findOne({userId : [id]}).exec().then(res => {
if (res) return true;
else return false;
})} // So if there is a Document with the id of the author of the message it will return true, else it returns false
if (check === true) return console.log("This User has already a Document with his info saved");
//so if the user has already a Document with his info it will return and stop the action of saving his Data
//everything from this point is basic Mongoose Syntax, to make a Document with User data
const theUser = new logUser({
_id : mongoose.Types.ObjectId(),
userName : author.username,
userId : author.id,
currency : 0
})
theUser.save()
.then(result => console.log(result))
.catch(err => console.log(err))
console.log(`User ${author.username} was stored into the database!`)
}
It fails in the if statement that checks if the user has a Document with his info already. I've tried multiple things but it doesn't work.
I think that the solution for this problem has to do with async functions but I'm not sure, and I don't know that much about async processes.
Thanks in advance!
The problem is that your treating logUser.findOne as synchronous. Perform the check in findOne callback like so:
function main(message){
// So first user sends a message to store some data about him
let author = message.author //this is discord.js syntax, basically it returns the author of a message
let id = author.id //also discord.js syntax, returns the id from the user, in this case the author variable above
logUser.findOne({userId : [id]}).exec().then(res => {
let check = Boolean(res);
if (check === true)
return console.log("This User has already a Document with his info saved");
const theUser = new logUser({
_id : mongoose.Types.ObjectId(),
userName : author.username,
userId : author.id,
currency : 0
});
theUser.save()
.then(result => {
console.log(result);
console.log(`User ${author.username} was stored into the database!`)
})
.catch(err => console.log(err))
});
}
Are you purposely wrapping the id in an array? I don't know your schema but it seems odd and may contributing to your issues. userId : [id]
You may want to consider async/await to reduce callbacks. You can also look into using a unique index to avoid multiple requests in the future. Using a unique index will throw an error when trying to save the same document twice.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
https://docs.mongodb.com/manual/core/index-unique/

Trying to fetch a member based on their nickname/displayname. Discord.js BOT

Hi am i trying to take a user specified nickname for a member and fetch that members and get additional information about that user. Right now i have confirmed the ARGS[0] sent by the user is correct but i am getting a NULL response to the matched user. Not sure what i am missing. Thanks
This is my current code. Just trying to get the match working right now. I also need to consider if the person doesnt have a nickname to check the username. Or think would displayname property be better. Thanks
if(command === "memberinfo") {
let sentNickname = args[0];
message.channel.send(`Sent Nickname: ${sentNickname}`);
const discordserver = client.guilds.get(DragonTS); // Define server to get information from
discordserver.fetchMembers() // Fetch guild members
.then() //.then(console.log)
.catch(console.error);
}
let matchedMember = discordserver.members.find(m => m.nickname === sentNickname);
message.channel.send(`Matched Member ${matchedMember}`);
Looks like some parts of your code aren't executed. You need to put all your code into the .then():
if(command === "memberinfo") {
let sentNickname = args[0];
message.channel.send(`Sent Nickname: ${sentNickname}`);
const discordserver = client.guilds.get(DragonTS); // Define server to get information from
discordserver.fetchMembers() // Fetch guild members
.then((serverWithFetchedMembers) => {
let matchedMember = serverWithFetchedMembers.members.find(m => m.nickname === sentNickname);
message.channel.send(`Matched Member ${matchedMember}`);
}) //.then(console.log)
.catch(console.error);
}
It will wait for the fetchMembers() function and execute your code after it!

Discord JS // Trying to add role by reacting to the message

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);
}
}
});

Discord.js deleteMessage() doesn't work

I am creating a Discord bot with discord.js and I'd like to create a command that can clear messages. For now, I have this code (only the interesting part) and I can't figure out why it doesn't work:
// Importing discord.js, creating bot and setting the prefix
const Discord = require('discord.js');
const bot = new Discord.Client();
const prefix = "/";
// Array that stores all messages sent
messages = [];
bot.on('message', (message) => {
// Store the new message in the messages array
messages.push(message);
// Split the command so that "/clear all" becames args["clear", "all"]
var args = message.content.substring(prefix.length).split(" ");
// If the command is "/clear all"
if(args[0] == "clear" && args[1] == "all") {
bot.deleteMessages(messages); // Code that doesn't work
// Resets the array
messages = [];
}
}
// CONNECT !!!
bot.login('LOGING TOKEN HERE');
Can you help me ?
You should use <TextChannel>.bulkDelete instead.
Example:
msg.channel.bulkDelete(100).then(() => {
msg.channel.send("Purged 100 messages.").then(m => m.delete(3000));
});
This would delete 2 - 100 messages in a channel for every call to this method so you would not receive 429 (Too many Requests) Error frequently which might result in your token being revoked.
I see two problems:
the messages array is always empty; there is no code that adds items to the array, so the call to bot.deleteMessages will always get an empty array;
it does not appear that deleteMessages is an available method on Discord.Client;
Based on the documentation, I think what you want is sweepMessages. The description of that states:
Sweeps all text-based channels' messages and removes the ones older than the max message lifetime. If the message has been edited, the time of the edit is used rather than the time of the original message.
Try changing the code to instead call bot.sweepMessages(1);, which I think will tell the client to clear all messages older than one second.
Another way to do this, without sweepMessages is by using fetchMessages:
let user = message.mentions.users.first();
let amount = !!parseInt(message.content.split(' ')[1]) ? parseInt(message.content.split(' ')[1]) : parseInt(message.content.split(' ')[2])
var prefix = '!'
if (message.content.startsWith(prefix + 'clear') && !amount)
return message.reply('Must specify an amount to clear!');
if (message.content.startsWith(prefix + 'clear') && !amount && !user) return message.reply('Must specify a user and amount, or just an amount, of messages to clear!');
message.channel.fetchMessages({
limit: amount,
}).then((messages) => {
if (user) {
const filterBy = user ? user.id : bot.user.id;
messages = messages.filter(m => m.author.id === filterBy).array().slice(0, amount);
}
message.channel.bulkDelete(messages).catch(error => console.log(error.stack));
});
This will allow users to use the command !clear [#] to delete that number of messages when sent. If it is run as just !clear you can set how many get deleted, without a specified number.
discord.js Documentation - TextChannel#fetchMessages
You can swap
bot.deleteMessages()
to:
messages.forEach(x => x.delete())
Its not like that. you should fetch the messages first then use bulkDelete to delete them
, here is a simple example
// Normal Javascript
<Message>.channel.fetchMessages()
.then(messages => {
// Here you can use bulkDelete(101) to delete 100 messages instead of using fetchMessages and deleting only 50
<Message>.channel.bulkDelete(messages);
});
// ES6
let messages = await <Message>.channel.fetchMessages();
// Here you can use bulkDelete(101) to delete 100 messages instead of using fetchMessages and deleting only 50
await <Message>.channel.bulkDelete(messages);

Categories