I'm probably misunderstanding exactly what's being returned by the members object here, but I'm attempting to test a deafen command within my bot - the documentation for discord.js states that the Message object contains a Mentions property that holds all the valid mentions within a sent message, from there, I can drill down a bit further and get to the Members property from within Mentions - which returns a collection of GuildMembers that have been mentioned in the message - which is what I want. The problems arises when I attempt to grab those GuildMember objects from within the collection that I get back - I'm not quite sure what I'm doing wrong, but I get back errors. The code I have is as follows:
module.exports = {
name: 'deafen',
cooldown: 5,
description: 'Deafens mentioned user or users.',
args: true,
execute(message) {
const taggedMembers = message.mentions.members;
for(const member of taggedMembers) {
member.setDeaf(true)
.then(() => console.log(`Deafened ${member.displayName}`))
.catch(console.error);
}
},
};
and I get back this error in my terminal window:
TypeError: member.setDeaf is not a function
at Object.execute (/home/tai/dev/FutabaBot/commands/admin/deafen.js:10:20)
at Client.<anonymous> (/home/tai/dev/FutabaBot/FutabaBot.js:80:17)
at Client.emit (events.js:210:5)
at MessageCreateHandler.handle (/home/tai/dev/FutabaBot/node_modules/discord.js/src/client/websocket/packets/handlers/MessageCreate.js:9:34)
at WebSocketPacketManager.handle (/home/tai/dev/FutabaBot/node_modules/discord.js/src/client/websocket/packets/WebSocketPacketManager.js:105:65)
at WebSocketConnection.onPacket (/home/tai/dev/FutabaBot/node_modules/discord.js/src/client/websocket/WebSocketConnection.js:333:35)
at WebSocketConnection.onMessage (/home/tai/dev/FutabaBot/node_modules/discord.js/src/client/websocket/WebSocketConnection.js:296:17)
at WebSocket.onMessage (/home/tai/dev/FutabaBot/node_modules/ws/lib/event-target.js:120:16)
at WebSocket.emit (events.js:210:5)
at Receiver.receiverOnMessage (/home/tai/dev/FutabaBot/node_modules/ws/lib/websocket.js:789:20)
I'm not sure if it's necessary, but I can post the other pieces of code that relate to this - and the documentation for discord.js can be found here
The message.mentions.members returns a Collection of GuildMembers and a Snowflake (some unique identifier. A Collection is an extension of the Map class, where a map is an array with each item having a key and a value attribute.
When looping over a map, like you're doing with for(const member of taggedMembers), each item (or member in your case) is a key and a value pair. Then you're trying to call the setDeaf method on that pair, which as you've seen doesn't work.
What you want is to only loop over the values in the collection. This can easily be done with a .forEach. I'll add some example code down below:
taggedMembers.forEach((member) => {
member.setDeaf(true)
.then(() => console.log(`Deafened ${member.displayName}`))
.catch(console.error);
});
Give it a go and let me know if you run into any more issues.
EDIT: As slothiful pointed out in the comments, using a .forEach won't catch any Promise rejections even after attaching a .catch(). To fix this you can use the for ... of loop but destructuring the pair. This can be seen in the example below:
for (let [, member] of taggedMembers) {
member.setDeaf(true)
.then(() => console.log(`Deafened ${member.displayName}`))
.catch(console.error);
}
Related
I'm trying to make a Discord bot, one of its features is that it plays chess, at the start of the command, I read the JSON file, then check if it's undefined since I'll call a key from the object, so just in case it doesn't exist already, I'll create the data needed
Problem is, when I try to assign the data, it says I haven't initialized the variable, which is weird, because I did initialize it 3 lines before, var, let and const all throw the same error
Another thing is that outside the if statement, just above it, when console.logging it, it works perfectly, but when console.logging it inside the if statement, it throws that error
I honestly have no idea what's happening here, I can't think of anything that's causing this either, is this a NodeJS bug? I feel like it could be.
const games = JSON.parse(fs.readFileSync("./lib/database/games/chess/chess_games.json"))
console.log(games, 'outside if statement') // Here it outputs just fine
if (games[interaction.guild.id] == undefined) {
console.log(games, 'inside if statement') // Here is where it breaks
games[interaction.guild.id] = {
games: {},
players: {},
amount_of_games: 0
}
fs.writeFileSync("./lib/database/games/chess/chess_games.json", JSON.stringify(games, null, 2));
const games = JSON.parse(fs.readFileSync("./lib/database/games/chess/chess_games.json"))
}
This is the error:
ReferenceError: Cannot access 'games' before initialization
at Object.execute (C:\Users\aschr\Dropbox\Coding\Javascript\entropic_bot\lib\database\bot\commands\chess.js:40:4)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Client.<anonymous> (C:\Users\aschr\Dropbox\Coding\Javascript\entropic_bot\index.js:44:3)
You have two variables with the same name.
Change the name of one of them
The second games is tried to be accessed instead of the first one because of hoisting. That's why you are getting the error
I am trying to code a discord bot for a friend's server. It's supposed to be a fun bot so I thought it would be funny to add a spam command. But I keep getting Errors when I do. Can someone help me out with the error? The code and the error are both given below.
It works fine when I do the command -spam #[user]. But the moment someone mistypes it and does maybe -spam [random characters], it shows me the error
CODE:
client.on("message", msg => {
if(msg.content.startsWith(prefix+'spam ')){
let mentions = msg.mentions.members.first().id;
if(!mentions) return msg.reply("I'm sorry! That user does not exist.")
for(var i=1;i<=5;i++) {
msg.channel.send('<#'+mentions+'>')
}
}
})
And the error is
TypeError: Cannot read property 'id' of undefined
at Client.<anonymous> (/home/runner/VADER-Bot/index.js:44:44)
at Client.emit (events.js:326:22)
at Client.EventEmitter.emit (domain.js:483:12)
at MessageCreateAction.handle (/home/runner/VADER-Bot/node_modules/discord.js/src/client/actions/MessageCreate.js:31:14)
at Object.module.exports [as MESSAGE_CREATE] (/home/runner/VADER-Bot/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_CREATE.js:4:32)
at WebSocketManager.handlePacket (/home/runner/VADER-Bot/node_modules/discord.js/src/client/websocket/WebSocketManager.js:384:31)
at WebSocketShard.onPacket (/home/runner/VADER-Bot/node_modules/discord.js/src/client/websocket/WebSocketShard.js:444:22)
at WebSocketShard.onMessage (/home/runner/VADER-Bot/node_modules/discord.js/src/client/websocket/WebSocketShard.js:301:10)
at WebSocket.onMessage (/home/runner/VADER-Bot/node_modules/ws/lib/event-target.js:132:16)
at WebSocket.emit (events.js:314:20)
repl process died unexpectedly: exit status 1
You can use optional chaining (?.). It will return undefined or null if the value before is nullish. If it isn’t, it goes to the next property (id in this case)
let mentions = msg.mentions.members.first()?.id //notice the '?.'
if(!mentions) return msg.reply("I'm sorry! That user does not exist.")
This will not throw an error if no one is mentioned, and will go to the "I'm sorry..." message.
Edit: due to your comment, it seems that you are using an old version of node.js. This is a bit longer but should do the trick.
const check = msg.mentions.members.first()
if(check) let mentions = check.id
The function msg.mentions.members.first() is returning undefined, try to log each part of this big object to see where you are missing your variable.
msg.mentions.members.first() is undefined, which is expected because they typed -spam [something that doesn't contain a user]
Try checking if msg.mentions.members.first() exists, and if so get the id. If not, then don't because you'll get an error.
client.on("message", msg => {
if(msg.content.startsWith(prefix+'spam ')){
let mentions = msg.mentions.members.first();
if(!mentions) return msg.reply("I'm sorry! That user does not exist.")
for(var i=1;i<=5;i++) {
msg.channel.send('<#'+mentions.id+'>')
//etc
}
}
}
call the function first() on let mentions = msg.mentions.members.first().id; separately and then assign id into mentions. Firstly make sure each object in msg.mentions.members there are definitions.
const object1 = { a: 'cat', b: 123, c: true }. If you want to access b's value you would type const bValue = object1.b. So in that same way, const object1 = { a: { b: 'Dog' } }, to access a's value, const aValue = object1.a.b would be the answer. So in your case you have to check if there is a object called mentions in msg and members in mentions and a function in object members which is highly unlinkely. First check let members = msg.mentions.members exist. if not you would again get TypeError: Cannot read property 'members' of undefined. Hope this is clear enough.
Other people have said this. but you said you were new to coding so I will try to elaborate.
What you have is this:
let mentions = msg.mentions.members.first().id;
if(!mentions) return msg.reply("I'm sorry! That user does not exist.")
It's giving you this error because you are checking to see if the user exists AFTER you are getting the ID of the user, you should check to see if they exist FIRST. It can't set mentions to the ID because msg.mentions.members.first() is returning undefined.
let mentions = msg.mentions.members.first(); // set mentions variable to the member object
if(!mentions) return msg.reply("I'm sorry! That user does not exist."); // check if user exists
mentions = mentions.id; // set mentions to the id of the mentioned user
I want the discord bot to allow the command to be run only if the person has one of the roles in the array.
const validroles = ['owner', 'Co-Owner']
if(!message.member.roles.includes(validroles)) {
return message.channel.send(`**${message.author}, You do not have permission to use this command**`)
}
It gives me the error TypeError: message.member.roles.includes is not a function
How do I fix this?
message.member.roles returns a manager for the roles belonging to this member, so you need to use the .cache property to return the roles. .cache returns a Collection that doesn't have an .includes() method. I think you were looking for the .has() property that checks if an element exists in the collection:
if (!message.member.roles.cache.has(validrole.id)) {
return message.channel.send(`**${message.author}, You do not have permission to use this command**`)
}
I'm working on a discord bot that does a variety of things. It keeps randomly crashing and I tracked down the source of the error. What it does is it downloads images sent to it in a discord private message, hashes them and sets their name to the hash to make sure no duplicates exist. This is not the most efficient way to do so but it works.
Here's my code (it's a bit messy)
message.attachments.forEach(url => {
if (!message.author.bot) {
function getDate() {
let d = new Date().getTime();
return d;
}
tempdate = new getDate();
ext = path.extname(url.url);
request.get(url).on(`error`, console.error).pipe(fs.createWriteStream(`./temp/Img-${tempdate}${ext}`));
hash = sha256(`./temp/Img-${tempdate}${ext}`);
if (fs.existsSync(`./attachments/Img-${hash}${ext}`)) {
request.get(url).on(`error`, console.error).pipe(fs.createWriteStream(`./attachments/Img-${hash}${ext}`));
console.log(`Error: Duplicate File`)
}
fs.createWriteStream(`./attachments/Img-${hash}${ext}`);
console.log(`Wrote Hashed File.`)
fs.unlinkSync(`./temp/Img-${tempdate}${ext}`)
}
})
Every once in a while, however it returns this:
fs.js:1061
return binding.unlink(pathModule._makeLong(path));
^
Error: ENOENT: no such file or directory, unlink 'C:\Users\xxxxx\Desktop\testbot\temp\Img-[object Object].png'
at Object.fs.unlinkSync (fs.js:1061:18)
at Client.client.on.message (C:\Users\xxxxx\Desktop\testbot\yes.js:48:20)
at emitOne (events.js:116:13)
at Client.emit (events.js:211:7)
at MessageCreateHandler.handle (C:\Users\xxxxx\node_modules\discord.js\src\client\websocket\packets\handlers\MessageCreate.js:9:34)
at WebSocketPacketManager.handle (C:\Users\xxxxx\node_modules\discord.js\src\client\websocket\packets\WebSocketPacketManager.js:103:65)
at WebSocketConnection.onPacket (C:\Users\xxxxx\node_modules\discord.js\src\client\websocket\WebSocketConnection.js:333:35)
at WebSocketConnection.onMessage (C:\Users\xxxxx\node_modules\discord.js\src\client\websocket\WebSocketConnection.js:296:17)
at WebSocket.onMessage (C:\Users\xxxxx\node_modules\ws\lib\event-target.js:120:16)
at emitOne (events.js:116:13)
I assume I did something wrong here. I can't find any answers online
You are mixing synchronous and asynchronous code.
The .pipe() is absolutely asynchronous, yet you're trying to assume that it's done immediately. You can't reliably program this way.
You need to listen for an event to know when the .pipe() is done before you can proceed with the rest of the processing.
And, as soon as you make it event driven, your .forEach() will run ahead with multiple iterations trying to run at the same time and then the fact that your variables aren't declared locally inside the loop will cause variable conflicts.
Also, what is this line of code doing all by itself:
fs.createWriteStream(`./attachments/Img-${hash}${ext}`);
You create a write stream, but don't even keep track of it. That will just leak a file handle.
As for solutions, it really requires a significant rewrite. I've answered a similar question here Issue with request and .pipe(). In that answer, I created a promise wrapper for .pipe() which would then let you use await to sequence a pipe operation. I'd probably use that solution in rewriting this code.
Currently I'm trying to add to a blacklist array for my discord bot. Reading the array works fine, but whenever I try to append to the bot node exits with code 1.
I've tried a few ways, but none really seem to work.
const data = require('./data.json');
data.serverData.blackListedColors.append(randomRoleColor);
which returns:
data.serverData.blackListedColors.append(randomRoleColor);
^
TypeError: data.serverData.blackListedColors.append is not a function
at Client.<anonymous> (C:\Users\mtutt\OneDrive\Documenten\DiscordKeyBot\bot.js:363:59)
at Client.emit (events.js:209:13)
at MessageCreateHandler.handle (C:\Users\mtutt\OneDrive\Documenten\DiscordKeyBot\node_modules\discord.js\src\client\websocket\packets\handlers\MessageCreate.js:9:34)
at WebSocketPacketManager.handle (C:\Users\mtutt\OneDrive\Documenten\DiscordKeyBot\node_modules\discord.js\src\client\websocket\packets\WebSocketPacketManager.js:105:65)
at WebSocketConnection.onPacket (C:\Users\mtutt\OneDrive\Documenten\DiscordKeyBot\node_modules\discord.js\src\client\websocket\WebSocketConnection.js:333:35)
at WebSocketConnection.onMessage (C:\Users\mtutt\OneDrive\Documenten\DiscordKeyBot\node_modules\discord.js\src\client\websocket\WebSocketConnection.js:296:17)
at WebSocket.onMessage (C:\Users\mtutt\OneDrive\Documenten\DiscordKeyBot\node_modules\discord.js\node_modules\ws\lib\event-target.js:120:16)
at WebSocket.emit (events.js:209:13)
at Receiver.receiverOnMessage (C:\Users\mtutt\OneDrive\Documenten\DiscordKeyBot\node_modules\discord.js\node_modules\ws\lib\websocket.js:789:20)
at Receiver.emit (events.js:209:13)
Process finished with exit code 1
I've tried using .parse and .add but those also don't seem to work.
using .push doesn't seem to crash it, but also doesn't add the string to the .json file.
edit:
here's the .json file for reference
{
"serverData": {
"muffinID": "[disocrdID]",
"token": "[token]",
"blackListedColors": []
}
You can't use require() for data that changes during the lifetime of your bot process due to the Node require cache. In addition, just modifying data won't automagically persist it back into the file; you'll have to write it back into the file.
It's not rocket surgery to write yourself, but you may want to look into a library that does this for you – I haven't tried this, but it looks promising enough: https://www.npmjs.com/package/json-persistent-object