How to iterate through an enmap? - discord.js

I'm trying to iterate through an enmap for my discord.js bot, I've managed to set and get values from a single entry but I'm trying to set up a command that adds people to a newsletter like DM about minor major updates.
if (args[0] === 'minor') {
if (devlog.updates === 'minor') return message.channel.send('You are already recieving minor updates.').then(m => m.delete(5000))
await client.devlog.set(userID, "yes", 'subscribed');
await client.devlog.set(userID, "minor", 'updates');
return message.channel.send('You will now recieve minor and major updates.').then(m => m.delete(5000))
}
if (args[0] === 'major') {
if (devlog.updates === 'major') return message.channel.send('You are already recieving major updates.').then(m => m.delete(5000))
await client.devlog.set(userID, "yes", 'subscribed');
await client.devlog.set(userID, "major", 'updates');
return message.channel.send('You will now recieve only major updates.').then(m => m.delete(5000))
}
if (!args[0]) {
if (devlog.subscribed === 'yes') {
await client.devlog.set(userID, "no", 'subscribed');
await client.devlog.set(userID, "none", 'updates');
return message.channel.send('You will stop recieving updates about RoboTurtle all together').then(m => m.delete(5000))
}
if (devlog.subscribed === 'no') {
return message.channel.send(`Please choose wether you\'d like to recieve minor or major updates! (minor has both) **devlog minor/major**`).then(m => m.delete(10000))
}
}
It kind of works but it won't trigger the message if they already are subscribed to the same type of update and if they do just !devlog it's meant to either set them to not receive updates if they already are, or tell them to choose between the two if they aren't, however it just sends the last message either way.
I tried setting up my enmap iteration for DMing all subscribed people with a for...of function based off the .map related docs (since they're meant to be just "fancier" maps) but to no avail, since they don't really show discord style use cases.
if (args[0] === 'minor') {
for (let entry of client.devlog) {
if (entry.updates === 'minor') {
let user = client.users.get(entry)
user.send(`**[Minor Update]\n${args.slice(1)}`)
}
}
}
if (args[0] === 'major') {
for (let entry of client.devlog) {
if (entry.subscribed === 'yes') {
let user = client.users.get(entry)
user.send(`**[Major Update!]\n${args.slice(1)}`)
}
}
}
In case anyone wanted to look at the full code to get a better idea of what Im trying to do here ya go: https://pastebin.com/bCML6EQ5

Since they are just an extension of the normal Map class, I would iterate through them with Map.forEach():
let yourEnmap = new Enmap();
yourEnmap.set('user_id', 'your_values');
yourEnmap.forEach((value, key, map) => {
...
});
In your case it would be something like:
client.devlog.forEach((values, user_id) => {
// you can check your subscription here, the use the user_id to send the DM
client.users.get(user_id).send("Your message.");
});

Related

How to make an image cooldown script in discord.js?

I have been having some problems with my image cooldown script recently. It's intent, when it works, is to let users post images in between a set time limit, in order to prevent spamming. In Discord.JS v12, it was working perfectly. However, after installing v13.6, it does not do its job anymore. Here's the code.
On line 6, there is a line that excludes some channels from the cooldown. The rest of the channels in the server are subject to it though. I would appreciate some help with this code, as it is pretty important.
FYI: All intents have been enabled and listed in the index.js file. Everything else works, but not this script.
Here's the raw paste code, if you want to test the code out:
const talkedRecently = new Set();
client.on('messageCreate', async message => {
if (!message.guild) return;
if (message.author.bot) return;
if (!message.channel.type === 'dm') return;
if (!message.channel.id === 'channel1' || 'channel2' || 'channel3' || 'channel4' || 'channel5' || 'channel6' || 'channel7' || 'channel8') {
if (message.attachments.size > 0) {
if (talkedRecently.has(message.author.id)) {
setTimeout(()=> message.delete(), 5000).catch(err => console.log(err))
message.channel.send("You must wait 30 seconds before sending another attachment - " + message.author.username).then(msg => {
setTimeout(() => message.delete(), 10000)
}).catch(/*Your Error handling if the Message isn't returned, sent, etc.*/)
}
}
}
});
There are 5 issues with this code.
You are strict-comparing boolean to a string, which of course... will always return false
// DON'T DO THIS
if (!thing === 'one') {
// DO THIS
if (thing !== 'one') {
That's not how we compare multiple values in JS
// DON'T DO THIS
if (thing === "one" || "two" || "three")
// DO THIS
if ([ "one", "two", "three" ].includes(thing)) {
The channel IDs must be changed, there are no channels IDs such as channelN
You are deleting the same message 2 times
// Right here
setTimeout(()=> message.delete(), 5000).catch(err => console.log(err))
// ...
// And here
.then(msg => { setTimeout(() => message.delete(), 10000) }).catch(/*Your Error handling if the Message isn't returned, sent, etc.*/)
Your code is outdated and requires an update
See the update guide here.

Discord.JS bot not responding to several commmands

My bot is not responding to any commands except for the .purge command.
Here is my code.
const { Client, MessageEmbed } = require('discord.js');
const client = new Client();
const { prefix, token } = require('./config.json');
client.on('ready', () => {
client.user.setStatus('invisible');
console.log('Bot ready!');
client.user.setActivity('Bot is in WIP Do not expect stuff to work', {
type: 'STREAMING',
url: "https://www.twitch.tv/jonkps4"
});
console.log('Changed status!');
});
client.on('message', message => {
if (message.content.startsWith(".") || message.author.bot) return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const command = args.shift().toLowerCase();
if (message === 'apply') {
message.reply("The Small Developers Application form link is:")
message.reply("https://forms.gle/nb6QwNySjC63wSMUA")
}
if (message === 'kick') {
const user = message.mentions.users.first();
// If we have a user mentioned
if (user) {
// Now we get the member from the user
const member = message.guild.member(user);
// If the member is in the guild
if (member) {
member
.kick('Optional reason that will display in the audit logs')
.then(() => {
// We let the message author know we were able to kick the person
message.reply(`Successfully kicked ${user.tag}`);
})
.catch(err => {
message.reply('I was unable to kick the member \n Maybe due to I having missing permissions or My role is not the higher than the role the person to kick has');
// Log the error
console.error(err);
});
} else {
// The mentioned user isn't in this guild
message.reply("That user isn't in this guild!");
}
// Otherwise, if no user was mentioned
} else {
message.reply("You didn't mention the user to kick!");
}
}
if (command === 'purge') {
const amount = parseInt(args[0]) + 1;
if (isNaN(amount)) {
return message.reply('Not a valid number');
} else if (amount > 100) {
return message.reply('Too many messages to clear. \n In order to clear the whole channel or clear more please either ```1. Right click on the channel and click Clone Channel``` or ```2. Execute this command again but more times and a number less than 100.```');
} else if (amount <= 1) {
return message.reply('Amount of messages to clear **MUST** not be less than 1 or more than 100.')
}
message.channel.bulkDelete(amount, true).catch(err => {
console.error(err);
message.channel.send('**There was an error trying to prune messages in this channel!**');
});
}
});
client.login(token);
I need a specific command to work which is the .apply command
and i would like to know why my embeds do not work.
I tried this embed example It didn't work.
const embed = new MessageEmbed()
// Set the title of the field
.setTitle('A slick little embed')
// Set the color of the embed
.setColor(0xff0000)
// Set the main content of the embed
.setDescription('Hello, this is a slick embed!');
.setThumbnail('https://tr.rbxcdn.com/23e104f6348dd71d597c3246990b9d84/420/420/Decal/Png')
// Send the embed to the same channel as the message
message.channel.send(embed);
What did I do wrong? I am quite new to Discord.JS Any help would be needed.
You used the message parameter instead of command. Instead of message === 'xxx' put command === 'xxx'. Simple mistake, I think that was what you meant anyways. Of course the purge command worked because you put command === 'purge' there

(discord.js v12) messageReactionAdd only work on owner of message [duplicate]

This question already has an answer here:
None of my discord.js guildmember events are emitting, my user caches are basically empty, and my functions are timing out?
(1 answer)
Closed 2 years ago.
I've an issue with messageReactionAdd with floowing code :
bot.on("ready", () =>
{
// I cache the selected message declared before in message_id and channel_id
bot.channels.cache.get(channel_id).messages.fetch(message_id).then(m => {
console.log("Cached reaction message.");
}).catch(e => {
console.error("Error loading message.");
console.error(e);
});
})
bot.on("messageReactionAdd", (reaction, user) => {
if(reaction.emoji.name == "👍" && reaction.message.id === message_id)
try {
const role = reaction.message.channel.guild.roles.cache.find(role => role.name == "Membres");
reaction.message.guild.member(user).roles.add(role);
} catch {
console.log('Error : can\'t add the role');
}
});
The problem is that code works only with the owner of the cached message not with other user in the channel.
Do you know why ?
If you want to create a reaction role system, you can use raw
bot.on('raw', event => {
if (event.t === 'MESSAGE_REACTION_ADD' || event.t == "MESSAGE_REACTION_REMOVE"){
let reaction = event.d.emoji
let userID = enevt.d.user_id
let messageID = event.d.message_id
let guildID = event.d.guild_id
let guild = bot.guilds.cache.get(guildID)
let role = guild.roles.cache.get(role_id) //role id is defined by yourself
let user = guild.members.cache.get(userID) //You need to enable server members intent to use that command
}
}
and I created all of the ids and objects you can develop a reaction role system.
If you did not enable server members intent, you can use:
guild.members.fetch(userID).then(user => user.roles.add(role))

how do i make sure that only one reaction can be added to a message?

I am creating a role reaction bot and I want that if a member has already clicked on a reaction and clicks another it removes the previous one and the role associated with it and gives him the role that corresponds to the last one clicked (there are 15 reactions available) , I was writing code similar to this:
let msg = reaction.message;
let msgGuild = msg.guild;
let userGuild = msgGuild.members.cache.get(user.id);
let userRole = userGuild.roles;
if(reaction.message.channel.id === "764148072498200589") {
if(reaction.emoji.name === "RedRoleID") {
if(userRole.cache.has("BaseRoleID")) {
userRole.remove("BaseRoleID");
userRole.add("RedRoleID");
} else if(userRole.cache.has("OrangeRoleID")) {
userRole.remove("OrangeRoleID");
userRole.add("RedRoleID");
}
};
};
is there an easier and shorter way to do what I want without creating an else if for each role?
I think you could probably make an array of all the emoji names, then use Array.prototype.forEach to check all of them.
let { emoji, message, message: { guild, channel }} = reaction;
let { roles } = guild.member(user.id);
const emojis = ['BaseRoleID', 'RedRoleID', 'OrangeRoleID', 'etc'];
if (channel.id === '764148072498200589') {
emojis.forEach((id) => (roles.cache.has(id) ? roles.remove(id) : id));
roles.add(emoji.name);
}
Edit: My mistake, I thought you had named the emojis as the corresponding role IDs. Here's an alternate method if you do not want to do that:
let { emoji, message, message: { guild, channel }} = reaction;
let { roles } = guild.member(user.id);
const emojis = [
{ emote: 'EmojiID', role: 'RoleID' },
'continue this pattern for all roles and emotes'
];
if (channel.id === '764148072498200589') {
emojis.forEach(({ emote, role }) => {
if (roles.cache.has(role))
return roles.remove(role)
if (emoji.id === emote) roles.add(role)
});
};

Discord.js not sending messages (no errors)

I've just started using discord.js to make a bot to my discord server. I'm trying to make the bot to send a message but it just doesn't do it. I don't even get any errors.
Here's a clip of the code that doesn't work:
bot.on('voiceStateUpdate', (oldMember, newMember) => {
let newUserChannel = newMember.voiceChannel
let oldUserChannel = oldMember.voiceChannel
if(oldUserChannel === undefined && newUserChannel !== undefined) {
// User Joins a voice channel
console.log("Join");
if(newMember = manu) {
console.log("kyllä")
bot.on('message', msg => {
msg.channel.send("Manu, oletko käynyt parturissa? \n Kirjoita vastauksesi numero. \n 1. Olen \n 2. En");
})
bot.on('message', msg => {
if(msg.content === "2") {
msg.channel.send("Ja parturin kautta takasin");
}
else if(msg.content === "1") {
msg.channel.send("Hyvvö");
}
else {
msg.channel.send("Puhu suomea");
}
})
}
}
else if(newUserChannel === undefined){
// User leaves a voice channel
console.log("Leave");
}
})
If you can understand the language in the text sections please notice this bot is just for fun :D.
What am I doing wrong?
You wrote if(newMember = manu) {. You need to use === or == to compare two values. Use = only to assign a value to a variable.
I think the problem is: You put a bot.on in a bot.on. What you can do is put the second bot.on with messages underneath the other bot.on, and it should fix your problem.

Resources