From c74203d7717d257e16ab06e5c0dc645a057b9bd3 Mon Sep 17 00:00:00 2001 From: Michal Date: Tue, 16 Nov 2021 14:40:18 +0100 Subject: [PATCH] 2.6.0 release --- CONTRIBUTING.md | 18 +++++++ README.md | 91 +++++++++++++++++++++++---------- docs/index.html | 8 +-- index.d.ts | 2 - index.js | 132 +++++++++++++++++++++++++++++++----------------- package.json | 8 ++- 6 files changed, 177 insertions(+), 82 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..602bf99 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,18 @@ +# Contributing to Discord-anti-spam (DAS) +👍🎉 First off, thanks for taking the time to contribute! 🎉👍 + +#### Table Of Contents + +[Code of Conduct](#code-of-conduct) + +## How Can I Contribute? + +### Reporting Bugs + +This section guides you through submitting a bug report for Atom. Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior :computer: :computer:, and find related reports :mag_right:. + +> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. + +### Creating pr's + +Make sure to keep it clear so that the team and see it clear what you change. You're not required to keep it short but it's recommended! Also every pr needs a review before merge by a maintainer. diff --git a/README.md b/README.md index 9ac2972..432e7de 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ # discord-anti-spam.js A simple module with quick setup and different options to implement anti-spam features in your bot. +**This version of the package will only support discord.js v13** ## Installation @@ -21,37 +22,73 @@ You can see the package documentation [**here**](https://discord-anti-spam.js.or Example of a basic bot handling spam messages using this module. ```js -const Discord = require('discord.js'); -const client = new Discord.Client(); -const AntiSpam = require('discord-anti-spam'); +const Discord = require("discord.js"); +const client = new Discord.Client({ + intents: [Discord.Intents.FLAGS.GUILDS, Discord.Intents.FLAGS.GUILD_MESSAGES], +}); +const AntiSpam = require("discord-anti-spam"); const antiSpam = new AntiSpam({ - warnThreshold: 3, // Amount of messages sent in a row that will cause a warning. - muteThreshold: 4, // Amount of messages sent in a row that will cause a mute - kickThreshold: 7, // Amount of messages sent in a row that will cause a kick. - banThreshold: 7, // Amount of messages sent in a row that will cause a ban. - maxInterval: 2000, // Amount of time (in milliseconds) in which messages are considered spam. - warnMessage: '{@user}, Please stop spamming.', // Message that will be sent in chat upon warning a user. - kickMessage: '**{user_tag}** has been kicked for spamming.', // Message that will be sent in chat upon kicking a user. - muteMessage: '**{user_tag}** has been muted for spamming.',// Message that will be sent in chat upon muting a user. - banMessage: '**{user_tag}** has been banned for spamming.', // Message that will be sent in chat upon banning a user. - maxDuplicatesWarning: 6, // Amount of duplicate messages that trigger a warning. - maxDuplicatesKick: 10, // Amount of duplicate messages that trigger a warning. - maxDuplicatesBan: 12, // Amount of duplicate messages that trigger a warning. - maxDuplicatesMute: 8, // Ammount of duplicate message that trigger a mute. - ignoredPermissions: [ 'ADMINISTRATOR'], // Bypass users with any of these permissions. - ignoreBots: true, // Ignore bot messages. - verbose: true, // Extended Logs from module. - ignoredMembers: [], // Array of User IDs that get ignored. - muteRoleName: "Muted", // Name of the role that will be given to muted users! - removeMessages: true // If the bot should remove all the spam messages when taking action on a user! - // And many more options... See the documentation. + warnThreshold: 3, // Amount of messages sent in a row that will cause a warning. + muteThreshold: 4, // Amount of messages sent in a row that will cause a mute + kickThreshold: 7, // Amount of messages sent in a row that will cause a kick. + banThreshold: 7, // Amount of messages sent in a row that will cause a ban. + maxInterval: 2000, // Amount of time (in milliseconds) in which messages are considered spam. + warnMessage: "{@user}, Please stop spamming.", // Message that will be sent in chat upon warning a user. + kickMessage: "**{user_tag}** has been kicked for spamming.", // Message that will be sent in chat upon kicking a user. + muteMessage: "**{user_tag}** has been muted for spamming.", // Message that will be sent in chat upon muting a user. + banMessage: "**{user_tag}** has been banned for spamming.", // Message that will be sent in chat upon banning a user. + maxDuplicatesWarning: 6, // Amount of duplicate messages that trigger a warning. + maxDuplicatesKick: 10, // Amount of duplicate messages that trigger a warning. + maxDuplicatesBan: 12, // Amount of duplicate messages that trigger a warning. + maxDuplicatesMute: 8, // Ammount of duplicate message that trigger a mute. + ignoredPermissions: ["ADMINISTRATOR"], // Bypass users with any of these permissions. + ignoreBots: true, // Ignore bot messages. + verbose: true, // Extended Logs from module. + ignoredMembers: [], // Array of User IDs that get ignored. + muteRoleName: "Muted", // Name of the role that will be given to muted users! + timeMute: 0, // Amount of time (in minutes) a user will be muted for. + removeMessages: true, // If the bot should remove all the spam messages when taking action on a user! + modLogsEnabled: false, // If to enable modlogs + modLogsChannelName: "mod-logs", // channel to send the modlogs too! + modLogsMode: "embed", + // And many more options... See the documentation. }); -client.on('ready', () => console.log(`Logged in as ${client.user.tag}.`)); +client.on("ready", () => console.log(`Logged in as ${client.user.tag}.`)); -client.on('message', (message) => antiSpam.message(message)); +client.on("messageCreate", (message) => antiSpam.message(message)); -client.login('YOUR_SUPER_SECRET_TOKEN'); +client.login("YOUR_SUPER_SECRET_TOKEN"); +``` + +## Example (As a direct copy template without explanations) + +```js +const antiSpam = new AntiSpam({ + warnThreshold: 3, + muteThreshold: 4, + kickThreshold: 7, + banThreshold: 7, + maxInterval: 2000, + warnMessage: "{@user}, Please stop spamming.", + kickMessage: "**{user_tag}** has been kicked for spamming.", + muteMessage: "**{user_tag}** has been muted for spamming.", + banMessage: "**{user_tag}** has been banned for spamming.", + maxDuplicatesWarning: 6, + maxDuplicatesKick: 10, + maxDuplicatesBan: 12, + maxDuplicatesMute: 8, + ignoredPermissions: ["ADMINISTRATOR"], + ignoreBots: true, + verbose: true, + ignoredMembers: [], + muteRoleName: "Muted", + muteTime: 0, + removeMessages: true, + modLogsEnabled: false, + modLogsChannelName: "mod-logs", + modLogsMode: "embed", +}); ``` ## Support Server @@ -62,8 +99,8 @@ Join our [Support Server](https://discord.gg/KQgDfGr) where we help you with iss If you have any bugs or trouble setting the module up, feel free to open an issue on [Github](https://github.com/Michael-J-Scofield/discord-anti-spam) - ## 📝 License + Copyright © 2019 [Michael-J-Scofield](https://github.com/Michael-J-Scofield)
This project is MIT licensed. diff --git a/docs/index.html b/docs/index.html index 8192c5d..dfe2930 100644 --- a/docs/index.html +++ b/docs/index.html @@ -61,9 +61,9 @@

