I am making a Discord bot that informs moderators when a user joins a specific voice channel. The bot is supposed to also have spam protection such that it will only log a message once per minute per user.
This is what I have tried before:
const { Client } = require("discord.js");
const { config } = require("dotenv");
const fs = require('fs');
const client = new Client({
partials: ['MESSAGE', 'CHANNEL', 'REACTION']
});
config({
path: __dirname + "/.env"
})
var supportchannel = '827574015526567947'
var dutychannel = '847445933969113118'
var ondutyrole = '847447374925398016'
client.on("ready", () => {
console.log(`Hi, ${client.user.username} is now online!`);
global.timer = 0;
client.user.setStatus('online');
client.user.setActivity('me getting developed', { type: "WATCHING"})
.then(presence => console.log('status set'))
.catch(console.error);
});
client.on('voiceStateUpdate', (oldMember, newMember) => {
let newUserChannel = newMember.channelID;
let oldUserChannel = oldMember.channelID;
if (newUserChannel === supportchannel) {
if (timer == 0) {
timer = 1
setTimeout(() => {
timer = 0
}, 60000);
const Userfm = client.users.cache.get(newMember.id);
if (Userfm) {
const channelfx = client.channels.cache.get(dutychannel)
let roleId = ondutyrole
channelfx.send(`<@&${roleId}> **${Userfm.tag}** requires Support`);
}
} else {
return;
}
}
console.log("User joined vc with id "+newUserChannel)
});
client.login(process.env.TOKEN);
This doesn't work the way I intended because the cooldown is not separate for every user; instead all users share a cooldown. This blocks every user from getting a moderator's attention for 60 seconds.
I thought that the code ran asynchronously for every user.
The same goes for this code in which I made use of the wait-sync
npm library:
const { Client } = require("discord.js");
const { config } = require("dotenv");
const fs = require('fs');
const waitSync = require('wait-sync');
const client = new Client({
partials: ['MESSAGE', 'CHANNEL', 'REACTION']
});
config({
path: __dirname + "/.env"
})
var supportchannel = '827574015526567947'
var dutychannel = '847445933969113118'
var ondutyrole = '847447374925398016'
client.on("ready", () => {
console.log(`Hi, ${client.user.username} is now online!`);
global.timer = 0;
client.user.setStatus('online');
client.user.setActivity('me getting developed', { type: "WATCHING"})
.then(presence => console.log('status set'))
.catch(console.error);
});
client.on('voiceStateUpdate', (oldMember, newMember) => {
let newUserChannel = newMember.channelID;
let oldUserChannel = oldMember.channelID;
if (newUserChannel === supportchannel) {
const Userfm = client.users.cache.get(newMember.id);
if (Userfm) {
const channelfx = client.channels.cache.get(dutychannel)
let roleId = ondutyrole
channelfx.send(`<@&${roleId}> **${Userfm.tag}** requires Support`);
waitSync(60);
}
}
console.log("User joined vc with id "+newUserChannel)
});
client.login(process.env.TOKEN);
If you know how to solve this problem please let me know.
What you can do is probably to have some sort of mapping that keeps track of the timer for each user and have the user IDs be the keys:
const timers = {};
client.on('voiceStateUpdate', (oldMember, newMember) => {
...
// If we don't have any timer set for this user, go ahead and set it
if (!timers[newMember.id]) {
timers[newMember.id] = 1;
setTimeout(() => {
// Delete the timer from the mapping
delete timers[newMember.id];
}, 60000);
...