Discord.js v13 send a message when kicked from the voice channel - discord.js

I'm trying to make a code that the bot send a message when is disconnected from voice channel for someone, but the bot is also sending this message when i use the quit command, there's a way to execute that code only when the bot gets kicked from voice channel by someone, and not by command?
My code:
client.on('voiceStateUpdate', async (oldState, newState) => {
if(oldState.channelId === newState.chanelId) return console.log('Mute/Deafen Update');
if(!oldState.channelId && newState.channelId) return console.log('Connection Update');
if(oldState.channelId && !newState.channelId){
console.log('Disconnection Update');
if(newState.id === client.user.id) return (
await queue.destroy(),
interaction.channel.send("I've kicked from the voice channel")
)
}
});

Define it like that :
const fetchedLogs = await (oldMember, newMember).guild.fetchAuditLogs({
limit: 1,
type: 'MEMBER_DISCONNECT',
});
const disconnectLog = fetchedLogs.entries.first();
// console.log(disconnectLog)
const { executor } = disconnectLog;
Be careful, it will get an executor also when nobody kick the bot, so you have to compare the log's timestamp with the leave's timestamp.

Related

Discordjs: how to listen for messages on a specific channel

I am building a discord bot to listen to messages on a specific channel. The issue is that my code listens to all channels.
Even if I use a condition to check for the channel id before picking the message, it means it will do more work than is necessary.
I want to avoid the case of selecting messages from multiple channels and just concentrate on the messages in the channel I want to listen to.
require('dotenv').config();
const { Client, Intents, Collection } = require('discord.js');
const {TOKEN, CHANNEL_ID} = require('./src/config/index');
const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES],
});
client.once('ready', (c) => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
client.on('messageCreate', async (message) => {
console.log(message)
})
client.login(TOKEN);
This code above is the current code I am using
You can check where the message was posted before running any code.
As far as i am aware that is the only way to do this
client.on('messageCreate', async (message) => {
if (message.channel.id === "YOUR CHANNEL ID") {
// run code here
}
})
There are three ways of sending a message to a specific channels.
//1. Single channel listener
client.on('messageCreate', async (message) => {
if (message.channel.id === "channel_id") {
//For a single channel listener.
} else {
//You can send a message if the channel_id is not equal.
}
})
//2. Multiple channel listener / can be use as .json
let channels = [
"channel_id",
"channel_id"
]
if(channels.includes(message.channel.id)) {
//Multiple Channel ID's
} else {
//An example of return for not including some channel_id
message.channel.send("I can't use these command on this channel.")
}
//3. Can be use like using a database such as mongodb / mongoose / etc.
let channels = {
"chan": [
"987627957478637619",
"948780253948575764"
]
}
if(channels?.chan.includes(message.channel.id)) {
//Multiple Channel ID's
} else {
//An example of return for not including some channel_id
message.channel.send("I can't use these command on this channel.")
}
This is my code, pretty simple and it works.
let allowedChannels = [
/*bot-channel*/"1053346645779152993",
/*console*/"1053346646227959900"
];
client.on('messageCreate', msg => {
//VERY important, exit if the message is from a bot to prevent loops
if (msg.author.bot) {
return;
};
//Check if the channel is accepting bot commands
if (allowedChannels.includes(msg.channel.id) === false) {
return;
}
}

Setting a timeout to delete a message embed on discord.js

I have a basic ticketing system for a suggestions channel.
Ideally, when a user does .exesuggest <whatever suggestion they want> (.exe is the bot prefix), I want the bot to reply that the ticket has been sent to staff, i want the bot to delete the user's message, and to delete it's own message after 5 seconds. At the same time, the bot will send a message with the suggestion's author and the suggestion itself into a staff channel.
At the moment everything is working except for the bot deleting it's own message after 5 seconds.
Here is my code:
const Discord = require("discord.js")
const channelId = '873769980729106442'
const check = '✅'
let registered = false
const registerEvent = client => {
if (registered) {
return
}
registered = true
client.on('messageReactionAdd', (reaction, user) => {
if (user.bot) {
return
}
const { message } = reaction
if (message.channel.id === channelId) {
message.delete()
}
})
}
module.exports = {
commands: ['ticket', 'suggest', 'suggestion'],
minArgs: 1,
expectedArgs: '<message>',
callback: (userMessage, arguments, text, client) => {
const { guild, member } = userMessage
registerEvent(client)
const channel = guild.channels.cache.get(channelId)
const newTicketEmbed = new Discord.MessageEmbed()
.setAuthor(userMessage.author.username)
.setTitle('Created a new ticket.')
.setDescription(`"${text}"`)
.setFooter(`Click the ${check} icon to delete this message.`)
channel.send(newTicketEmbed).then(ticketMessage => {
ticketMessage.react(check)
const replyEmbed = new Discord.MessageEmbed()
.setDescription(`<#${member.id}> Your ticket has been created! Expect a reply soon!`)
userMessage.channel.send(replyEmbed)
})
}
}
I have a working command base handler in another file that makes the command work.
I just need to know exactly how to make that bot's reply in replyEmbed to be deleted after 5 seconds.
You can use a setTimeout function to delay the <message>.delete() function from executing.
Example:
setTimeout(function() { // Setup a timer
userMessage.delete(); // Deletes the users message
ticketMessage.delete(); // Deletes the ticket message
}, 5000); // 5 seconds in milliseconds
Full example:
const Discord = require("discord.js")
const channelId = '873769980729106442'
const check = '✅'
let registered = false
const registerEvent = client => {
if (registered) return;
registered = true
client.on('messageReactionAdd', (reaction, user) => {
if (user.bot) return;
const { message } = reaction
if (message.channel.id === channelId)
message.delete()
});
}
module.exports = {
commands: ['ticket', 'suggest', 'suggestion'],
minArgs: 1,
expectedArgs: '<message>',
callback: (userMessage, arguments, text, client) => {
const { guild, member } = userMessage
registerEvent(client)
const channel = guild.channels.cache.get(channelId)
const newTicketEmbed = new Discord.MessageEmbed()
.setAuthor(userMessage.author.username)
.setTitle('Created a new ticket.')
.setDescription(`"${text}"`)
.setFooter(`Click the ${check} icon to delete this message.`)
channel.send(newTicketEmbed).then(ticketMessage => {
ticketMessage.react(check)
const replyEmbed = new Discord.MessageEmbed()
.setDescription(`<#${member.id}> Your ticket has been created! Expect a reply soon!`)
userMessage.channel.send(replyEmbed);
setTimeout(function() { // Setup a timer
userMessage.delete(); // Deletes the users message
ticketMessage.delete(); // Deletes the ticket message
}, 5000); // 5 seconds in milliseconds
});
}
}
In Discord.js v13 you have to use setTimeout.
You can implement what you want like this:
userMessage.channel.send(replyEmbed).then(msg => {
setTimeout(() => msg.delete(), 5000);
});// It will delete after 5 seconds
It might work.
Message.delete has an options argument which is an object, and you can set the timeout there (v13 doesn’t have this!):
userMessage.delete({timeout: 5000}) //deletes after 5000 ms
v13 must use setTimeout since the feature was removed
setTimeout(() => userMessage.delete(), 5000) //deletes after 5000 ms

How do I make suggest command public to all servers? discord.js

I have a suggest command on my bot that im working on. However it only works when the user suggesting is in my server since it is codded to send the suggestion to a specific channel id. Is there a way to code it where the suggestion comes to my dms or specified channel even if the user suggesting isn't in the server? here is my code:
const { MessageEmbed } = require("discord.js")
module.exports.run = async (client, message, args) => {
if (!args.length) {
return message.channel.send("Please Give the Suggestion")
}
let channel = message.guild.channels.cache.find((x) => (x.name === "sauce-supplier-suggestions" || x.name === "sauce-supplier-suggestions"))
if (!channel) {
return message.channel.send("there is no channel with name - sauce-supplier-suggestions")
}
let embed = new MessageEmbed()
.setAuthor("SUGGESTION: " + message.author.tag, message.author.avatarURL())
.setThumbnail(message.author.avatarURL())
.setColor("#ff2050")
.setDescription(args.join(" "))
.setTimestamp()
channel.send(embed).then(m => {
m.react("✅")
m.react("❌")
})
message.channel.send("sucsessfully sent your suggestion to bot team thank you for your suggestion!!")
}
I made some small changes in your code. Now if a user uses the command correctly, the bot will send you a DM with the users suggestion.
const { MessageEmbed } = require("discord.js")
module.exports.run = async (client, message, args) => {
let suggestion = args.join(" ");
let owner = client.users.cache.get("YOUR ID");
if (!suggestion) {
return message.channel.send("Please Give the Suggestion")
}
let channel = message.guild.channels.cache.find((x) => (x.name === "sauce-supplier-suggestions" || x.name === "sauce-supplier-suggestions"))
if (!channel) {
return message.channel.send("there is no channel with name - sauce-supplier-suggestions")
}
let embed = new MessageEmbed()
.setAuthor("SUGGESTION: " + message.author.tag, message.author.displayAvatarURL({ dynamic: true }))
.setThumbnail(message.author.displayAvatarURL({ dynamic: true }))
.setColor("#ff2050")
.setDescription(suggestion)
.setTimestamp()
owner.send(embed).then(m => {
m.react("✅")
m.react("❌")
})
message.channel.send("sucsessfully sent your suggestion to bot team thank you for your suggestion!!")
}

How to make a bot that deletes a message and posts it in another channel based on reactions

I'm trying to make it so when my bot picks up a reaction in a specific channel, it'll see if it hit 10 reactions on a specific reaction. Then it'll delete the reacted message and post it into another specific channel with a message attached to it.
Here's the code
doopliss.on('message', message => {
if (message.channel.id === "587066921422290953") {
setTimeout(function(){
message.react(message.guild.emojis.get('587070377696690177'))
}, 10)
setTimeout(function(){
message.react(message.guild.emojis.get('587071853609353256'))
}, 50)
setTimeout(function(){
message.react(message.guild.emojis.get('587070377704816640'))
}, 100)
}
});
const message = require("discord.js");
const emoji = require("discord.js");
const reaction = require("discord.js");
doopliss.on('message', message => {
if (message.channel.id === "587066921422290953") {
let limit = 2; // number of thumbsdown reactions you need
if (message.reaction.emoji.name == message.guild.emojis.get('587070377696690177')
&& reaction.count >= limit) message.reaction.message.delete();
let tcontent = message.reaction.message.content
let accept = message.guild.channels.get('587097086256873483')
accept.send(`${tcontent} \`\`\`This server suggestion has been accepted by the community! Great job! Now a staff member just needs to forward it to username.\`\`\``)
}})
Can't figure out how to do this.
Expected Result: Bot sees if post has 10 reactions, then delete it and take the same message to a different channel
Actual Result: An error occurs Cannot read 'channel' property
First I want to say that some question here like this one have what you search.
Moreover, the discord documentation and the guide provide an awaiting reactions section.
There is some other question that refer to the subject or the function used in the guide and by searching a bit you can even find question like this one which is almost the same thing as you.
However, here is a complete example of what you want to do. You can add a timer to the promise instead of just waiting. I didn't use the reaction collector because promise are a bit faster, but you can also create a management system of multiple collector , or use the client.on('messageReactionAdd').
const Discord = require('discord.js');
const config = require('./config.json');
const channelSuggestion = '<channelID>';
const channelSend = '<channelID>';
const emojiReact = '<emojiID>';
const prefixSuggestion = '!';
const reactionMax = 11;
const client = new Discord.Client();
client.on('ready', () => {
console.log('Starting!');
client.user.setActivity(config.activity);
});
client.on('message', (msg) => {
if ((msg.content[0] === prefixSuggestion) && (msg.channel.type === 'dm')){
sendSuggestion(msg);
}
});
function filter(reaction) {
return reaction.emoji.id === emojiReact;
}
function moveSuggestion(msg) {
client.channels.get(channelSend).send(msg.content)
.then(() => msg.delete()).catch(err => console.log(error));
}
function sendSuggestion(msg){
client.channels.get(channelSuggestion).send(msg.content.substr(1))
.then((newMsg) => newMsg.react(emojiReact))
.then((newMsgReaction) =>
newMsgReaction.message
.awaitReactions(filter, {max: reactionMax})//, time: 15000, errors: ['time']})
.then(collected => {
moveSuggestion(newMsgReaction.message);
})
// .catch(collected => {
// console.log(`After a minute, only ${collected.size} out of 10 reacted.`);
// })
);
}
client.login(config.token)
.then(() => console.log("We're in!"))
.catch((err) => console.log(err));
The bot will listen to dm message (I don't know how you want your bot to send the suggestion message, so I made my own way) which start with a !.
Then the bot will send a message to a specific channel, wait for N person to add a reaction, and then will send the message to another channel.

How to get reaction collector on embed sent by the bot

I was using something like this but i want it to look for reactions in the embed sent! not in the message
const collector = message.createReactionCollector((reaction, user) =>
user.id === message.author.id &&
reaction.emoji.name === "◀" ||
reaction.emoji.name === "▶" ||
reaction.emoji.name === "❌"
).once("collect", reaction => {
const chosen = reaction.emoji.name;
if(chosen === "◀"){
// Prev page
}else if(chosen === "▶"){
// Next page
}else{
// Stop navigating pages
}
collector.stop();
});
A RichEmbed is sent as part of a message. Therefore, when you add a reaction, it's on the message, not the embed.
See the example below which gives the appearance of reactions on an embed.
const { RichEmbed } = require('discord.js');
var embed = new RichEmbed()
.setTitle('**Test**')
.setDescription('React with the emojis.');
message.channel.send(embed)
.then(async msg => {
// Establish reaction collector
for (emoji of ['◀', '▶', '❌']) await msg.react(emoji);
})
.catch(console.error);

Resources