Dropdown failed after restart - discord.js - node.js

This is my interaction reaction roles code.FYI i have used the new node.js so it couldnt be error because of the version. The problem is dropdown failed after restarting my bot. The "secret" at my code is the role id so just ignore it.
Here is my code:
client.on("message", async message => {
if (message.content == prefix + "rr") {
let option1 = new MessageMenuOption()
.setLabel("Black Charcoal")
.setValue("Option 1")
.setDefault()
.setEmoji("🌑")
let option2 = new MessageMenuOption()
.setLabel("Love Magenta")
.setValue("Option 2")
.setDefault()
.setEmoji("❤️")
let selection = new MessageMenu()
.setID("Selection")
.setMaxValues(1)
.setMinValues(0)
.setPlaceholder("Select Role")
.addOption(option1)
.addOption(option2)
let embed = new Discord.MessageEmbed()
.setColor("0x00a6ff")
.setTitle("VIP Colour Role")
.setDescription(`<#&secret>\n<#&secret>\n<#&secret>\n<#&secret>\n<#&secret>`)
let menumsg = await message.channel.send(embed, selection)
const role1 = message.guild.roles.cache.find(r => r.id === "secret")
const role2 = message.guild.roles.cache.find(r => r.id === "secret")
async function menuselection(menu) {
switch(menu.values[0]) {
case "Option 1":
if(message.member.roles.cache.has("secret")){
await message.member.roles.add(role1)
await message.member.roles.remove([role2])
await menu.reply.send("Claimed Black Charcoal!", true)}
break;
case "Option 2":
if(message.member.roles.cache.has("secret")){
await message.member.roles.add(role2)
await message.member.roles.remove([role1])
menu.reply.send("Claimed Love Magenta!", true)}
break;
}
}
client.on("clickMenu", (menu) => {
if(menu.message.id == menumsg.id) {
if(menu.clicker.user.id == message.author.id) menuselection(menu)
else menu.reply.send(":x: you are not allowed to pick something", true)
}
})
}
})

You seem to be using the now archived discord-buttons library. Looking through its source code, it looks like it does not store information about which messages have menus anywhere other than the bot's memory. When you restart your bot, that information is lost, and your bot stops watching for menu clicks.
To keep it working after restarts, you would have to store such information somewhere external to your bot, like a file or some database, and start the menus again when the bot starts.

Related

How to make a button work infinitely and not only once when pressed discord.js

I just learnt how to make a button in discord.js, and I even learnt how to make a cookie counter, but the only problem is that I can only click it once. If I do it again, it doesn't work. My code is:
let button = new ButtonBuilder()
.setCustomId('cookie')
.setLabel('0')
.setStyle(ButtonStyle.Primary)
let clicker = new ActionRowBuilder()
.addComponents(
button,
);
console.log(button);
console.log(button.data.label);
for the components and
const filter = i => i.customId === 'cookie' && i.user.id === `${interaction.user.id}`;
const collector = interaction.channel.createMessageComponentCollector({ filter, time: 15000 });
collector.on('collect', async i => {
if (i.customId === 'cookie'){
// cookieCount(guildid, messageid);
const newCookie = Number(button.data.label + 1);
clicker = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('cookie')
.setLabel(`${newCookie}`)
.setStyle(ButtonStyle.Primary),
);
await i.update({ embeds: [embed], components: [clicker]})
}
});
for the update.
Btw I'm relatively new to discord.js.
The time option is how long the collector will run in milliseconds. If you remove that option, it should go forever.
const collector = interaction.channel.createMessageComponentCollector({ filter });
If you are wanting to have a button that works indefinitely and through restarts of the bot you can create an event called interactionCreate and then you can filter that to run only when it's a button interaction.
From that you can check the name of the clicked button then run the correct code for that button. Using the event allows all buttons that the bot has sent to be used.
import { Client, Interaction, InteractionType } from 'discord.js';
client.on('interactionCreate', interaction => {
if(interaction.type == InteractionType.MessageComponent) {
if(interaction.customId == 'button_1') {
// Your code....
}
}
});

Discord.js AutoRole Reaction do nothing

