So I basically want to create a countdown for my discord ticket bot. If someone types in -close[...] the channel will be deleted after 10 seconds. But if the person who did this command types something in the channel the countdown will stop and the channel won't be deleted.
That works fine so far. But if I abort the countdown on every other message that I send to the channel the embed will be sent where it says "Countdown stopped" also if I type -close [...] again this message pops up but the channel will still be deleted after 10 seconds.
function closeTicket (_ticketid, channel, deleter, reason) {
var timer = setTimeout(function() {
channel.delete();
}, 10000);
channel.send({embed: {
color: 3447003,
author: {
name: client.user.username,
icon_url: client.user.avatarURL
},
title: ``,
description: "This ticket will close in 10 seconds. If this was a mistake type anything to stop the timer.",
fields: [{
name: "Thank you!",
value: "Thank you for using our ticket system! Good luck and have fun playing on our servers."
},
],
timestamp: new Date(),
footer: {
icon_url: client.user.avatarURL,
text: "Support Ticket System © H4rry#6701"
}
}
});
logTicketClosed(_ticketid, deleter, reason);
client.on('message', message => {
if(message.channel === channel && message.author === deleter && timer != null) {
clearTimeout(timer);
timer = null;
message.channel.send({embed: {
color: 3447003,
author: {
name: client.user.username,
icon_url: client.user.avatarURL
},
title: `Timer Stopped`,
description: "The timer has been stopped, the ticket will remain open.",
timestamp: new Date(),
footer: {
icon_url: client.user.avatarURL,
text: "Support Ticket System © H4rry#6701"
}
}});
}
});
return 0;
}
I got it to work now! I defined a new variable called timer_running which would be set to true when the timer starts and to false when it stops. That way I got it to work now.
function closeTicket (_ticketid, channel, deleter, reason) {
var timer_running = false;
var timer = setTimeout(function() {
channel.delete();
}, 10000);
timer_running = true;
channel.send({embed: {
color: 3447003,
author: {
name: client.user.username,
icon_url: client.user.avatarURL
},
title: ``,
description: "This ticket will close in 10 seconds. If this was a mistake type anything to stop the timer.",
fields: [{
name: "Thank you!",
value: "Thank you for using our ticket system! Good luck and have fun playing on our servers."
},
],
timestamp: new Date(),
footer: {
icon_url: client.user.avatarURL,
text: "Support Ticket System © H4rry#6701"
}
}
});
logTicketClosed(_ticketid, deleter, reason);
client.on('message', message => {
if(message.channel === channel && message.author === deleter && timer_running === true) {
clearTimeout(timer);
timer_running = false;
message.channel.send({embed: {
color: 3447003,
author: {
name: client.user.username,
icon_url: client.user.avatarURL
},
title: `Timer Stopped`,
description: "The timer has been stopped, the ticket will remain open.",
timestamp: new Date(),
footer: {
icon_url: client.user.avatarURL,
text: "Support Ticket System © H4rry#6701"
}
}});
}
});
}
Related
I have the following code that creates a slash command. I want the embed to be updated every 10 seconds.
const embed = new EmbedBuilder()
.setAuthor({ name: track.title, iconURL: client.user.displayAvatarURL({ size: 1024, dynamic: true }) })
.setThumbnail(track.thumbnail)
.addFields(
{ name: "**volume**", value: `**${queue.volume}**` },
{ name: "**اtime**", value: `**${trackDuration}**` },
{ name: "**song**", value: `**${progress}**` },
{ name: "**repeat mode**", value: `**${methods[queue.repeatMode]}**` },
{ name: "**track**", value: `**${track.requestedBy}**` }
)
.setFooter({ text: inter.user.username, iconURL: inter.member.avatarURL({ dynamic: true }) })
.setColor("ff0000")
.setTimestamp();
I tried with setInterval but it didn't work.
You really need to add more information, but you could use setInterval().
I am just taking a guess on how you use your bot, interaction.editReply() is my guess that you send the embed as a reply, but you can change it to whatever you want, and the code within the setInterval will run once every 10 seconds.
EDIT: You also need to send the initial reply if you wish to edit it.
e.g.
const embed = new EmbedBuilder()
.setAuthor({ name: track.title, iconURL: client.user.displayAvatarURL({ size: 1024, dynamic: true }) })
.setThumbnail(track.thumbnail)
.addFields(
{ name: '**volume**', value: `**${queue.volume}**` },
{ name: '**اtime**', value: `**${trackDuration}**` },
{ name: '**song**', value: `**${progress}**` },
{ name: '**repeat mode**', value: `**${methods[queue.repeatMode]}**` },
{ name: '**track**', value: `**${track.requestedBy}**` }
)
.setFooter({ text: inter.user.username, iconURL: inter.member.avatarURL({ dynamic: true }) })
.setColor('ff0000')
.setTimestamp();
// You need to send the initial embed if you wish to edit it
interaction.reply({ embeds: [embed] });
setInterval(() => {
// Code to run every 10 seconds:
interaction.editReply({ embeds: [embed] });
// 10 seconds in milliseconds
}, 10000);
I've been working to create a Purge Command in JavaScript based off this Purge Command written in TypeScript for reconlx's DJS v13 command handler (I modified a few bits to make all the handlers and whatnot function in DJS v14), however, there are some bugs and a few things I'm losing my mind over.
Firstly, everytime the command is enacted, this little nuisance of a message appears with the success confirmation embeds, and I don't really know how to deal with it.
Secondly, when I purge specifically by user and term, the wrong embed is sent and my bot will purge as normal. According to the source code, it (referring to my bot) should be sending the cleanPurge embed, but it instead sends the userPurge embed. Purging specifically by user works as intended, just with the annoying "thinking" message as an unwanted bonus.
Thirdly, when purging by term, I can only purge if I enact the command right after a message with the specified term. Here's an example (if you don't understand my wording).
// It is okay to purge during these situations
// cat in a hat
// cat in a hat
// cat in a hat
// /purge [amount: 3] {term: cat}
// The command will purge only if it is enacted right after the message with the specific term, however...
// The command won't purge during these situations
// cat in a hat
// cat in a hat
// cat in a hat
// SHITPOST
// /purge [amount: 3] {term: cat}
// The message "SHITPOST" is in-between the last message with the term "cat" and when I enact my command,
// therefore, for some reason, I can't purge any messages with my specified keyword before the message "SHITPOST".
// I can purge messages with the term "cat" AFTER the message "SHITPOST" until another message gets in the way.
// If you have no idea what I mean, a link to my bot's demo is below.
Purging without specifics DOESN'T bring up the "{Bot} is thinking..." message and works as intended.
If you're confused, here's a link to a demo of my bot's bugs
Any questions, please feel free to ask me, and sorry if my wording is shit.
Source code for purge.js
const { EmbedBuilder, ApplicationCommandOptionType, PermissionsBitField } = require("discord.js");
const { Command } = require("reconlx");
const ms = require("ms");
module.exports = new Command({
name: "purge",
description: "Deletes a specified number of messages",
userPermissions: PermissionsBitField.Flags.ManageMessages,
options: [
{
name: "amount",
description: "Number of messages to purge",
type: ApplicationCommandOptionType.Integer,
min_value: 1,
max_value: 100,
required: true,
},
{
name: "user",
description: "Purge this member's messages",
type: ApplicationCommandOptionType.User,
required: false,
},
{
name: "term",
description: "Purge messages with this specific term",
type: ApplicationCommandOptionType.String,
required: false,
},
{
name: "reason",
description: "Reason for purging",
type: ApplicationCommandOptionType.String,
required: false,
},
],
run: async ({ interaction }) => {
const amount = interaction.options.getInteger("amount");
const user = interaction.options.getUser("user");
const term = interaction.options.getString("term");
const reason = interaction.options.getString("reason") || "Unspecified";
const channel = interaction.channel
const messages = await interaction.channel.messages.fetch({
limit: amount + 1,
});
if (user) {
const userMessages = messages.filter((m) => m.author.id === user.id);
const purged = await interaction.channel.bulkDelete(userMessages, true);
const userPurge = new EmbedBuilder()
.setColor("#2F3136")
.setTitle(`🧹 PURGED!`)
.addFields(
{
name: `Cleared ${purged.size} message${
purged.size > 1 ? "s" : ""
}!`,
value: `Any messages from \`${user.tag}\` have been deleted from ${channel}!`
},
{
name: `User`,
value: `\`${user.tag}\``,
inline: true
},
{
name: `Term`,
value: `\`Unspecified\``,
inline: true
},
{
name: `Reason(s)`,
value: `\`${reason}\``,
inline: true
},
)
interaction.channel.send({ embeds: [userPurge] });
} else if (term) {
const filteredTerm = messages.filter((m) =>
m.content.toLowerCase().includes(term)
);
const purged = await interaction.channel.bulkDelete(filteredTerm, true);
const termPurge = new EmbedBuilder()
.setColor("#2F3136")
.setTitle(`🧹 PURGED!`)
.addFields(
{
name: `Cleared ${purged.size} message${
purged.size > 1 ? "s" : ""
}!`,
value: `Any messages with the term ||\`${term}\`|| have been deleted from ${channel}!`
},
{
name: `User`,
value: `\`Unspecified\``,
inline: true
},
{
name: `Term`,
value: `||\`${term}\`||`,
inline: true
},
{
name: `Reason(s)`,
value: `\`${reason}\``,
inline: true
},
)
interaction.channel.send({ embeds: [termPurge] });
} else if (term && user) {
const memberMessages = messages.filter((m) => m.author.id === member.id && m.content.toLowerCase().includes(term));
const purged = await interaction.channel.bulkDelete(memberMessages, true);
const cleanPurge = new EmbedBuilder()
.setColor("#2F3136")
.setTitle(`🧹 PURGED!`)
.addFields(
{
name: `Cleared ${purged.size} message${
purged.size > 1 ? "s" : ""
}!`,
value: `Any messages from \`${user.tag}\` with the term ||\`${term}\`|| have been deleted from ${channel}!`
},
{
name: `User`,
value: `\`${user.tag}\``,
inline: true
},
{
name: `Term`,
value: `||\`${term}\`||`,
inline: true
},
{
name: `Reason(s)`,
value: `\`${reason}\``,
inline: true
},
)
interaction.channel.send({ embeds: [cleanPurge] });
} else {
const purged = await interaction.channel.bulkDelete(messages, true);
const purge = new EmbedBuilder()
.setColor("#2F3136")
.setTitle(`🧹 PURGED!`)
.addFields(
{
name: `Cleared ${purged.size - 1} message${
purged.size > 1 ? "s" : ""
}!`,
value: `The specified number of messages have been deleted from ${channel}!`
},
{
name: `User`,
value: `\`Unspecified\``,
inline: true
},
{
name: `Term`,
value: `\`Unspecified\``,
inline: true
},
{
name: `Reason(s)`,
value: `\`Unspecified\``,
inline: true
},
)
interaction.channel.send({ embeds: [purge] });
}
},
});
Your video is still processing, so I couldn't watch it, but:
In the "cat"/"cat"/"cat"/"shitpost" situation, you'd need amount=4, because you're only fetching N + 1 messages. If you need want your bot to purge N last matching messages even if there are more in between (e.g. in a "a"/"b"/"a"/"b"/"a"/"b" situation where you want to purge all "b"s), you'd need to fetch more messages until you've purged enough. Another "good enough" option might be to fetch e.g. amount * 2 messages and hope it's enough.
In any case, you could start by de-quadriplicating your message filtering and embed building:
{
run: async ({ interaction }) => {
const { options, channel } = interaction;
const amount = options.getInteger("amount");
const user = options.getUser("user");
const term = options.getString("term");
const reason = options.getString("reason") || "Unspecified";
const lastNMessages = await channel.messages.fetch({
limit: amount + 1,
});
const filteredMessages = lastNMessages.filter((message) => {
if (user && message.author.id !== user.id) {
return false;
}
if (term && !message.content.toLowerCase().includes(term)) {
return false;
}
return true;
});
const purged = await channel.bulkDelete(filteredMessages, true);
const title = `Cleared ${purged.size} message${purged.size > 1 ? "s" : ""}!`;
const message = [
`${purged.size} messages`,
user ? ` from \`${user.tag}\`` : "",
term ? ` containing \`${term}\`` : "",
` have been deleted from ${channel}!`,
].join("");
const userPurge = new EmbedBuilder()
.setColor("#2F3136")
.setTitle(`🧹 PURGED!`)
.addFields(
{
name: title,
value: message,
},
{
name: `User`,
value: user ? `\`${user.tag}\`` : "Unspecified",
inline: true,
},
{
name: `Term`,
value: term ? `||\`${term}\`||` : `\`Unspecified\``,
inline: true,
},
{
name: `Reason(s)`,
value: `\`${reason}\``,
inline: true,
},
);
await channel.send({ embeds: [userPurge] });
},
}
So I am building my bot using discord.js (v13).
Here is my code:
const { MessageEmbed } = require('discord.js')
const { SlashCommandBuilder } = require("#discordjs/builders")
const guild = require('../config.json');
module.exports = {
data: new SlashCommandBuilder()
.setName('server')
.setDescription('Display info about this server.'),
async execute(interaction) {
const exampleEmbed = new MessageEmbed()
.setColor('#0099ff')
.setTitle(`Server infomation on ${guild.name}`)
.setDescription('Tells Server Info')
.addFields(
{ name: 'Server Name', value: `${guild.name}` },
{ name: '\u200B', value: '\u200B' },
{ name: 'Inline field titlve', alue: 'Some value here', inline: true },
{ name: 'Inline field title', value: 'Some value here', inline: true },
)
.setTimestamp()
await interaction.reply({embeds: [exampleEmbed]}) ;
},
};
the above is an example of a slash command with an embed. In my embed, I am trying to print the guild name. Using guild.name. I don't get any error in the terminal but when I run the code in my discord server my bot shows undefined.
What am I doing wrong here and how do I fix it?
Edit: My Config.json:-
{
"token": "Test Test",
"clientId": "Client Id",
"guildId": "Guild Id"
}
P.S. I am kinda new to discord.js and javascript
The problem is that the variable guild is the content of the config.json file. If this file contains an object with the keys guildID and clientID only, guild.name will be undefined.
I think you want to use the guild where the interaction is coming from, in this case, it's interaction.guild:
async execute(interaction) {
const exampleEmbed = new MessageEmbed()
.setColor('#0099ff')
.setTitle(`Server infomation on ${interaction.guild.name}`)
.setDescription('Tells Server Info')
.addFields(
{ name: 'Server Name', value: `${interaction.guild.name}` },
{ name: '\u200B', value: '\u200B' },
{ name: 'Inline field title', value: 'Some value here', inline: true },
{ name: 'Inline field title', value: 'Some value here', inline: true },
)
.setTimestamp();
await interaction.reply({ embeds: [exampleEmbed] });
}
My join.js Code is Below :-
I want the bot to auto self deafen when ever it joins any Voice Channel.
module.exports = {
name: "join",
description: "Joins your voice channel",
category: "music",
execute(message, args) {
if (message.member.voice.channel) {
message.member.voice.channel.join().then((connections) => {
message.channel.send({
embed: {
color: message.client.messageEmbedData.color,
author: {
name: "✔️ Hey, i joined your voice channel",
},
timestamp: new Date(),
},
});
});
} else {
message.channel.send({
embed: {
color: message.client.messageEmbedData.color,
author: {
name: "❗ You are not in a voice channel",
},
timestamp: new Date(),
},
});
}
},
};
I tried many way but can't implement .setSelfDeaf(true) .
Someone please assist?
You can use VoiceState#setSelfDeaf to achieve that. It's pretty easy to do so.
if (message.guild.me.voice.channel) { // Checking if the bot is in a VoiceChannel.
message.guild.me.voice.setSelfDeaf(true); // Using setSelfDeaf to self-deafen the bot.
};
module.exports = {
name: "join",
description: "Joins your voice channel",
category: "music",
execute(message, args) {
if (message.member.voice.channel) {
message.member.voice.channel.join().then((connections) => {
message.guild.me.voice.setSelfDeaf(true);
message.channel.send({
embed: {
color: message.client.messageEmbedData.color,
author: {
name: "✔️ Hey, i joined your voice channel",
},
timestamp: new Date(),
},
});
});
} else {
message.channel.send({
embed: {
color: message.client.messageEmbedData.color,
author: {
name: "❗ You are not in a voice channel",
},
timestamp: new Date(),
},
});
}
},
};
So, I was making a platform for a suggestion channel. The idea was that there is a voting, and when it reaches a such cap, it auto accepts or rejects. I was also making staff can approve or reject. Well, i had a problem in this.
An image of this platform (I censored out the nicknames):
The image
When it reaches the approve cap (10 white check marks), it is supposed to delete the embed and post a new one meaning that the suggestion is approved.
Reproducible sample of code:
client.on("messageReactionAdd", function (messageReaction, member) {
if (member.bot) return;
if (messageReaction.message.channel.id == "516263179446124555") {
if (messageReaction.emoji.name == "✅") {
if (messageReaction.count >= 10) {
messageReaction.message.channel.send("", {embed: {
title: "Suggestion Approved",
description: messageReaction.message.embeds[0].title + "\n" + messageReaction.message.embeds[0].description,
author: {
name: messageReaction.message.embeds[0].author.name,
icon_url: messageReaction.message.embeds[0].author.iconURL
},
color: 3394611,
footer: {
text: "Why: The message got 10 ✅ reactions."
}
}})
}
messageReaction.message.delete();
}
if (messageReaction.emoji.name == "516258169035554817") {
if (messageReaction.count >= 8) {
messageReaction.message.channel.send("", {embed: {
title: "Suggestion sent to Staff",
description: messageReaction.message.embeds[0].title + "\n" + messageReaction.message.embeds[0].description,
author: {
name: messageReaction.message.embeds[0].author.name,
icon_url: messageReaction.message.embeds[0].author.iconURL
},
color: 16764006,
footer: {
text: "Why: The message got 8 <:neutral:516258169035554817> reactions."
}
}})
}
messageReaction.message.guild.channels.get("517331518843125760").send("", {embed: {
title: "Suggestion to check",
description: messageReaction.message.embeds[0].title + "\n" + messageReaction.message.embeds[0].description,
author: {
name: messageReaction.message.embeds[0].author.name,
icon_url: messageReaction.message.embeds[0].author.iconURL
},
color: 16764006,
footer: {
text: "Approving/disapproving this won't change the embed in <#516263179446124555>."
}
}})
messageReaction.message.delete();
}
if (messageReaction.emoji.name == "516258587845328906") {
if (messageReaction.count >= 7) {
messageReaction.message.channel.send("", {embed: {
title: "Suggestion Rejected",
description: messageReaction.message.embeds[0].title + "\n" + messageReaction.message.embeds[0].description,
author: {
name: messageReaction.message.embeds[0].author.name,
icon_url: messageReaction.message.embeds[0].author.iconURL
},
color: 16724736,
footer: {
text: "Why: The message got 7 <:bad:516258587845328906> reactions."
}
}})
}
}
if (messageReaction.emoji.name == "☑") {
var staffMemberReacted = false;
messageReaction.message.guild.members.forEach(function(GuildMember) {
if (messageReaction.users.keyArray().includes(GuildMember.user) && (GuildMember.roles.has("501752627709870080") || GuildMember.roles.has("493436150019784704"))) {
staffMemberReacted = true;
}
})
console.log("reached manapprove")
if (staffMemberReacted) {
messageReaction.message.channel.send("", {embed: {
title: "Suggestion Approved",
description: messageReaction.message.embeds[0].title + "\n" + messageReaction.message.embeds[0].description,
author: {
name: messageReaction.message.embeds[0].author.name,
icon_url: messageReaction.message.embeds[0].author.iconURL
},
color: 3394611,
footer: {
text: "Why: A owner or co-owner manually approved it."
}
}})
messageReaction.message.delete();
}
}
if (messageReaction.emoji.name == "517327626373824522") {
var staffMemberReacted = false;
messageReaction.message.guild.members.forEach(function(GuildMember) {
if (messageReaction.users.keyArray().includes(GuildMember.user) && (GuildMember.id || GuildMember.roles.find)) {
staffMemberReacted = true;
}
})
if (staffMemberReacted) {
messageReaction.message.channel.send("", {embed: {
title: "Suggestion Rejected",
description: messageReaction.message.embeds[0].title + "\n" + messageReaction.message.embeds[0].description,
author: {
name: messageReaction.message.embeds[0].author.name,
icon_url: messageReaction.message.embeds[0].author.iconURL
},
color: 16724736,
footer: {
text: "Why: A owner or co-owner manually rejected it."
}
}})
messageReaction.message.delete();
}
}
}
})
When adding a console.log of it reaching, heroku logs don't put out anything. I was looking for the problem for over a hour.
Please never do this.
Discord.js has a guide on what to do in this situation https://discordjs.guide/#/popular-topics/reactions?id=awaiting-reactions
I would follow their example and use message.awaitReactions To sum it up, use the filter to set the possible reactions you will consider, makes everything much easier.
This is from that link.
message.react('👍').then(() => message.react('👎'));
const filter = (reaction, user) => {
return ['👍', '👎'].includes(reaction.emoji.name) && user.id === message.author.id;
};
message.awaitReactions(filter, { max: 1, time: 60000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === '👍') {
message.reply('you reacted with a thumbs up.');
}
else {
message.reply('you reacted with a thumbs down.');
}
})
.catch(collected => {
console.log(`After a minute, only ${collected.size} out of 4 reacted.`);
message.reply('you didn\'t react with neither a thumbs up, nor a thumbs down.');
});