Javascript: Anti-spam Automoderator (Discord.js) - javascript

I am coding a multipurpose Discord bot to replace some of the more minor ones, and I am looking for a piece of code for a feature that recognizes repeated messages or messages sent in a very short time period (let's say 5000ms).
Here is what could be used to implement this idea.
client.on("message", (message) => {
//let's use something like a spam variable for 10 or more messages sent within 5000ms
if(message.content === spam) {
message.reply("Warning: Spamming in this channel is forbidden.");
console.log(message.author.username + " (" + message.author.id + ") has sent 10 messages or more in 5 seconds in " + message.channel.name + ".");
}
});
For reference, I also made a feature that deletes messages, using a ~delete [n] command. It looks like this:
//this will only delete one message in the channel, the most recent one.
message.delete(1000);
//1000 represents the timeout duration. it will only delete one message, regardless of the value.
//we can delete multiple messages with this, but note it has to come before the reply message.
message.channel.bulkDelete(11);
I was thinking of somehow combining the delete command with recognizing spam messages. If you have any ideas, that would be perfect.

Try This:
const usersMap = new Map();
const LIMIT = 7;
const DIFF = 5000;
client.on('message', async(message) => {
if(message.author.bot) return;
if(usersMap.has(message.author.id)) {
const userData = usersMap.get(message.author.id);
const { lastMessage, timer } = userData;
const difference = message.createdTimestamp - lastMessage.createdTimestamp;
let msgCount = userData.msgCount;
console.log(difference);
if(difference > DIFF) {
clearTimeout(timer);
console.log('Cleared Timeout');
userData.msgCount = 1;
userData.lastMessage = message;
userData.timer = setTimeout(() => {
usersMap.delete(message.author.id);
console.log('Removed from map.')
}, TIME);
usersMap.set(message.author.id, userData)
}
else {
++msgCount;
if(parseInt(msgCount) === LIMIT) {
message.reply("Warning: Spamming in this channel is forbidden.");
message.channel.bulkDelete(LIMIT);
} else {
userData.msgCount = msgCount;
usersMap.set(message.author.id, userData);
}
}
}
else {
let fn = setTimeout(() => {
usersMap.delete(message.author.id);
console.log('Removed from map.')
}, TIME);
usersMap.set(message.author.id, {
msgCount: 1,
lastMessage : message,
timer : fn
});
}
})

Related

Having an issue with randomization in Discord JS

so i've been trying to make it so that every time the user sends a message there's a 50/50 chance that the bot reacts with an emoji, however the number is only picked every time i restart the bot. any ideas on how i can make it pick the number every time the command is triggered?
i tried to use setInterval but that didn't work so idk
here code;
const userID = "user id"
let random = Math.floor(Math.random()*2)
client.on('messageCreate', (message) => {
if(random === 1) {
if(message.author.id === userID) {
message.react('emoji');
}
}
});
Simply, define the random variable inside the messageCreate event.
Example:
const userID = "user id";
client.on('messageCreate', (message) => {
let random = Math.floor(Math.random() * 2);
if (random === 1) {
if (message.author.id === userID) {
message.react('emoji');
}
}
});
If you define random inside of the messageCreate event it means that a new random number is generated each time the even is called.
const userID = "user id"
client.on('messageCreate', (message) => {
let random = Math.floor(Math.random()*2)
if(random === 1) {
if(message.author.id === userID) {
message.react('emoji');
}
}
});
As Tyler2P has already shown an example, just wanted to explain why this works.
Thanks

waiting for reply gives error (time out) after reply. Discord.js

I'm creating a discord bot and I'm trying to create a bot in which you can adopt children (in my code you can get up to 5 children).
Now I have no idea if I'm even doing it the correct way but it looks like it should be working. I'm a kinda beginner in JS.
I found the code I'm using as example here.
I then edited it to work with my code. The error I get is if the mentioned user answers with yes, my bot responds with "They didn't respond in time. try again later" while it should be "you're now adopted".
Here is my code:
else if (message.content.startsWith(`${prefix}adopt`)) {
let filter = m => m.author.id === message.mentions.users.first().id
let marryEmbed = new discord.MessageEmbed();
marryEmbed.setDescription(mentioned.username + ', ' + randomadopt + `\`YES\` / \`NO\``)
marryEmbed.setColor()
marryEmbed.setTimestamp()
message.channel.send(marryEmbed).then(() => {
//console.log(rUser, rMentioned)
message.channel.awaitMessages(filter, {
max: 1,
time: 30000,
errors: ['time']
})
.then(message => {
message = message.first()
if (message.content.toUpperCase() == 'YES' || message.content.toUpperCase() == 'Y') {
let replyembed = new discord.MessageEmbed();
replyembed.setColor()
replyembed.setDescription(randomAdopted)
replyembed.setTimestamp()
if (!rUser.child1) {
if(!rUser.partner){
{code here}
else{
{code here}
}
}
else if (!rUser.child2) {
if(!rUser.partner){
{code here}
}
else{
{code here}
}
}
} else if (message.content.toUpperCase() == 'NO' || message.content.toUpperCase() == 'N') {
let replyembed = new discord.MessageEmbed();
replyembed.setColor()
replyembed.setDescription('guess they\'ll stay homeless for a bit longer.')
replyembed.setTimestamp()
message.channel.send(replyembed)
//message.reply('keep your head up, you\'re too good for them')
} else {
message.channel.send(`Terminated: Invalid Response`)
}
})
.catch(collected => {
let noreplyembed = new discord.MessageEmbed();
noreplyembed.setColor()
noreplyembed.setDescription('They didn\'t respond in time. try again later')
noreplyembed.setTimestamp()
message.channel.send(noreplyembed)
console.log()
//message.reply('No answer after 30 seconds, request canceled.');
});
})
}
}

Not finding an easy solution to unban command for Discord Bot

I have been trying to get the unban command to work for the past 2 days, but I haven't found an easy solution for it, I keep getting errors like ".find()" isn't a function, or can't define "id". And I just don't get what I need to do. PS.: I am a noobie when it comes to code.
It's also worth mentioning that I have gone through many variations of this code and I have ended at this, probably previous iterations of the code were closer to the actual solution.
const Discord = require('discord.js');
const client = new Discord.Client();
const prefix = "+";
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on('message', msg => {
const { content } = msg;
if (!content.startsWith(prefix)) return;
const args = content.slice(prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
switch(command) {
case "ping" : {
let latency = Date.now() - msg.createdTimestamp;
let latencyOfAPI = Math.round(client.ws.ping);
msg.reply("This is the latency between the message and the response: " + latency + "." + "\nThis is the API latency: " + latencyOfAPI + ".");
break;
}
case "pong" : {
msg.reply("ping");
break
}
case "ban" : {
const user = msg.mentions.members.first();
if (user) {
msg.guild.members.ban(user);
msg.reply("The user " + user + " has been banned.")
} else {
return msg.reply("There is no one to ban.").catch(console.error);
}
break
}
case "unban" : {
const user = client.users.cache.find(user => user.username == "").id;
let banList = msg.guild.fetchBans();
if(banList = 0) {
return msg.reply("This user isn't in the community, or he is not banned.");
} else {
banList.find(user)
msg.guild.members.unban(user);
msg.reply("User " + user + " has been unbanned.")
}
break
}
}
});
client.login('.....');
Try this:
case "unban" : {
const user = client.users.fetch(args[1]).catch((err) => console.log(err));
user.then((u) => {
if (!args[1]) {
return msg.reply("Enter ID to unban")
} else {
if (u) {
msg.guild.members.unban(u).then(() => {
msg.reply("The user " + u.username + " has been unbanned.")
}).catch((err) => console.log(err))
} else {
return msg.reply("Cannot Find User")
}
}
})
break
Usage: [prefix]unban [ID] e.g [prefix]unban 3426743678738 (type in text channel)
Tip #1: Try to use .then() & .catch() on function which return a promise. You can use .then() to confirm that you've successfully unbanned a user and .catch() to see why there was a issue with unbanning a user.
Tip #2: Make an if statement which checks if the user running this command has the right permissions before trying the code i.e BAN_MEMBERS & ADMINISTRATOR
Also Note: .fetchBans() returns a collection and Promise

My bot keeps spamming the same message. What is wrong?

const Discord = require("discord.js");
const client = new Discord.Client();
const ayarlar = require("./ayalar.json");
let takipedilen = "648424230081265664";
let onlinetakipedilen = 648424230081265664;
let hesap = "648424230081265664";
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on("presenceUpdate", (oldMember, newMember) => {
if (!oldMember.id == onlinetakipedilen) return;
if (oldMember.id == onlinetakipedilen) {
if (oldMember.presence.status != newMember.presence.status) {
var interval = setInterval(function () {
// use the message's channel (TextChannel) to send a new message
client.guilds
.get("812505935280472084")
.channels.get("812506306321580062")
.send("**" + `${newMember.user.username}` + "**" + " " + "şuanda" + " " + `${newMember.presence.status}`)
.catch(console.error); // add error handling here
}, 1000);
}
}
});
This my code and it's spamming the same thing to my text channel.
This is the result;
You're doing the first evaluation kind of wrong.
Instead of doing this:
if(!oldMember.id == onlinetakipedilen) return;
try:
if(oldMember.id !== onlinetakipedilen) return;
The issue is because onlinetakipedilen is an Integer, not a String.
Replace 5th line with:
let onlinetakipedilen = "648424230081265664";
If you are wondering why this is happening please read What is JavaScript's highest integer value that a number can go to without losing precision?.
You're also comparing a Boolean to an Integer.
if (oldMember.id !== onlinetakipedilen)
Equality comparisons and sameness

How to update 'bot.users.size' in bot status without restarting

So basically I want my bot to have a dynamic status that changes every 5 seconds and displays how many users my bot is currently helping. The changing status part is not the issue, the problem is the users helped count does not change without restarting my bot, which is not ideal considering it is hosted and on many servers, no point restarting all the time just for the user count to be accurate.
What I have tried is by including a interval timer that will update the userCount variable in an attempt to make it accurate to how many users it is helping. What seems to be happening is when a user joins the server, the variable will update accordingly and display +1 in relation to the previous number of users helped. But, when a user leaves, it does not subtract one from the count, instead, it just leaves it at the previous count. I included console.log(userCount) just to make it easier to see the number every 10 seconds in the console, instead of having to wait for the bot's status to change to the proper one.
bot.on('ready', function() {
let userCount = bot.users.size
setInterval(() => {
userCount = bot.users.size
console.log(userCount)
}, 10000);
setInterval(async () => {
let statuslist = [
'blah',
"blah'",
'blah ' + ` ${userCount} Users`
];
const random = Math.floor(Math.random() * statuslist.length);
try {
await bot.user.setPresence({
game: {
name: `${statuslist[random]}`,
type: "Playing"
},
status: "online"
});
} catch (error) {
console.error(error);
}
}, 5000);
console.log("Logged in as " + bot.user.username);
});
I feel as though this isn't a library issue, because I am not very confident in my ability to create code that checks for changes. Ideally, it will display the accurate number based on users joining/leaving servers the bot is on, as well as guilds inviting/removing the bot from the guild. I am not sure if I should use events for this, and even if I was to, I do not know how I could.
But, when a user leaves, it does not subtract one from the count, instead, it just leaves it at the previous count.
This is expected of client.users. It's a collection of all the users the client has cached at some point, so it shouldn't remove any. I think what you're looking for is this...
bot.on('ready', () => {
setInterval(async () => {
let users = 0;
for (let g of bot.guilds.array()) users += (g.members.size - 1));
await bot.user.setActivity(`${users} user${users !== 1 ? 's' : ''}`, {type: 'WATCHING'})
.catch(err => console.error());
}, 15000);
});
Note that this will count users over again if they're in 2 guilds. If you'd rather have a precise count, at the cost of memory, you could use...
bot.on('ready', () => {
setInterval(() => {
let guilds = bot.guilds.array();
let users = [];
for (var i = 0; i < guilds.length; i++) {
let members = guilds[i].members.array();
for (var i = 0; i < members.length; i++) {
if (members[i].user.id !== bot.user.id && users.indexOf(members[i].user.id) === -1) users.push(members[i].user.id);
}
}
bot.user.setActivity(`${users.length} user${users.length !== 1 ? 's' : ''}`, {type: 'WATCHING'})
.catch(err => console.error());
});
});
You have 2 setIntervals, combine them!
That should solve your issue.
You could also use the guildMemberAdd / guildMemberRemove event.
bot.on('ready', function() {
setInterval(async () => {
const statuslist = [
'blah',
'blah_1',
` ${bot.users.size} Users`,
];
console.log(statuslist);
const random = Math.floor(Math.random() * statuslist.length);
try {
await bot.user.setPresence({
game: {
name: `${statuslist[random]}`,
type: 'Playing',
},
status: 'online',
});
}
catch (error) {
console.error(error);
}
}, 15000);
console.log('Logged in as ' + bot.user.username);
});

Categories

Resources