my little problem is the next one :
When i react a message, my bot do nothing :D and it's not the objectives.
My events :
module.exports = async(client, messageReaction, user) => {
const message = messageReaction.message;
const member = message.guild.members.cache.get(user.id);
const emoji = messageReaction.emoji.name;
const channel = message.guild.channels.cache.find(c => c.id === '739163072064651296');
const lol = message.guild.roles.cache.get("763104201588473896"); //id role lol
const wz = message.guild.roles.cache.get("763104236119785584"); //id role wz
if (["lol", "wz"].includes(emoji) && message.channel.id === channel.id) {// lol = emoji name and wz too
switch (emoji) {
case "lol":
member.roles.add(lol);
message.channel.send('test')
break;
case "wz":
member.roles.add(wz);
message.channel.send('test')
break;
};
};
};
My events handler :
fs.readdir("./Events/",(error , f) => {
if(error) console.log(error);
console.log(`${f.length} events chargés`);
f.forEach((f) => {
const events = require(`./Events/${f}`);
const event = f.split(".")[0];
client.on(event, events.bind(null, client));
});
});
If someone can help it's perfect ! Thank you !
I tried to understand what you wanted to make but couln't understand you at all, your trying to make a autoRole sytem that listen's to reactions? AutoRole is supposed to be in a guildMemberAdd event, so if a member join's, you add a role automatically, but from the code you provided, it looks like it listen's to reactions on some message? If your trying to make a Reaction Role system, then follow this. Other than that, i can't help you.
If your trying to make a autoRole system follow this
From what i know, when you add a role to someone, you will have to do the following
member.roles.add("roleid")
But what your doing is basically this:
member.roles.add(message.guild.roles.cache.get("763104201588473896")) //as lol is defined like that
So, to fix it, instead of getting the role object, then trying to add the role to the user, do this, and be sure to make the file name "guildMemberAdd.js":
module.exports = async(client, member) => {
const lol = "763104201588473896" //id role lol
const wz = "763104236119785584"; //id role wz
member.roles.add(lol);
member.roles.add(wz);
};

Discord.js - Updating a MessageEmbed in the following code

So, I have (this is only part of it) the following code, but I can't figure out this whole updating a sent embed thing...
The coding is all working if I send a new embed every time, but I don't want to clutter the channel; thus attempting to update the first embed.
Code:
const filter = m => m.author.id === message.author.id;
let hangembedStart = new Discord.MessageEmbed()
.setDescription("Let's get started!")
.setColor('#0099ff')
.setThumbnail(sicon)
.addField('Word:', asterisc)
message.channel.send(hangembedStart);
const collector = message.channel.createMessageCollector(filter, {
maxMatches: 9,
time: 30000
});
collector.on('collect', m => {
if (m.content === 'cancel') {
inProgress = false;
delete guessed;
collector.stop();
return;
}
if (lowChar === text) {
message.channel.send(`Congratulations, you guessed the word!`);
inProgress = false;
delete guessed;
collector.stop();
return;
}
let hits = checkChar(lowChar, text);
if (hits === 0) {
let hangembedGuess = new Discord.MessageEmbed()
.setDescription("Hangman - The Game - In progress")
.setColor('#0099ff')
.setThumbnail(sicon)
.addField('Word:', reveal)
.addField('Guessed:', guessed.join(" "))
message.channel.send(hangembedGuess);
} else if (hits > 0) {
let hangembedGuess = new Discord.MessageEmbed()
.setDescription("Hangman - The Game - In progress")
.setColor('#0099ff')
.setThumbnail(sicon)
.addField('Word:', reveal)
.addField('Guessed:', guessed.join(" "))
message.channel.send(hangembedGuess);
}
});
collector.on('end', collected => {
message.channel.send(`Game ended, word was: ${text}!`);
inProgress = false;
delete guessed;
//collector.stop();
});
How the ... can I update the first embed in this code, instead of sending a new one each time?
I tried using message.edit() but that triggers:
UnhandledPromiseRejectionWarning: DiscordAPIError: Cannot edit a message authored by another user
I've googled, read, searched, tried, tested just about everything I've come across, but can't wrap my head around this one...
Got it sorted!!
Added the following line:
const hangmanMessage = await message.channel.send(hangembedStart);
//above
const filter = m => m.author.id === message.author.id;
Then changed the following line(s):
message.channel.send(hangembedGuess);
//to this
hangmanMessage.edit(hangembedGuess);
Now it updates the first embed, instead of sending a new one each time :D