Installation

Documentation

You can see the package documentation here.

Example

-

Example of a basic bot handling spam messages using this module.

+

Example of a basic bot handling spam messages using this module.\n
The module only supports discord.js v13 and the required intents are: "GUILD_MESSAGES"

const Discord = require('discord.js');
-const client = new Discord.Client();
+const client = new Discord.Client({ intents: [Discord.Intents.FLAGS.GUILDS,Discord.Intents.FLAGS.GUILD_MESSAGES] });
 const AntiSpam = require('discord-anti-spam');
 const antiSpam = new AntiSpam({
 	warnThreshold: 3, // Amount of messages sent in a row that will cause a warning.
@@ -90,7 +90,7 @@ 

Example

client.on('ready', () => console.log(`Logged in as ${client.user.tag}.`)); -client.on('message', (message) => antiSpam.message(message)); +client.on('messageCreate', (message) => antiSpam.message(message)); client.login('YOUR_SUPER_SECRET_TOKEN');
@@ -116,4 +116,4 @@

Bug Reports

- \ No newline at end of file + diff --git a/index.d.ts b/index.d.ts index 4d1b858..9d99122 100644 --- a/index.d.ts +++ b/index.d.ts @@ -85,7 +85,5 @@ declare module 'discord-anti-spam' { modLogsChannelName?: string; modLogsEnabled?: boolean; removeMessages?: boolean; - removeBotMessages?: boolean; - removeBotMessagesAfter?: number; }; } diff --git a/index.js b/index.js index 27ca9af..c4822b1 100644 --- a/index.js +++ b/index.js @@ -42,6 +42,11 @@ const { EventEmitter } = require('events') * @event AntiSpamClient#muteAdd * @property {Discord.GuildMember} member The member that was muted. */ +/** + * Emitted when a member gets unmuted. + * @event AntiSpamClient#muteRemove + * @property {Discord.GuildMember} member The member that was unmuted. + */ /** * Emitted when a member gets banned. @@ -67,12 +72,14 @@ const { EventEmitter } = require('events') * @property {number} [maxDuplicatesBan=11] Amount of duplicate messages that trigger a ban. * * @property {string|Discord.Snowflake} [muteRoleName='Muted'] Name or ID of the role that will be added to users if they got muted. + * @property {number} [unMuteTime='0'] Time in minutes to wait until unmuting a user. 0=never. * @property {string|Discord.Snowflake} [modLogsChannelName='mod-logs'] Name or ID of the channel in which moderation logs will be sent. * @property {boolean} [modLogsEnabled=false] Whether moderation logs are enabled. + * @property {string} [modLogsMode='embed'] Whether send moderations logs in an discord embed or normal message! Options: 'embed' or 'message". * * @property {string|Discord.MessageEmbed} [warnMessage='{@user}, Please stop spamming.'] Message that will be sent in the channel when someone is warned. - * @property {string|Discord.MessageEmbed} [kickMessage='**{user_tag}** has been muted for spamming.'] Message that will be sent in the channel when someone is kicked. - * @property {string|Discord.MessageEmbed} [muteMessage='**{user_tag}** has been kicked for spamming.'] Message that will be sent in the channel when someone is muted. + * @property {string|Discord.MessageEmbed} [kickMessage='**{user_tag}** has been kicked for spamming.'] Message that will be sent in the channel when someone is kicked. + * @property {string|Discord.MessageEmbed} [muteMessage='**{user_tag}** has been muted for spamming.'] Message that will be sent in the channel when someone is muted. * @property {string|Discord.MessageEmbed} [banMessage='**{user_tag}** has been banned for spamming.'] Message that will be sent in the channel when someone is banned. * * @property {boolean} [errorMessages=true] Whether the bot should send a message in the channel when it doesn't have some required permissions, like it can't kick members. @@ -97,8 +104,7 @@ const { EventEmitter } = require('events') * @property {boolean} [debug=false] Whether to run the module in debug mode. * @property {boolean} [removeMessages=true] Whether to delete user messages after a sanction. * - * @property {boolean} [removeBotMessages=false] Whether to delete bot messages after an time. - * @property {number} [removeBotMessagesAfter=2000] Whenever to delete bot messages. IN MILLISECONDS + * @property {boolean} [MultipleSanctions=false] Whether to run sanctions multiple times */ /** @@ -153,9 +159,11 @@ class AntiSpamClient extends EventEmitter { maxDuplicatesBan: options.maxDuplicatesBan || 11, muteRoleName: options.muteRoleName || 'Muted', + unMuteTime: options.unMuteTime || 0, modLogsChannelName: options.modLogsChannelName || 'mod-logs', modLogsEnabled: options.modLogsEnabled || false, + modLogsMode: options.modLogsMode || 'embed', warnMessage: options.warnMessage || '{@user}, Please stop spamming.', muteMessage: options.muteMessage || '**{user_tag}** has been muted for spamming.', @@ -185,7 +193,9 @@ class AntiSpamClient extends EventEmitter { removeMessages: options.removeMessages != undefined ? options.removeMessages : true, removeBotMessages: options.removeBotMessages || false, - removeBotMessagesAfter: options.removeBotMessagesAfter || 2000 + removeBotMessagesAfter: options.removeBotMessagesAfter || 2000, + + MultipleSanctions: options.MultipleSanctions || false, } /** @@ -225,19 +235,30 @@ class AntiSpamClient extends EventEmitter { } /** - * Send a message to the logs channel + * Logs the actions * @ignore * @param {Discord.Message} msg The message to check the channel with - * @param {string} message The message to log + * @param {string} action The action to log * @param {Discord.Client} client The Discord client that will send the message */ - log (msg, message, client) { + log (msg, action, client) { if (this.options.modLogsEnabled) { const modLogChannel = client.channels.cache.get(this.options.modLogsChannelName) || msg.guild.channels.cache.find((channel) => channel.name === this.options.modLogsChannelName && channel.type === 'GUILD_TEXT') - if (modLogChannel) { - modLogChannel.send({ content: message}) + if(modLogChannel) { + if(this.options.modLogsMode == "embed"){ + const embed = new Discord.MessageEmbed() + .setAuthor(`DAS Spam detection`,'https://discord-anti-spam.js.org/img/antispam.png') + .setDescription(`${msg.author}(${msg.author.id}) has been **${action}** for **spam**!`) + .setFooter(`DAS Anti spam`,'https://discord-anti-spam.js.org/img/antispam.png') + .setTimestamp() + .setColor('RED') + modLogChannel.send({embeds:[embed]}) + }else{ + modLogChannel.send(`${msg.author}(${msg.author.id}) has been **${action}** for **spam**.`) + } } + } } @@ -251,38 +272,22 @@ class AntiSpamClient extends EventEmitter { async clearSpamMessages (messages, client) { try { messages.forEach((message) => { - const channel = client.channels.cache.get(message.channelID) + const channel = client.channels.cache.get(message.channelId) if (channel) { - const msg = channel.messages.cache.get(message.messageID) - if (msg && msg.deletable) msg.delete() + const msg = channel.messages.cache.get(message.messageId) + if (msg && msg.deletable) msg.delete().catch(err => { + if(err && this.options.debug == true) console.log(`DAntiSpam (clearSpamMessages#failed): The message(s) couldn't be deleted`) + }) } }) } catch (e) { if(e){ - if (this.options.verbose) { + if (this.options.debug) { console.log(`DAntiSpam (clearSpamMessages#failed): The message(s) couldn't be deleted!`); } } } } - /** - * Delete bot messages - * @ignore - * @param {Discord.Message} message Bot message object to delete - * @returns {Promise} - */ - async clearBotMessages(message){ - if(this.options.removeBotMessages == false) return; - try { - setTimeout(function(){message.delete() }, this.options.removeBotMessagesAfter); - } catch(e){ - if(this.options.verbose){ - if (this.options.verbose) { - console.log(`DAntiSpam (clearBotmMessages#failed): The message(s) couldn't be deleted!`); - } - } - } - } /** * Ban a user. @@ -307,8 +312,6 @@ class AntiSpamClient extends EventEmitter { if (this.options.verbose) { console.error(`DAntiSpam (banUser#sendMissingPermMessage): ${e.message}`) } - }).then(msg => { - return this.clearBotMessages(msg) }) } return false @@ -322,9 +325,7 @@ class AntiSpamClient extends EventEmitter { if (this.options.verbose) { console.error(`DAntiSpam (banUser#sendSuccessMessage): ${e.message}`) } - }).then(msg => { - return this.clearBotMessages(msg) - }) + }) } }) if (this.options.modLogsEnabled) { @@ -371,16 +372,15 @@ class AntiSpamClient extends EventEmitter { if (this.options.muteMessage) { await message.channel.send(this.format(this.options.muteMessage, message)).catch(e => { if (this.options.verbose) { - console.error(`DAntiSpam (kickUser#sendSuccessMessage): ${e.message}`) + console.error(`DAntiSpam (muteUser#sendSuccessMessage): ${e.message}`) } - }).then(msg => { - return this.clearBotMessages(msg) }) } if (this.options.modLogsEnabled) { this.log(message, `Spam detected: ${message.author} got **muted**`, message.client) } this.emit('muteAdd', member) + this.timeMute(member, message, role) return true } @@ -407,8 +407,6 @@ class AntiSpamClient extends EventEmitter { if (this.options.verbose) { console.error(`DAntiSpam (kickUser#sendMissingPermMessage): ${e.message}`) } - }).then(msg => { - return this.clearBotMessages(msg) }) } return false @@ -419,8 +417,6 @@ class AntiSpamClient extends EventEmitter { if (this.options.verbose) { console.error(`DAntiSpam (kickUser#sendSuccessMessage): ${e.message}`) } - }).then(msg => { - return this.clearBotMessages(msg) }) } if (this.options.modLogsEnabled) { @@ -450,8 +446,6 @@ class AntiSpamClient extends EventEmitter { if (this.options.verbose) { console.error(`DAntiSpam (warnUser#sendSuccessMessage): ${e.message}`) } - }).then(msg => { - return this.clearBotMessages(msg) }) } this.emit('warnAdd', member) @@ -472,7 +466,7 @@ class AntiSpamClient extends EventEmitter { if ( !message.guild || message.author.id === message.client.user.id || - (message.guild.ownerID === message.author.id && !options.debug) || + (message.guild.ownerId === message.author.id && !options.debug) || (options.ignoreBots && message.author.bot) ) { return false @@ -568,6 +562,50 @@ class AntiSpamClient extends EventEmitter { return sanctioned } + /** + * Checks if the user left the server to remove him from the cache! + * @param {Discord.GuildMember} member The member to remove from the cache. + * @returns {Promise} Whether the member has been removed + * @example + * client.on('guildMemberRemove', (member) => { + * antiSpam.userleave(member); + * }); + */ + async userleave (member){ + const options = this.options + const isGuildIgnored = typeof options.ignoredGuilds === 'function' ? options.ignoredGuilds(member.guild) : options.ignoredGuilds.includes(member.guild.id) + if (isGuildIgnored) return false + + this.cache.bannedUsers = this.cache.bannedUsers.filter((u) => u !== member.user.id) + this.cache.mutedUsers = this.cache.mutedUsers.filter((u) => u !== member.user.id) + this.cache.kickedUsers = this.cache.kickedUsers.filter((u) => u !== member.user.id) + this.cache.warnedUsers = this.cache.warnedUsers.filter((u) => u !== member.user.id) + + return true + } + + /** + * Removes the muted role from member after specefic time + * @param {Discord.GuildMember} member The member to the role from + * @returns {Promise} Whether the role has been removed + */ + async timeMute(member, message, role) { + const minutestime = this.options.unMuteTime * 60 * 1000 + if(minutestime != 0) { + setTimeout(() => { + member.roles.remove(role) + this.cache.mutedUsers = this.cache.mutedUsers.filter((u) => u !== member.user.id) + if (this.options.modLogsEnabled) { + this.log(message, `Temp mute: ${message.author} got **unmuted**.`, message.client) + } + this.emit('muteRemove', member) + return true + }, minutestime) + + }else { + return null; + } + } /** * Reset the cache of this AntiSpam client instance. diff --git a/package.json b/package.json index 7e60e02..c50c2e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "discord-anti-spam", - "version": "2.5.8", + "version": "2.5.1", "description": "An easy to setup package that help you integration of anti-spam feature in your discord bot.", "main": "index.js", "scripts": { @@ -31,5 +31,9 @@ "devDependencies": { "jsdoc": "^3.6.3", "minami": "Androz2091/minami" + }, + "dependencies": { + "discord-anti-spam": "github:Michael-J-Scofield/discord-anti-spam#2.6.0", + "discord.js": "^13.3.1" } -} \ No newline at end of file +}