I want to make a Setup Command for my Bot, that I can use to set up channels for the bot e.g. a welcome channel. For this, I used a JSON file.
Code
collector.on('collect', async (i) => {
if (i.customId === 'modchannelbutton') {
const ModChannelSetEmbed = new MessageEmbed()
.setTitle('<:vsl_settings:991655211179442216> | **__SERVER SETUP__**')
.addField(
'» Stand',
setupconfig[interaction.guild.id].modlog === 'nochannel'
? '<:m_notdone:991657968296808478> Du hast noch kein Moderator Log gesetzt'
: `<:m_done:991657855549710376> Dein aktueller Moderator Log ist: <#${
setupconfig[interaction.guild.id].modlog
}>`,
)
.setDescription(
'> Du hast 1 Minute Zeit um einen neuen Moderator Log zu setzen, schreib dafür einfach nur den #Channel in diesem Channel',
)
.setColor('#0c06b6');
row.components[0].setDisabled(true);
await i.update({ embeds: [ModChannelSetEmbed], components: [] });
// … Here I need the Message Collector for the Channel …
}
});
I want to make a collector that collected if the message next to the button is clicked in a channel. But all my tries don't reply.
That means:
Slash Command use —> Button Click —> Channel send
The Collector should control if the message next to the button click is a channel.
Related
I would like to make a commander (cmd slash) to activate maintenance on a remote server. Most of the order is done and functional. But when I want to put the number of minutes via a .addNumberOption, I get the error
Option "minutes" is of type: 10; expected 3.
data: new SlashCommandBuilder()
.setName('maintenancemc-staff')
.setDescription('Active ou désactive le mode maintenance du serveur Minecraft')
.addStringOption((option) =>
option
.setName('raison')
.setDescription('Raison du changement de statut')
.setRequired(true)
)
.addNumberOption((option) =>
option
.setName('minutes')
.setDescription("Décompte d'activation du mode maintenance en minute")
.setRequired(true)
),
async execute(interaction, client) {
await interaction.deferReply({ fetchReply: true, ephemeral: true });
const { options } = interaction;
const raison = options.getString("raison");
const timer = options.getString("minutes");
...
Thank you in advance for your help! 🦊
If you use addNumberOption, instead of options.getString("minutes"), you need to use options.getNumber("minutes").
im trying to do an embed, but every time i try using it, it says "DiscordAPIError: Cannot send an empty message"
Here is the embed and everything related to it:
client.on('message',(message) => {
if(message.author.bot) return;
let botMessageLog = new Discord.MessageEmbed()
.setAuthor(`Logs`, client.user.avatarURL())
.setDescription(`**${message.author.toString()}** said: **${message.content}** in channel **${message.channel.toString()}**`)
.setFooter(`Log system`, client.user.avatarURL())
.setTimestamp()
.setColor("FF0000");
bot.channels.cache.get("1018767166218182668").send(botMessageLog)
});
You are doing many things wrong if you are using discord js v 14
hare is a quick fix
const {Client, EmbedBuilder} = require("discord.js")
//define a new client
client.on('messageCreate',(message) => {
if(message.author.bot) return;
let botMessageLog = new EmbedBuilder()
.setAuthor({name:`Logs`,iconURL: client.user.displayAvatarURL()})
.setDescription(`**${message.author.username}** said: **${message.content}** in channel **${message.channel.name}**`)
.setFooter({text:`Log system`, iconURL: client.user.displayAvatarURL() })
.setTimestamp()
.setColor("FF0000");
bot.channels.cache.get("1018767166218182668").send({embeds:[botMessageLog]})
//you must define bot as client
})
it always better if you use the latest Version of discord js
Why does this not work? According to the idea, it should output an embed with a greeting and give the role of "traveler" when a new user on server, but something goes wrong, either an error in the embed or in my bad code.
robot.on('guildMemberAdd', member => {
const userId = member.id;
const exampleeEmbedd = new MessageEmbed()
.setColor('#53db56')
.setTitle(' [👋] Приветствуем нового путника!')
.setDescription(' Приветствуем вас <#!'+ userId +'>!\nДобро пожаловать на международный сервер режима Geopolitics. \nЗдесь вы можете присоеденится к существующему городу/государству, либо зарегистрировать свой город/государство.')
.setURL('')
.setAuthor('👑Имперский Бот👑', 'https://images-ext-2.discordapp.net/external/nWASMV-67mx7guRheeUpvyD_cb6X2NkxUMH4PtbweyA/%3Fsize%3D512/https/cdn.discordapp.com/avatars/916617120064884796/5028d4861b407575072686657b3c2e9a.png' )
.setThumbnail(member.user.avatarURL())
.addFields(
)
.setImage('')
.setTimestamp()
.setFooter('Всего пользователей: ' + member.guild.memberCount, 'https://images-ext-2.discordapp.net/external/nWASMV-67mx7guRheeUpvyD_cb6X2NkxUMH4PtbweyA/%3Fsize%3D512/https/cdn.discordapp.com/avatars/916617120064884796/5028d4861b407575072686657b3c2e9a.png');
const role = member.guild.roles.cache.get("921840233883009084")
member.roles.add(role);
var msg = member.guild.channels.get('921833742585188353').
msg.send( { embeds: [exampleeEmbedd] } );
});
Your issue most likely lies in that you do not have proper intents for guild member events. In your developer portal under your bot enable the server members intent.
When instantiating your client be sure to add the GUILD_MEMBERS intent in your intents.
I am trying to make it so when my bot is added to another server, it will send an embed saying how many servers it's in now and the guild name and also the guild owner. I am also trying to make another embed so it tells me when it leaves a server and tells me when it joined the server first and then when it was removed and the guild name and guild owner. I use discord.js. Could someone help, please? This is my current script:
bot.on("guildCreate", guild => {
const joinserverembed = new Discord.MessageEmbed()
.setTitle("Joined a server!")
.addField("Guild name:", `${guild.name}`)
.addField("Time of join:", `${Discord.Guild.createdTimestamp()}`)
.setColor("GREEN")
.setThumbnail(guild.displayAvatarURL())
if (guilds.channel.id = 740121026683207760) {
channel.send(joinserverembed)
}
guild.channel.send("Thank you for inviting Ultra Bot Premium! Please use up!introduction and up!help for the new perks and more!")
})
bot.on("guildDelete", guild => {
const leftserverembed = new Discord.MessageEmbed()
.setTitle("Left a server!")
.addField("Guild name:", `${guild.name}`)
.addField("Time of removal:", `${createdTimestamp()}`)
.setColor("RED")
.setThumbnail(guild.displayAvatarURL())
if (guilds.channel.id = 740121026683207760) {
channel.send(leftserverembed)
}
})
I have resolved your first issue for you in the code below.
You were doing guild.channel.send(), in this case, guild represents a Discord.Guild however you're using it like it represents an instance of Message, which it does not.
You can use guild.channels.cache.find(x => x.name == 'general').send("Thanks for inviting me to this server¬!") will send a message to a channel named general in that server.
bot.on("guildCreate", (guild) => {
const joinserverembed = new Discord.MessageEmbed()
.setTitle("Joined a server!")
.addField("Guild name:", guild.name)
.addField("Time of join:", Date.now())
.setColor("GREEN")
.setThumbnail(guild.iconURL({ dynamic: true }));
bot.channels.cache.get("740121026683207760").send(joinserverembed);
guild.channels.cache
.filter((c) => c.type === "text")
.random()
.send(
"Thank you for inviting Ultra Bot Premium! Please use up!introduction and up!help for the new perks and more!"
);
});
I filter the channels in the guild, ensuring that they are not categories or voice channels, then send the welcome message to a random one.
As for your second query, you need to use a database, store the Date.now timestamp of when it was added, then once the bot has left the guild it must get the value and display its time. I haven't done this for you, but I have fixed your code:
bot.on("guildDelete", (guild) => {
const leftserverembed = new Discord.MessageEmbed()
.setTitle("Left a server!")
.addField("Guild name:", guild.name)
.addField("Time of removal:", Date.now())
.setColor("RED")
.setThumbnail(guild.iconURL({ dynamic: true }));
bot.channels.cache.get("740121026683207760").send(leftserverembed);
});
module.exports.run = (client, message, args) => {
if (message.member.roles.some(role => role.name === process.env.MODO)) {
const user = message.mentions.users.first();
// Parse Amount
const amount = !!parseInt(message.content.split(' ')[1]) ? parseInt(message.content.split(' ')[1]) : parseInt(message.content.split(' ')[2])
if (!amount) return message.reply('Vous devez spécifier un montant à supprimer !');
if (!amount && !user) return message.reply('Vous devez spécifier un utilisateur et le montant, ou juste une quantité de messages à purger !');
if (amount > 100) return message.reply('Malheureusement, discord ne permet pas la Suppression de plus de 100 messages en une fois ...');
// Fetch 100 messages (will be filtered and lowered up to max amount requested)
message.channel.fetchMessages({
limit: amount,
}).then((messages) => {
if (user) {
const filterBy = user ? user.id : Client.user.id;
messages = messages.filter(m => m.author.id === filterBy).array().slice(0, amount);
}
message.channel.bulkDelete(messages).catch(error => console.log(error.stack));
});
var purge = new Discord.RichEmbed()
.setAuthor(`Suppression de ${amount} Messages dans le salon ${message.channel.name}`)
.setFooter("Requête par " + message.member.user.tag, message.member.user.avatarURL)
.setTimestamp()
.setColor(0xF03434)
message.channel.send(purge).then(message => {
message.react('🗑')
client.on('messageReactionAdd', (reaction, user) => {
// on vérifie que ce soit bien la bonne réaction et on ne compte pas celui du bot
if (reaction.emoji.name === '🗑' && user.id !== client.user.id) {
message.delete()
}
})
});
}
}
What I would like is that at the level of the 'final' embed, when it tells me that the purge has been done, there is a reaction '🗑' and when we click it removes the message.
The problem is that the current code removes all the embed of the same type.
If I click on the reaction of the first embed, it also removes the second, and does not delete anything else...
Attaching a listener to the client's messageReactionAdd event is what's causing this; any reaction emits this event, and your code is executed for each one after a single purge. As long as the reaction is 🗑 and the user isn't the client, Message.delete() will be called on message.
(node: 10752) UnhandledPromiseRejectionWarning: DiscordAPIError: Unknown Message
at item.request.gen.end (/Users/jeremy/Desktop/BERRYBOT/node_modules/discord.js/src/client/rest/RequestHandlers/Sequential.js:85:15)
at then (/Users/jeremy/Desktop/BERRYBOT/node_modules/snekfetch/src/index.js:215:21)
at process._tickCallback (internal / process / next_tick.js: 68: 7)
(node: 10752) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated from the inside of the outside world, but it was not handled by .catch (). (rejection id: 14)
After adding that reaction that deletes the wrong message, it no longer exists. When you try to delete it again, this error will be thrown.
Furthermore, your code isn't waiting for the messages to be purged before sending the reply. Because of this, the message can be sent before and subsequently deleted by the TextChannel.bulkDelete() call. Then, when you try to react to the same message via Message.react(), your error is thrown because it no longer exists.
To make sure the code is executed in the proper order, make sure you're using your then() chains properly, or utilize the beauty of async/await.
Reorganizing the code, still using then() methods:
message.channel.fetchMessages({ limit: amount })
.then(fetchedMessages => {
const filterBy = user ? user.id : Client.user.id;
const toPurge = messages.filter(m => m.author.id === filterBy).array().slice(0, amount);
message.channel.bulkDelete(toPurge)
.then(deletedMessages => {
var embed = new Discord.RichEmbed()
.setAuthor(`Suppression de ${deletedMessages.size} Messages dans le salon ${message.channel.name}`)
.setFooter(`Requête par ${message.author.tag}`, message.author.avatarURL)
.setTimestamp()
.setColor(0xF03434)
message.channel.send(embed)
.then(reply => {
reply.react('🗑');
const filter = (reaction, user) => reaction.emoji.name === '🗑' && user.id !== client.user.id;
reply.createReactionCollector(filter, { maxMatches: 1 })
.on('collect', () => reply.delete());
});
});
})
.catch(console.error);
Alternatively, using await:
// You must define your callback function as async to use the 'await' keyword! It should look like...
// async (client, message, args) => { ... }
try {
const fetchedMessages = await message.channel.fetchMessages({ limit: amount });
const filterBy = user ? user.id : Client.user.id;
const toPurge = messages.filter(m => m.author.id === filterBy).array().slice(0, amount);
const deletedMessages = await message.channel.bulkDelete(toPurge);
var embed = new Discord.RichEmbed()
.setAuthor(`Suppression de ${deletedMessages.size} Messages dans le salon ${message.channel.name}`)
.setFooter(`Requête par ${message.author.tag}`, message.author.avatarURL)
.setTimestamp()
.setColor(0xF03434)
const reply = await message.channel.send(embed)
await reply.react('🗑');
const filter = (reaction, user) => reaction.emoji.name === '🗑' && user.id !== client.user.id;
reply.createReactionCollector(filter, { maxMatches: 1 })
.on('collect', async () => await reply.delete());
} catch(err) {
console.error(err);
}
You'll notice this code is using ReactionCollectors as opposed to attaching listeners to the messageReactionAdd event. The former are meant for this usage and will prevent memory leaks. Also, I've changed some of the variable names to make the code easier to read and understand. A few other very minor improvements are present as well.