How to use db.subtract after time using glitch.com, discord.js

Basically im trying to run this code
const Discord = require('discord.js');
const fs = require('fs');
const db = require("quick.db");
module.exports.run = async (bot, message, args) => {
let user = message.member;
let vic = db.get(`vic_${user.id}`);
console.log("Activating auto start command!");
let intro = new Discord.RichEmbed()
.setTitle("You have dosed on vicodin and you are now immune to all shots")
.setColor('#00cc00');
let nopill = new Discord.RichEmbed()
.setTitle("You do not own this drug")
.addField("Error", "<:bluepill:713790607901982780> --- **You do not own any `Vicodin Pills`, please purchase off of the black market** --- <:bluepill:713790607901982780>")
.setFooter("Must own first")
let pill = new Discord.RichEmbed()
.setTitle("You have already dosed")
.addField("Error", "<:bluepill:713790607901982780> --- **You have already dosed on `Vicodin Pills`, please wait until the effect wear off to dose again** --- <:bluepill:713790607901982780>")
.setFooter("Already dosed")
if (args[0].startsWith("testing")) {
if (vic === null) return message.channel.send(nopill)
} else if (args[0].startsWith("vicodin")) {
if (vic === 0) return message.channel.send(nopill)
if (vic === 2) return message.channel.send(pill)
message.channel.send(intro)
db.set(`vic_${user.id}`, 2)
console.log(`${user} just dosed vicodine`);
setTimeout(() => {
console.log(`this is a test by zuc`)
db.set(`vic_${user.id}`, 0)
}, 1800000);
}
}
What it dose is when a user run the Dose command it makes them dose on the pill, im trying to make the pill/dose remove after a certain amount of time using db.subtract, since im using glitch.com to do this, the setTimeout isnt doing what i want it to after that time.
Change the timeout code to:
setTimeout(() => {
console.log(`this is a test by zuc`)
db.delete(`vic_${user.id}`);
db.add(`vic_${user.id}`, 0);
}, 1800000);

showing user with multiple roles discord.js

with this command set to only one role. I want to set more than one role. how can I do it ?
let rolid = "663047983675342849";
let tokuchi = client.guilds
.get(sunucuid)
.roles.get(rolid)
.members.filter(o => !o.voiceChannel).map(member => member.user);
.setDescription(tokuchi.join("\n"))```
You can get all members with multiple role somethink like this, but other code shown leaves questions
let sGuild = client.guilds.get(sunucuid)
let membersWithRoles = sunucuid.members.filter(member => {
return member.roles.some(r=>['ROLEID','ROLEID'].includes(r.id))
})
console.log(membersWithRoles)
v2 version
At the fist you dont need get guild in all comands, use message.guild for this.
This code will return array of users usernames with any of your roles and if they dont have voiceconnection now.
exports.run = async (client, message, args) => {
if(message.channel.type === 'dm') return
if (!message.member.hasPermission("ADMINISTRATOR"))
return message.channel.send(" Missing Permission");
let tokuchi = message.guild.members.filter(member => {
return member.roles.some(r=>['ROLEID','ROLEID'].includes(r.id)) && !member.voiceChannel
}).map(member => (member.user.username))
const basarili = new Discord.RichEmbed()
.setColor('RANDOM')
.setAuthor(`Seste Olmayan Yetkililer`, client.user.avatarURL)
.setDescription(tokuchi.join("\n"))
.setFooter("Created by Tokuchi")
.setTimestamp()
.addField(`İşlemi Gerçekleştiren Kişi:`, `${message.author.username}#${message.author.discriminator}`)
return message.channel.send(basarili)
};
its return a users.username because you cant .join('\n) users, its a collection, not array.

Resources