From 8ec607b88891290300c4e71ea01ea953674de414 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:58:36 +0200 Subject: [PATCH 01/70] Create context button --- new-era-commands/context-menu/bann-spammer.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 new-era-commands/context-menu/bann-spammer.js diff --git a/new-era-commands/context-menu/bann-spammer.js b/new-era-commands/context-menu/bann-spammer.js new file mode 100644 index 00000000..21323f43 --- /dev/null +++ b/new-era-commands/context-menu/bann-spammer.js @@ -0,0 +1,12 @@ +const { ContextMenuCommandBuilder, ApplicationCommandType, PermissionFlagsBits } = require('discord.js'); +const BanSpammer = require('../../services/ban-spammer.service'); + +module.exports = { + data: new ContextMenuCommandBuilder() + .setName('Bann Spammer') + .setType(ApplicationCommandType.Message) + .setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages), + execute: async (interaction) => { + await ModerationMessageDeleteService.handleInteraction(interaction); + }, +}; From bc93656c80a4a90aa1ba2f433b1d6ca96413ef48 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Wed, 5 Jun 2024 14:26:20 +0200 Subject: [PATCH 02/70] Fix calling wrong service --- new-era-commands/context-menu/bann-spammer.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/new-era-commands/context-menu/bann-spammer.js b/new-era-commands/context-menu/bann-spammer.js index 21323f43..ba21fca6 100644 --- a/new-era-commands/context-menu/bann-spammer.js +++ b/new-era-commands/context-menu/bann-spammer.js @@ -1,12 +1,16 @@ -const { ContextMenuCommandBuilder, ApplicationCommandType, PermissionFlagsBits } = require('discord.js'); -const BanSpammer = require('../../services/ban-spammer.service'); +const { + ContextMenuCommandBuilder, + ApplicationCommandType, + PermissionFlagsBits, +} = require("discord.js"); +const SpammerBanning = require("../../services/spammer-banning.service"); module.exports = { data: new ContextMenuCommandBuilder() - .setName('Bann Spammer') + .setName("Bann Spammer") .setType(ApplicationCommandType.Message) .setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages), execute: async (interaction) => { - await ModerationMessageDeleteService.handleInteraction(interaction); + await SpammerBanning.handleInteraction(interaction); }, }; From df980adca7eb141282afe45fd26fcfb3ce599dc3 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Wed, 5 Jun 2024 14:29:46 +0200 Subject: [PATCH 03/70] Refactor naming --- new-era-commands/context-menu/bann-spammer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/new-era-commands/context-menu/bann-spammer.js b/new-era-commands/context-menu/bann-spammer.js index ba21fca6..af283755 100644 --- a/new-era-commands/context-menu/bann-spammer.js +++ b/new-era-commands/context-menu/bann-spammer.js @@ -3,7 +3,7 @@ const { ApplicationCommandType, PermissionFlagsBits, } = require("discord.js"); -const SpammerBanning = require("../../services/spammer-banning.service"); +const SpammerBanningService = require("../../services/spammer-banning.service"); module.exports = { data: new ContextMenuCommandBuilder() @@ -11,6 +11,6 @@ module.exports = { .setType(ApplicationCommandType.Message) .setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages), execute: async (interaction) => { - await SpammerBanning.handleInteraction(interaction); + await SpammerBanningService.handleInteraction(interaction); }, }; From e8664f0015fe819aba3457c87b91d2c60e0d027a Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Wed, 5 Jun 2024 14:49:32 +0200 Subject: [PATCH 04/70] Update logic to spammer-banning service --- services/spammer-banning.service.js | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 services/spammer-banning.service.js diff --git a/services/spammer-banning.service.js b/services/spammer-banning.service.js new file mode 100644 index 00000000..efb1fa0f --- /dev/null +++ b/services/spammer-banning.service.js @@ -0,0 +1,35 @@ +const { EmbedBuilder } = require("discord.js"); + +class SpammerBanningService { + static async handleInteraction(interaction) { + const message = interaction.options.getMessage("message"); + console.log(message); + if (message.author.bot) return; + const messageEmbed = await SpammerBanningService.#messageBuilder(message); + + try { + await SpammerBanningService.#sendMessageToUser(message.author, { + embeds: [messageEmbed], + }); + } catch (error) { + console.log(error); + } + } + + static async #sendMessageToUser(user, message) { + await user.send(message); + } + + static async #messageBuilder(message) { + return new EmbedBuilder() + .setTitle("Banned: Compromised account / Spam") + .setDescription( + ` + Hi <@${message.author.id}>, Your account has been banned because it is posting phishing links in our server. +If you would still like to continue using our server, make sure to change your password and recover your account. +After that send a detailed contact information to appeal the ban on theodinproject@gmail.com`, + ); + } +} + +module.exports = SpammerBanningService; From 765abce8e9286b15eaf7b3d8c20c9268430e865c Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:02:36 +0200 Subject: [PATCH 05/70] Reformat message to contain new line --- services/spammer-banning.service.js | 1 + 1 file changed, 1 insertion(+) diff --git a/services/spammer-banning.service.js b/services/spammer-banning.service.js index efb1fa0f..63d33914 100644 --- a/services/spammer-banning.service.js +++ b/services/spammer-banning.service.js @@ -26,6 +26,7 @@ class SpammerBanningService { .setDescription( ` Hi <@${message.author.id}>, Your account has been banned because it is posting phishing links in our server. + If you would still like to continue using our server, make sure to change your password and recover your account. After that send a detailed contact information to appeal the ban on theodinproject@gmail.com`, ); From 3615580521a11d7a1d839fe0e883b055a70cd33c Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:14:01 +0200 Subject: [PATCH 06/70] Fix contact email --- services/spammer-banning.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/spammer-banning.service.js b/services/spammer-banning.service.js index 63d33914..72aaadb0 100644 --- a/services/spammer-banning.service.js +++ b/services/spammer-banning.service.js @@ -28,7 +28,7 @@ class SpammerBanningService { Hi <@${message.author.id}>, Your account has been banned because it is posting phishing links in our server. If you would still like to continue using our server, make sure to change your password and recover your account. -After that send a detailed contact information to appeal the ban on theodinproject@gmail.com`, +After that send a detailed contact information to appeal the ban on theodinprojectcontact@gmail.com`, ); } } From e693636bc693560bdfbdd5394682d5e650a35a7d Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:36:57 +0200 Subject: [PATCH 07/70] Reverse to send message directly --- services/spammer-banning.service.js | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/services/spammer-banning.service.js b/services/spammer-banning.service.js index 72aaadb0..5705b5ba 100644 --- a/services/spammer-banning.service.js +++ b/services/spammer-banning.service.js @@ -3,33 +3,26 @@ const { EmbedBuilder } = require("discord.js"); class SpammerBanningService { static async handleInteraction(interaction) { const message = interaction.options.getMessage("message"); - console.log(message); if (message.author.bot) return; - const messageEmbed = await SpammerBanningService.#messageBuilder(message); try { - await SpammerBanningService.#sendMessageToUser(message.author, { - embeds: [messageEmbed], - }); + await SpammerBanningService.#sendMessageToUser(message.author); } catch (error) { console.log(error); } } - static async #sendMessageToUser(user, message) { - await user.send(message); - } - - static async #messageBuilder(message) { - return new EmbedBuilder() + static async #sendMessageToUser(user) { + const embed = new EmbedBuilder() .setTitle("Banned: Compromised account / Spam") .setDescription( - ` - Hi <@${message.author.id}>, Your account has been banned because it is posting phishing links in our server. + `Account is compromised and is used to spam phishing links. -If you would still like to continue using our server, make sure to change your password and recover your account. -After that send a detailed contact information to appeal the ban on theodinprojectcontact@gmail.com`, + If you would still like to continue using our server, make sure to change your password and recover your account. + After that send a detailed contact information to appeal the ban on theodinprojectcontact@gmail.com`, ); + + await user.send(embed); } } From 9b351cf7bf16e30f2b2376b80550c7fd3863e513 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:40:20 +0200 Subject: [PATCH 08/70] Fix message sending issue --- services/spammer-banning.service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/spammer-banning.service.js b/services/spammer-banning.service.js index 5705b5ba..ee4fc15b 100644 --- a/services/spammer-banning.service.js +++ b/services/spammer-banning.service.js @@ -13,7 +13,7 @@ class SpammerBanningService { } static async #sendMessageToUser(user) { - const embed = new EmbedBuilder() + const embedMessage = new EmbedBuilder() .setTitle("Banned: Compromised account / Spam") .setDescription( `Account is compromised and is used to spam phishing links. @@ -22,7 +22,7 @@ class SpammerBanningService { After that send a detailed contact information to appeal the ban on theodinprojectcontact@gmail.com`, ); - await user.send(embed); + await user.send({ embeds: [embedMessage] }); } } From 2928b708efec18fb24e7bfb0cc8f4d7653d1844a Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:44:31 +0200 Subject: [PATCH 09/70] Update structure of calls --- services/spammer-banning.service.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/services/spammer-banning.service.js b/services/spammer-banning.service.js index ee4fc15b..8a0710fe 100644 --- a/services/spammer-banning.service.js +++ b/services/spammer-banning.service.js @@ -6,13 +6,17 @@ class SpammerBanningService { if (message.author.bot) return; try { - await SpammerBanningService.#sendMessageToUser(message.author); + await SpammerBanningService.#banUser(message.member, message.author); } catch (error) { console.log(error); } } - static async #sendMessageToUser(user) { + static async #banUser(guildMember, author) { + await SpammerBanningService.#sendMessageToUser(author); + } + + static async #sendMessageToUser(author) { const embedMessage = new EmbedBuilder() .setTitle("Banned: Compromised account / Spam") .setDescription( @@ -22,7 +26,7 @@ class SpammerBanningService { After that send a detailed contact information to appeal the ban on theodinprojectcontact@gmail.com`, ); - await user.send({ embeds: [embedMessage] }); + await author.send({ embeds: [embedMessage] }); } } From 818c39525f06cf944332dfe1c24a119d29f9572a Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 12:11:24 +0200 Subject: [PATCH 10/70] Add announcing user banning and failure --- services/spammer-banning.service.js | 33 ++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/services/spammer-banning.service.js b/services/spammer-banning.service.js index 8a0710fe..671839b2 100644 --- a/services/spammer-banning.service.js +++ b/services/spammer-banning.service.js @@ -6,14 +6,29 @@ class SpammerBanningService { if (message.author.bot) return; try { - await SpammerBanningService.#banUser(message.member, message.author); + await SpammerBanningService.#banUser(interaction, message); } catch (error) { console.log(error); } } - static async #banUser(guildMember, author) { - await SpammerBanningService.#sendMessageToUser(author); + static async #banUser(interaction, message) { + if (message.member) { + // Make sure to send the message before banning otherwise user will not be found + await SpammerBanningService.#sendMessageToUser(message.author); + message.member.ban({ reason: "Account is compromised" }); + await SpammerBanningService.#announceBanningUser( + interaction, + message.author, + ); + } else { + await SpammerBanningService.#announceUserLeaving( + interaction, + message.author, + ); + } + + message.react("✅"); } static async #sendMessageToUser(author) { @@ -28,6 +43,18 @@ class SpammerBanningService { await author.send({ embeds: [embedMessage] }); } + + static async #announceBanningUser(interaction, author) { + interaction.reply({ + content: `Banned <@${author.id}> for spam successfully.`, + }); + } + + static async #announceUserLeaving(interaction, author) { + interaction.reply({ + content: `Couldn't bann <@${author.id}>. User is not on the server.`, + }); + } } module.exports = SpammerBanningService; From 0384dcf4b6b9ddd226e795e08b4b536b0e0d094c Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 12:49:27 +0200 Subject: [PATCH 11/70] Refactor --- services/spammer-banning.service.js | 45 +++++++++++++---------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/services/spammer-banning.service.js b/services/spammer-banning.service.js index 671839b2..00721d35 100644 --- a/services/spammer-banning.service.js +++ b/services/spammer-banning.service.js @@ -6,29 +6,36 @@ class SpammerBanningService { if (message.author.bot) return; try { - await SpammerBanningService.#banUser(interaction, message); + const reply = await SpammerBanningService.#handleBanning(message); + interaction.reply(reply); } catch (error) { console.log(error); } } - static async #banUser(interaction, message) { + static async #handleBanning(message) { if (message.member) { - // Make sure to send the message before banning otherwise user will not be found + return SpammerBanningService.#banUser(message); + } + + message.react("❌"); + return { + content: `Couldn't bann <@${message.author.id}>. User is not on the server.`, + }; + } + + static async #banUser(message) { + // Make sure to send the message before banning otherwise user will not be found + let reply = `Banned <@${message.author.id}> for spam successfully.`; + try { await SpammerBanningService.#sendMessageToUser(message.author); - message.member.ban({ reason: "Account is compromised" }); - await SpammerBanningService.#announceBanningUser( - interaction, - message.author, - ); - } else { - await SpammerBanningService.#announceUserLeaving( - interaction, - message.author, - ); + } catch (error) { + reply = `Banned <@${message.author.id}> for spam but wasn't able to contact the user.`; } + message.member.ban({ reason: "Account is compromised" }); message.react("✅"); + return { content: reply }; } static async #sendMessageToUser(author) { @@ -43,18 +50,6 @@ class SpammerBanningService { await author.send({ embeds: [embedMessage] }); } - - static async #announceBanningUser(interaction, author) { - interaction.reply({ - content: `Banned <@${author.id}> for spam successfully.`, - }); - } - - static async #announceUserLeaving(interaction, author) { - interaction.reply({ - content: `Couldn't bann <@${author.id}>. User is not on the server.`, - }); - } } module.exports = SpammerBanningService; From 9c9a895e1e519ec63b64e5cd7a032e64f25d1cbc Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 12:52:59 +0200 Subject: [PATCH 12/70] Update sending error to stderr channel --- services/spammer-banning.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/spammer-banning.service.js b/services/spammer-banning.service.js index 00721d35..742141ff 100644 --- a/services/spammer-banning.service.js +++ b/services/spammer-banning.service.js @@ -9,7 +9,7 @@ class SpammerBanningService { const reply = await SpammerBanningService.#handleBanning(message); interaction.reply(reply); } catch (error) { - console.log(error); + console.error(error); } } From 21dafe487f6719712dce6678d4967e8b36c52414 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 12:57:19 +0200 Subject: [PATCH 13/70] Refactor modules --- new-era-commands/context-menu/bann-spammer.js | 4 ++-- services/spam-ban/index.js | 3 +++ .../spam-banning.service.js} | 10 +++++----- 3 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 services/spam-ban/index.js rename services/{spammer-banning.service.js => spam-ban/spam-banning.service.js} (84%) diff --git a/new-era-commands/context-menu/bann-spammer.js b/new-era-commands/context-menu/bann-spammer.js index af283755..4f1e4436 100644 --- a/new-era-commands/context-menu/bann-spammer.js +++ b/new-era-commands/context-menu/bann-spammer.js @@ -3,7 +3,7 @@ const { ApplicationCommandType, PermissionFlagsBits, } = require("discord.js"); -const SpammerBanningService = require("../../services/spammer-banning.service"); +const SpamBanningService = require("../../services/spam-ban/spam-banning.service"); module.exports = { data: new ContextMenuCommandBuilder() @@ -11,6 +11,6 @@ module.exports = { .setType(ApplicationCommandType.Message) .setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages), execute: async (interaction) => { - await SpammerBanningService.handleInteraction(interaction); + await SpamBanningService.handleInteraction(interaction); }, }; diff --git a/services/spam-ban/index.js b/services/spam-ban/index.js new file mode 100644 index 00000000..d028b450 --- /dev/null +++ b/services/spam-ban/index.js @@ -0,0 +1,3 @@ +const SpamBanningService = require("./spam-banning.service"); + +module.exports = SpamBanningService; diff --git a/services/spammer-banning.service.js b/services/spam-ban/spam-banning.service.js similarity index 84% rename from services/spammer-banning.service.js rename to services/spam-ban/spam-banning.service.js index 742141ff..a6a850d3 100644 --- a/services/spammer-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -1,12 +1,12 @@ const { EmbedBuilder } = require("discord.js"); -class SpammerBanningService { +class SpamBanningService { static async handleInteraction(interaction) { const message = interaction.options.getMessage("message"); if (message.author.bot) return; try { - const reply = await SpammerBanningService.#handleBanning(message); + const reply = await SpamBanningService.#handleBanning(message); interaction.reply(reply); } catch (error) { console.error(error); @@ -15,7 +15,7 @@ class SpammerBanningService { static async #handleBanning(message) { if (message.member) { - return SpammerBanningService.#banUser(message); + return SpamBanningService.#banUser(message); } message.react("❌"); @@ -28,7 +28,7 @@ class SpammerBanningService { // Make sure to send the message before banning otherwise user will not be found let reply = `Banned <@${message.author.id}> for spam successfully.`; try { - await SpammerBanningService.#sendMessageToUser(message.author); + await SpamBanningService.#sendMessageToUser(message.author); } catch (error) { reply = `Banned <@${message.author.id}> for spam but wasn't able to contact the user.`; } @@ -52,4 +52,4 @@ class SpammerBanningService { } } -module.exports = SpammerBanningService; +module.exports = SpamBanningService; From c1508f321bda6e022197eea9e176dc689bb928e3 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:17:45 +0200 Subject: [PATCH 14/70] Add tests --- .../spam-ban/spam-banning.service.test.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 services/spam-ban/spam-banning.service.test.js diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js new file mode 100644 index 00000000..b963a230 --- /dev/null +++ b/services/spam-ban/spam-banning.service.test.js @@ -0,0 +1,25 @@ +const SpamBanningService = require("./spam-banning.service"); + +describe("Successfully bans user", () => { + // Message from interaction, will be changed per test + let interactionMessage; + // Will be replaced by the reply coming from interaction + let reply; + + const interactionMock = { + options: { + getMessage: () => interactionMessage, + }, + reply: jest.fn((message) => { + reply = message; + }), + }; + it("User is banned successfully on full ban", async () => { + const author = { id: "123", send: jest.fn(() => {}) }; + const member = { ban: jest.fn(() => {}) }; + interactionMessage = { author, member }; + await SpamBanningService.handleInteraction(interactionMock); + expect(author.send).toHaveBeenCalled(); + expect(reply).toMatchSnapshot(); + }); +}); From 75cb035a145e6b16813b452d558f4ca9da56f700 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:27:05 +0200 Subject: [PATCH 15/70] Update tests and use snapshot --- .../__snapshots__/spam-banning.service.test.js.snap | 7 +++++++ services/spam-ban/spam-banning.service.test.js | 11 +++++------ 2 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 services/spam-ban/__snapshots__/spam-banning.service.test.js.snap diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap new file mode 100644 index 00000000..4b5090bd --- /dev/null +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Successfully bans user User is banned successfully on full ban 1`] = ` +{ + "content": "Banned <@123> for spam successfully.", +} +`; diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index b963a230..c937d462 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -2,24 +2,23 @@ const SpamBanningService = require("./spam-banning.service"); describe("Successfully bans user", () => { // Message from interaction, will be changed per test - let interactionMessage; + const messageMock = { react: jest.fn(() => {}) }; // Will be replaced by the reply coming from interaction let reply; const interactionMock = { options: { - getMessage: () => interactionMessage, + getMessage: () => messageMock, }, reply: jest.fn((message) => { reply = message; }), }; it("User is banned successfully on full ban", async () => { - const author = { id: "123", send: jest.fn(() => {}) }; - const member = { ban: jest.fn(() => {}) }; - interactionMessage = { author, member }; + messageMock.author = { id: "123", send: jest.fn(() => {}) }; + messageMock.member = { ban: jest.fn(() => {}) }; await SpamBanningService.handleInteraction(interactionMock); - expect(author.send).toHaveBeenCalled(); + expect(messageMock.author.send).toHaveBeenCalled(); expect(reply).toMatchSnapshot(); }); }); From 310f6775b6be876bc62ce457b1a351a9ef5c9ab5 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:27:53 +0200 Subject: [PATCH 16/70] Finalize first full test --- services/spam-ban/spam-banning.service.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index c937d462..4508c128 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -19,6 +19,8 @@ describe("Successfully bans user", () => { messageMock.member = { ban: jest.fn(() => {}) }; await SpamBanningService.handleInteraction(interactionMock); expect(messageMock.author.send).toHaveBeenCalled(); + expect(messageMock.member.ban).toHaveBeenCalled(); + expect(messageMock.react).toHaveBeenCalled(); expect(reply).toMatchSnapshot(); }); }); From 680184f97f143106baa4aa59eac29e74528e9c95 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:30:43 +0200 Subject: [PATCH 17/70] Add second test for users that isn't able to recieve messages --- .../spam-banning.service.test.js.snap | 6 ++++++ services/spam-ban/spam-banning.service.test.js | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index 4b5090bd..17457e17 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -1,5 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Successfully bans user User is banned but couldn't send a DM 1`] = ` +{ + "content": "Banned <@007> for spam but wasn't able to contact the user.", +} +`; + exports[`Successfully bans user User is banned successfully on full ban 1`] = ` { "content": "Banned <@123> for spam successfully.", diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 4508c128..b256418f 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -14,6 +14,7 @@ describe("Successfully bans user", () => { reply = message; }), }; + it("User is banned successfully on full ban", async () => { messageMock.author = { id: "123", send: jest.fn(() => {}) }; messageMock.member = { ban: jest.fn(() => {}) }; @@ -23,4 +24,19 @@ describe("Successfully bans user", () => { expect(messageMock.react).toHaveBeenCalled(); expect(reply).toMatchSnapshot(); }); + + it("User is banned but couldn't send a DM", async () => { + messageMock.author = { + id: "007", + send: jest.fn(() => { + throw new Error(""); + }), + }; + messageMock.member = { ban: jest.fn(() => {}) }; + await SpamBanningService.handleInteraction(interactionMock); + expect(messageMock.author.send).toHaveBeenCalled(); + expect(messageMock.member.ban).toHaveBeenCalled(); + expect(messageMock.react).toHaveBeenCalled(); + expect(reply).toMatchSnapshot(); + }); }); From 1f748a9a0145f903a1bf8c2c38d8fa9b7de95818 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:33:28 +0200 Subject: [PATCH 18/70] Add test for user that is not on the server anymore --- .../__snapshots__/spam-banning.service.test.js.snap | 6 ++++++ services/spam-ban/spam-banning.service.test.js | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index 17457e17..4814f7f5 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -1,5 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Successfully bans user User has left the server 1`] = ` +{ + "content": "Couldn't bann <@008>. User is not on the server.", +} +`; + exports[`Successfully bans user User is banned but couldn't send a DM 1`] = ` { "content": "Banned <@007> for spam but wasn't able to contact the user.", diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index b256418f..163c71be 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -39,4 +39,13 @@ describe("Successfully bans user", () => { expect(messageMock.react).toHaveBeenCalled(); expect(reply).toMatchSnapshot(); }); + + it("User has left the server", async () => { + messageMock.author = { id: "008", send: jest.fn(() => {}) }; + messageMock.member = null; + await SpamBanningService.handleInteraction(interactionMock); + expect(messageMock.author.send).not.toHaveBeenCalled(); + expect(messageMock.react).toHaveBeenCalled(); + expect(reply).toMatchSnapshot(); + }); }); From 133c0e8df0cad55508e56398b4db26e554dc8dd0 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:49:20 +0200 Subject: [PATCH 19/70] Add function to announce the ban --- services/spam-ban/spam-banning.service.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index a6a850d3..532977ac 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -1,4 +1,5 @@ const { EmbedBuilder } = require("discord.js"); +const config = require("../../config"); class SpamBanningService { static async handleInteraction(interaction) { @@ -6,8 +7,9 @@ class SpamBanningService { if (message.author.bot) return; try { - const reply = await SpamBanningService.#handleBanning(message); - interaction.reply(reply); + // const reply = await SpamBanningService.#handleBanning(message); + // interaction.reply(reply); + await SpamBanningService.#announceBan(interaction); } catch (error) { console.error(error); } @@ -50,6 +52,15 @@ class SpamBanningService { await author.send({ embeds: [embedMessage] }); } + + static async #announceBan(interaction) { + const channelID = config.channels.moderationActions; + console.log("Getting channels"); + const channel = interaction.guild.channels.cache.find( + (c) => c.id === channelID, + ); + channel.send("Hello fred"); + } } module.exports = SpamBanningService; From 282e02fb6b3617c8b67d85e4cfcfab8be8eafbcc Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Sun, 9 Jun 2024 21:15:30 +0200 Subject: [PATCH 20/70] Refactor naming --- services/spam-ban/spam-banning.service.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 532977ac..ee385d89 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -7,8 +7,8 @@ class SpamBanningService { if (message.author.bot) return; try { - // const reply = await SpamBanningService.#handleBanning(message); - // interaction.reply(reply); + const reply = await SpamBanningService.#handleBanning(message); + interaction.reply(reply); await SpamBanningService.#announceBan(interaction); } catch (error) { console.error(error); @@ -54,8 +54,7 @@ class SpamBanningService { } static async #announceBan(interaction) { - const channelID = config.channels.moderationActions; - console.log("Getting channels"); + const channelID = config.channels.moderationLog; const channel = interaction.guild.channels.cache.find( (c) => c.id === channelID, ); From 94ddcb9f1c68059db06e480b6c45fdf9f61146e1 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Sun, 9 Jun 2024 21:39:55 +0200 Subject: [PATCH 21/70] Update tests --- .../spam-ban/spam-banning.service.test.js | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 163c71be..1c38d013 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -15,28 +15,26 @@ describe("Successfully bans user", () => { }), }; - it("User is banned successfully on full ban", async () => { + it("Discord ban api is called", async () => { messageMock.author = { id: "123", send: jest.fn(() => {}) }; messageMock.member = { ban: jest.fn(() => {}) }; await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.author.send).toHaveBeenCalled(); expect(messageMock.member.ban).toHaveBeenCalled(); - expect(messageMock.react).toHaveBeenCalled(); expect(reply).toMatchSnapshot(); }); - it("User is banned but couldn't send a DM", async () => { - messageMock.author = { - id: "007", - send: jest.fn(() => { - throw new Error(""); + it("Discord ban api is called with right message", async () => { + let banReason = {}; + messageMock.author = { id: "007", send: jest.fn(() => {}) }; + messageMock.member = { + ban: jest.fn((arg) => { + banReason = arg; }), }; - messageMock.member = { ban: jest.fn(() => {}) }; + await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.author.send).toHaveBeenCalled(); expect(messageMock.member.ban).toHaveBeenCalled(); - expect(messageMock.react).toHaveBeenCalled(); + expect(banReason).toMatchSnapshot(); expect(reply).toMatchSnapshot(); }); From 349be4af3fd1dbee03f4741aedb941c5e8f857e9 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Sun, 9 Jun 2024 21:45:35 +0200 Subject: [PATCH 22/70] Refactor seperate tests --- .../spam-ban/spam-banning.service.test.js | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 1c38d013..b32f6c80 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -3,7 +3,7 @@ const SpamBanningService = require("./spam-banning.service"); describe("Successfully bans user", () => { // Message from interaction, will be changed per test const messageMock = { react: jest.fn(() => {}) }; - // Will be replaced by the reply coming from interaction + // Reply will be replaced by the reply coming from interaction automaticly let reply; const interactionMock = { @@ -20,7 +20,6 @@ describe("Successfully bans user", () => { messageMock.member = { ban: jest.fn(() => {}) }; await SpamBanningService.handleInteraction(interactionMock); expect(messageMock.member.ban).toHaveBeenCalled(); - expect(reply).toMatchSnapshot(); }); it("Discord ban api is called with right message", async () => { @@ -35,15 +34,35 @@ describe("Successfully bans user", () => { await SpamBanningService.handleInteraction(interactionMock); expect(messageMock.member.ban).toHaveBeenCalled(); expect(banReason).toMatchSnapshot(); - expect(reply).toMatchSnapshot(); }); - it("User has left the server", async () => { - messageMock.author = { id: "008", send: jest.fn(() => {}) }; - messageMock.member = null; + it("Discord message api is called", async () => { + messageMock.author = { id: "123", send: jest.fn(() => {}) }; + messageMock.member = { ban: jest.fn(() => {}) }; await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.author.send).not.toHaveBeenCalled(); - expect(messageMock.react).toHaveBeenCalled(); - expect(reply).toMatchSnapshot(); + expect(messageMock.author.send).toHaveBeenCalled(); }); + + it("Discord message api is called with correct message", async () => { + let userMessage = {}; + messageMock.author = { + id: "123", + send: jest.fn((arg) => { + userMessage = arg; + }), + }; + messageMock.member = { ban: jest.fn(() => {}) }; + await SpamBanningService.handleInteraction(interactionMock); + expect(messageMock.author.send).toHaveBeenCalled(); + expect(userMessage).toMatchSnapshot(); + }); + + // it("User has left the server", async () => { + // messageMock.author = { id: "008", send: jest.fn(() => {}) }; + // messageMock.member = null; + // await SpamBanningService.handleInteraction(interactionMock); + // expect(messageMock.author.send).not.toHaveBeenCalled(); + // expect(messageMock.react).toHaveBeenCalled(); + // expect(reply).toMatchSnapshot(); + // }); }); From cad7b18a8c0b577d65eafb9bcbde15b261502d44 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 10 Jun 2024 00:32:08 +0200 Subject: [PATCH 23/70] Refactor testing to seperate ideas --- .../spam-banning.service.test.js.snap | 30 ++++- .../spam-ban/spam-banning.service.test.js | 113 +++++++++++------- 2 files changed, 97 insertions(+), 46 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index 4814f7f5..4da16b82 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -1,19 +1,39 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Successfully bans user User has left the server 1`] = ` +exports[`Banning spammer that is still on the server Discord ban api is called with the correct reason 1`] = ` { - "content": "Couldn't bann <@008>. User is not on the server.", + "reason": "Account is compromised", } `; -exports[`Successfully bans user User is banned but couldn't send a DM 1`] = ` +exports[`Banning spammer that is still on the server Discord message api is called with the correct message 1`] = ` { - "content": "Banned <@007> for spam but wasn't able to contact the user.", + "embeds": [ + { + "description": "Account is compromised and is used to spam phishing links. + + If you would still like to continue using our server, make sure to change your password and recover your account. + After that send a detailed contact information to appeal the ban on theodinprojectcontact@gmail.com", + "title": "Banned: Compromised account / Spam", + }, + ], } `; -exports[`Successfully bans user User is banned successfully on full ban 1`] = ` +exports[`Banning spammer that is still on the server Sends back correct interaction reply to calling moderator 1`] = ` { "content": "Banned <@123> for spam successfully.", } `; + +exports[`Banning spammer who has DM set to private Discord ban api is called with the correct reason 1`] = ` +{ + "reason": "Account is compromised", +} +`; + +exports[`Banning spammer who has DM set to private Sends back correct interaction reply to calling moderator 1`] = ` +{ + "content": "Banned <@123> for spam but wasn't able to contact the user.", +} +`; diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index b32f6c80..e9258894 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -1,68 +1,99 @@ const SpamBanningService = require("./spam-banning.service"); -describe("Successfully bans user", () => { - // Message from interaction, will be changed per test - const messageMock = { react: jest.fn(() => {}) }; - // Reply will be replaced by the reply coming from interaction automaticly - let reply; +describe("Banning spammer that is still on the server", () => { + let sendArg; + let banArg; + let reactArg; - const interactionMock = { - options: { - getMessage: () => messageMock, + const messageMock = { + author: { + id: "123", + send: jest.fn((arg) => { + sendArg = arg; + }), + }, + member: { + ban: jest.fn((arg) => { + banArg = arg; + }), }, + react: jest.fn((arg) => { + reactArg = arg; + }), + }; + + let reply; + const interactionMock = { reply: jest.fn((message) => { reply = message; }), + options: { + getMessage: () => messageMock, + }, }; - it("Discord ban api is called", async () => { - messageMock.author = { id: "123", send: jest.fn(() => {}) }; - messageMock.member = { ban: jest.fn(() => {}) }; + it("Discord ban api is called with the correct reason", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(messageMock.member.ban).toHaveBeenCalled(); + expect(banArg).toMatchSnapshot(); + }); + + it("Discord message api is called with the correct message", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(messageMock.author.send).toHaveBeenCalled(); + expect(sendArg).toMatchSnapshot(); + }); + + it("Sends back correct interaction reply to calling moderator", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(reply).toMatchSnapshot(); }); +}); + +describe("Banning spammer who has DM set to private", () => { + let banArg; + let reactArg; - it("Discord ban api is called with right message", async () => { - let banReason = {}; - messageMock.author = { id: "007", send: jest.fn(() => {}) }; - messageMock.member = { + const messageMock = { + author: { + id: "123", + send: jest.fn(() => { + throw new Error("Cannot send DM to user"); + }), + }, + member: { ban: jest.fn((arg) => { - banReason = arg; + banArg = arg; }), - }; + }, + react: jest.fn((arg) => { + reactArg = arg; + }), + }; + + let reply; + const interactionMock = { + reply: jest.fn((message) => { + reply = message; + }), + options: { + getMessage: () => messageMock, + }, + }; + it("Discord ban api is called with the correct reason", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(messageMock.member.ban).toHaveBeenCalled(); - expect(banReason).toMatchSnapshot(); + expect(banArg).toMatchSnapshot(); }); - it("Discord message api is called", async () => { - messageMock.author = { id: "123", send: jest.fn(() => {}) }; - messageMock.member = { ban: jest.fn(() => {}) }; + it("Discord message api is called and error handled", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(messageMock.author.send).toHaveBeenCalled(); }); - it("Discord message api is called with correct message", async () => { - let userMessage = {}; - messageMock.author = { - id: "123", - send: jest.fn((arg) => { - userMessage = arg; - }), - }; - messageMock.member = { ban: jest.fn(() => {}) }; + it("Sends back correct interaction reply to calling moderator", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.author.send).toHaveBeenCalled(); - expect(userMessage).toMatchSnapshot(); + expect(reply).toMatchSnapshot(); }); - - // it("User has left the server", async () => { - // messageMock.author = { id: "008", send: jest.fn(() => {}) }; - // messageMock.member = null; - // await SpamBanningService.handleInteraction(interactionMock); - // expect(messageMock.author.send).not.toHaveBeenCalled(); - // expect(messageMock.react).toHaveBeenCalled(); - // expect(reply).toMatchSnapshot(); - // }); }); From 9afb67f70034d7ed96467af8e34415300091d88f Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 10 Jun 2024 00:34:08 +0200 Subject: [PATCH 24/70] Add reaction testing --- .../__snapshots__/spam-banning.service.test.js.snap | 2 ++ services/spam-ban/spam-banning.service.test.js | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index 4da16b82..e98f49b9 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -32,6 +32,8 @@ exports[`Banning spammer who has DM set to private Discord ban api is called wit } `; +exports[`Banning spammer who has DM set to private Reacts with the correct emoji 1`] = `"k"`; + exports[`Banning spammer who has DM set to private Sends back correct interaction reply to calling moderator 1`] = ` { "content": "Banned <@123> for spam but wasn't able to contact the user.", diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index e9258894..25fb6446 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -92,6 +92,12 @@ describe("Banning spammer who has DM set to private", () => { expect(messageMock.author.send).toHaveBeenCalled(); }); + it("Reacts with the correct emoji", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(messageMock.react).toHaveBeenCalled(); + expect(reactArg).toMatchSnapshot(); + }); + it("Sends back correct interaction reply to calling moderator", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(reply).toMatchSnapshot(); From 2c820620e4acac681e2100df6340f39cf4f31d44 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 10 Jun 2024 00:35:19 +0200 Subject: [PATCH 25/70] Update snapshot --- .../__snapshots__/spam-banning.service.test.js.snap | 4 +++- services/spam-ban/spam-banning.service.test.js | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index e98f49b9..8119c772 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -20,6 +20,8 @@ exports[`Banning spammer that is still on the server Discord message api is call } `; +exports[`Banning spammer that is still on the server Reacts with the correct emoji 1`] = `"✅"`; + exports[`Banning spammer that is still on the server Sends back correct interaction reply to calling moderator 1`] = ` { "content": "Banned <@123> for spam successfully.", @@ -32,7 +34,7 @@ exports[`Banning spammer who has DM set to private Discord ban api is called wit } `; -exports[`Banning spammer who has DM set to private Reacts with the correct emoji 1`] = `"k"`; +exports[`Banning spammer who has DM set to private Reacts with the correct emoji 1`] = `"✅"`; exports[`Banning spammer who has DM set to private Sends back correct interaction reply to calling moderator 1`] = ` { diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 25fb6446..cc4ad336 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -44,6 +44,12 @@ describe("Banning spammer that is still on the server", () => { expect(sendArg).toMatchSnapshot(); }); + it("Reacts with the correct emoji", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(messageMock.react).toHaveBeenCalled(); + expect(reactArg).toMatchSnapshot(); + }); + it("Sends back correct interaction reply to calling moderator", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(reply).toMatchSnapshot(); From a0dcf98da6046147e0fec6200952bde1eaf53377 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 10 Jun 2024 01:28:26 +0200 Subject: [PATCH 26/70] Add testing channel sending --- .../spam-banning.service.test.js.snap | 4 ++ .../spam-ban/spam-banning.service.test.js | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index 8119c772..ce041e50 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -28,6 +28,10 @@ exports[`Banning spammer that is still on the server Sends back correct interact } `; +exports[`Banning spammer that is still on the server Sends message to the correct channel 1`] = `""`; + +exports[`Banning spammer that is still on the server Sends message to the correct channel 2`] = `undefined`; + exports[`Banning spammer who has DM set to private Discord ban api is called with the correct reason 1`] = ` { "reason": "Account is compromised", diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index cc4ad336..d1dc02d8 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -1,4 +1,27 @@ const SpamBanningService = require("./spam-banning.service"); +const config = require("../../config"); + +class Channel { + constructor(id) { + this.id = id; + this.send = jest.fn((arg) => { + this.arg = arg; + }); + } +} + +const guild = { + channels: { + cache: [ + new Channel("2342314"), + new Channel("101010"), + new Channel("22223333"), + new Channel(config.channels.moderationLog), + new Channel("2302382"), + new Channel("000000"), + ], + }, +}; describe("Banning spammer that is still on the server", () => { let sendArg; @@ -30,6 +53,7 @@ describe("Banning spammer that is still on the server", () => { options: { getMessage: () => messageMock, }, + guild, }; it("Discord ban api is called with the correct reason", async () => { @@ -50,6 +74,19 @@ describe("Banning spammer that is still on the server", () => { expect(reactArg).toMatchSnapshot(); }); + it("Sends message to the correct channel", async () => { + await SpamBanningService.handleInteraction(interactionMock); + guild.channels.cache.forEach((channel) => { + if (channel.id === config.channels.moderationLog) { + expect(channel.send).toHaveBeenCalled(); + expect(channel.arg).toMatchSnapshot(); + } else { + expect(channel.send).not.toHaveBeenCalled(); + } + }); + expect().toMatchSnapshot(); + }); + it("Sends back correct interaction reply to calling moderator", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(reply).toMatchSnapshot(); @@ -85,6 +122,7 @@ describe("Banning spammer who has DM set to private", () => { options: { getMessage: () => messageMock, }, + guild, }; it("Discord ban api is called with the correct reason", async () => { From 233b9983bf07c9c6560d46b706a0cb57e9ebae2b Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 10 Jun 2024 01:33:09 +0200 Subject: [PATCH 27/70] Refactor fix issue with snapshots --- .../spam-banning.service.test.js.snap | 42 +++++++++---------- .../spam-ban/spam-banning.service.test.js | 17 ++++++-- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index ce041e50..d01d0555 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -1,12 +1,28 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Banning spammer that is still on the server Discord ban api is called with the correct reason 1`] = ` +exports[`Banning spammer who has DM set to private Discord ban api is called with the correct reason 1`] = ` +{ + "reason": "Account is compromised", +} +`; + +exports[`Banning spammer who has DM set to private Reacts with the correct emoji 1`] = `"✅"`; + +exports[`Banning spammer who has DM set to private Sends back correct interaction reply to calling moderator 1`] = ` +{ + "content": "Banned <@123> for spam but wasn't able to contact the user.", +} +`; + +exports[`Banning spammer who has DM set to private Sends log to the correct channel 1`] = `"Hello fred"`; + +exports[`Banning spammer with DM enabled Discord ban api is called with the correct reason 1`] = ` { "reason": "Account is compromised", } `; -exports[`Banning spammer that is still on the server Discord message api is called with the correct message 1`] = ` +exports[`Banning spammer with DM enabled Discord message api is called with the correct message 1`] = ` { "embeds": [ { @@ -20,28 +36,12 @@ exports[`Banning spammer that is still on the server Discord message api is call } `; -exports[`Banning spammer that is still on the server Reacts with the correct emoji 1`] = `"✅"`; +exports[`Banning spammer with DM enabled Reacts with the correct emoji 1`] = `"✅"`; -exports[`Banning spammer that is still on the server Sends back correct interaction reply to calling moderator 1`] = ` +exports[`Banning spammer with DM enabled Sends back correct interaction reply to calling moderator 1`] = ` { "content": "Banned <@123> for spam successfully.", } `; -exports[`Banning spammer that is still on the server Sends message to the correct channel 1`] = `""`; - -exports[`Banning spammer that is still on the server Sends message to the correct channel 2`] = `undefined`; - -exports[`Banning spammer who has DM set to private Discord ban api is called with the correct reason 1`] = ` -{ - "reason": "Account is compromised", -} -`; - -exports[`Banning spammer who has DM set to private Reacts with the correct emoji 1`] = `"✅"`; - -exports[`Banning spammer who has DM set to private Sends back correct interaction reply to calling moderator 1`] = ` -{ - "content": "Banned <@123> for spam but wasn't able to contact the user.", -} -`; +exports[`Banning spammer with DM enabled Sends log to the correct channel 1`] = `"Hello fred"`; diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index d1dc02d8..34a138a3 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -23,7 +23,7 @@ const guild = { }, }; -describe("Banning spammer that is still on the server", () => { +describe("Banning spammer with DM enabled", () => { let sendArg; let banArg; let reactArg; @@ -74,7 +74,7 @@ describe("Banning spammer that is still on the server", () => { expect(reactArg).toMatchSnapshot(); }); - it("Sends message to the correct channel", async () => { + it("Sends log to the correct channel", async () => { await SpamBanningService.handleInteraction(interactionMock); guild.channels.cache.forEach((channel) => { if (channel.id === config.channels.moderationLog) { @@ -84,7 +84,6 @@ describe("Banning spammer that is still on the server", () => { expect(channel.send).not.toHaveBeenCalled(); } }); - expect().toMatchSnapshot(); }); it("Sends back correct interaction reply to calling moderator", async () => { @@ -142,6 +141,18 @@ describe("Banning spammer who has DM set to private", () => { expect(reactArg).toMatchSnapshot(); }); + it("Sends log to the correct channel", async () => { + await SpamBanningService.handleInteraction(interactionMock); + guild.channels.cache.forEach((channel) => { + if (channel.id === config.channels.moderationLog) { + expect(channel.send).toHaveBeenCalled(); + expect(channel.arg).toMatchSnapshot(); + } else { + expect(channel.send).not.toHaveBeenCalled(); + } + }); + }); + it("Sends back correct interaction reply to calling moderator", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(reply).toMatchSnapshot(); From beda9d54b208293f54482d91b2106b0de0dbeea4 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:43:43 +0200 Subject: [PATCH 28/70] Add tests to users who has left the server --- .../spam-banning.service.test.js.snap | 8 +++ .../spam-ban/spam-banning.service.test.js | 49 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index d01d0555..db0e95a3 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -1,5 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Banning spammer that has left the server Reacts with the correct emoji to automod message 1`] = `"❌"`; + +exports[`Banning spammer that has left the server Sends back correct interaction reply to calling moderator 1`] = ` +{ + "content": "Couldn't bann <@123>. User is not on the server.", +} +`; + exports[`Banning spammer who has DM set to private Discord ban api is called with the correct reason 1`] = ` { "reason": "Account is compromised", diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 34a138a3..9d17c69e 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -158,3 +158,52 @@ describe("Banning spammer who has DM set to private", () => { expect(reply).toMatchSnapshot(); }); }); + +describe("Banning spammer that has left the server", () => { + let reactArg; + + const messageMock = { + author: { + id: "123", + send: jest.fn(() => {}), + }, + member: null, + react: jest.fn((arg) => { + reactArg = arg; + }), + }; + + let reply; + const interactionMock = { + reply: jest.fn((message) => { + reply = message; + }), + options: { + getMessage: () => messageMock, + }, + guild, + }; + + it("Author message sending api is not called", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(messageMock.author.send).not.toHaveBeenCalled(); + }); + + it("Reacts with the correct emoji to automod message", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(messageMock.react).toHaveBeenCalled(); + expect(reactArg).toMatchSnapshot(); + }); + + it("Does not log any channel", async () => { + await SpamBanningService.handleInteraction(interactionMock); + guild.channels.cache.forEach((channel) => { + expect(channel.send).not.toHaveBeenCalled(); + }); + }); + + it("Sends back correct interaction reply to calling moderator", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(reply).toMatchSnapshot(); + }); +}); From caf9b7559ad4c5e9cd2b30fa70c5cdea4cd6379a Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:55:34 +0200 Subject: [PATCH 29/70] Update logic --- services/spam-ban/spam-banning.service.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index ee385d89..58b3202d 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -6,26 +6,23 @@ class SpamBanningService { const message = interaction.options.getMessage("message"); if (message.author.bot) return; + let reply; try { - const reply = await SpamBanningService.#handleBanning(message); + if (!message.member) { + message.react("❌"); + reply = { + content: `Couldn't bann <@${message.author.id}>. User is not on the server.`, + }; + } else { + reply = await SpamBanningService.#banUser(message); + await SpamBanningService.#announceBan(interaction); + } interaction.reply(reply); - await SpamBanningService.#announceBan(interaction); } catch (error) { console.error(error); } } - static async #handleBanning(message) { - if (message.member) { - return SpamBanningService.#banUser(message); - } - - message.react("❌"); - return { - content: `Couldn't bann <@${message.author.id}>. User is not on the server.`, - }; - } - static async #banUser(message) { // Make sure to send the message before banning otherwise user will not be found let reply = `Banned <@${message.author.id}> for spam successfully.`; From 4b7a513e460d5f62d9f889a6bebdc382065c8f9b Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 10 Jun 2024 19:59:55 +0200 Subject: [PATCH 30/70] Update testing to test number of calls --- .../spam-ban/spam-banning.service.test.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 9d17c69e..cb0845f9 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -58,19 +58,19 @@ describe("Banning spammer with DM enabled", () => { it("Discord ban api is called with the correct reason", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.member.ban).toHaveBeenCalled(); + expect(messageMock.member.ban).toHaveBeenCalledTimes(1); expect(banArg).toMatchSnapshot(); }); it("Discord message api is called with the correct message", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.author.send).toHaveBeenCalled(); + expect(messageMock.author.send).toHaveBeenCalledTimes(1); expect(sendArg).toMatchSnapshot(); }); it("Reacts with the correct emoji", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.react).toHaveBeenCalled(); + expect(messageMock.react).toHaveBeenCalledTimes(1); expect(reactArg).toMatchSnapshot(); }); @@ -78,10 +78,10 @@ describe("Banning spammer with DM enabled", () => { await SpamBanningService.handleInteraction(interactionMock); guild.channels.cache.forEach((channel) => { if (channel.id === config.channels.moderationLog) { - expect(channel.send).toHaveBeenCalled(); + expect(channel.send).toHaveBeenCalledTimes(1); expect(channel.arg).toMatchSnapshot(); } else { - expect(channel.send).not.toHaveBeenCalled(); + expect(channel.send).not.toHaveBeenCalledTimes(1); } }); }); @@ -126,18 +126,18 @@ describe("Banning spammer who has DM set to private", () => { it("Discord ban api is called with the correct reason", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.member.ban).toHaveBeenCalled(); + expect(messageMock.member.ban).toHaveBeenCalledTimes(1); expect(banArg).toMatchSnapshot(); }); it("Discord message api is called and error handled", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.author.send).toHaveBeenCalled(); + expect(messageMock.author.send).toHaveBeenCalledTimes(1); }); it("Reacts with the correct emoji", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.react).toHaveBeenCalled(); + expect(messageMock.react).toHaveBeenCalledTimes(1); expect(reactArg).toMatchSnapshot(); }); @@ -145,10 +145,10 @@ describe("Banning spammer who has DM set to private", () => { await SpamBanningService.handleInteraction(interactionMock); guild.channels.cache.forEach((channel) => { if (channel.id === config.channels.moderationLog) { - expect(channel.send).toHaveBeenCalled(); + expect(channel.send).toHaveBeenCalledTimes(1); expect(channel.arg).toMatchSnapshot(); } else { - expect(channel.send).not.toHaveBeenCalled(); + expect(channel.send).not.toHaveBeenCalledTimes(1); } }); }); @@ -191,7 +191,7 @@ describe("Banning spammer that has left the server", () => { it("Reacts with the correct emoji to automod message", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.react).toHaveBeenCalled(); + expect(messageMock.react).toHaveBeenCalledTimes(1); expect(reactArg).toMatchSnapshot(); }); From e1df63bd8817c4dff51d66472999e8c18dfc6a17 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 13:28:34 +0200 Subject: [PATCH 31/70] Refactor to use creation mocks --- .../spam-ban/spam-banning.service.test.js | 315 +++++++++--------- 1 file changed, 164 insertions(+), 151 deletions(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index cb0845f9..090a3b2c 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -1,36 +1,27 @@ const SpamBanningService = require("./spam-banning.service"); const config = require("../../config"); -class Channel { - constructor(id) { - this.id = id; - this.send = jest.fn((arg) => { - this.arg = arg; - }); - } -} +function createInteractionMock(message, guild) { + let replyArg; -const guild = { - channels: { - cache: [ - new Channel("2342314"), - new Channel("101010"), - new Channel("22223333"), - new Channel(config.channels.moderationLog), - new Channel("2302382"), - new Channel("000000"), - ], - }, -}; + return { + reply: jest.fn((arg) => { + replyArg = arg; + }), -describe("Banning spammer with DM enabled", () => { + guild, + options: { getMessage: () => message }, + getReplyArg: () => replyArg, + }; +} + +function createMessageMock() { let sendArg; let banArg; let reactArg; - const messageMock = { + return { author: { - id: "123", send: jest.fn((arg) => { sendArg = arg; }), @@ -43,107 +34,63 @@ describe("Banning spammer with DM enabled", () => { react: jest.fn((arg) => { reactArg = arg; }), + getSendArg: () => sendArg, + getBanArg: () => banArg, + getReactArg: () => reactArg, }; +} - let reply; - const interactionMock = { - reply: jest.fn((message) => { - reply = message; - }), - options: { - getMessage: () => messageMock, - }, - guild, - }; - - it("Discord ban api is called with the correct reason", async () => { - await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.member.ban).toHaveBeenCalledTimes(1); - expect(banArg).toMatchSnapshot(); - }); - - it("Discord message api is called with the correct message", async () => { - await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.author.send).toHaveBeenCalledTimes(1); - expect(sendArg).toMatchSnapshot(); - }); - - it("Reacts with the correct emoji", async () => { - await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.react).toHaveBeenCalledTimes(1); - expect(reactArg).toMatchSnapshot(); - }); - - it("Sends log to the correct channel", async () => { - await SpamBanningService.handleInteraction(interactionMock); - guild.channels.cache.forEach((channel) => { - if (channel.id === config.channels.moderationLog) { - expect(channel.send).toHaveBeenCalledTimes(1); - expect(channel.arg).toMatchSnapshot(); - } else { - expect(channel.send).not.toHaveBeenCalledTimes(1); - } +class ChannelMock { + constructor(id) { + this.id = id; + this.send = jest.fn((arg) => { + this.arg = arg; }); - }); + } +} - it("Sends back correct interaction reply to calling moderator", async () => { - await SpamBanningService.handleInteraction(interactionMock); - expect(reply).toMatchSnapshot(); - }); +const createGuild = () => ({ + channels: { + cache: [ + new ChannelMock("2342314"), + new ChannelMock("101010"), + new ChannelMock("22223333"), + new ChannelMock(config.channels.moderationLog), + new ChannelMock("2302382"), + new ChannelMock("000000"), + ], + }, }); -describe("Banning spammer who has DM set to private", () => { - let banArg; - let reactArg; - - const messageMock = { - author: { - id: "123", - send: jest.fn(() => { - throw new Error("Cannot send DM to user"); - }), - }, - member: { - ban: jest.fn((arg) => { - banArg = arg; - }), - }, - react: jest.fn((arg) => { - reactArg = arg; - }), - }; +describe("Banning spammer with DM enabled", () => { + const guild = createGuild(); - let reply; - const interactionMock = { - reply: jest.fn((message) => { - reply = message; - }), - options: { - getMessage: () => messageMock, - }, - guild, - }; + const interactionMock = createInteractionMock( + createMessageMock(), + createGuild(), + ); it("Discord ban api is called with the correct reason", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.member.ban).toHaveBeenCalledTimes(1); - expect(banArg).toMatchSnapshot(); + expect(interactionMock.message.member.ban).toHaveBeenCalledTimes(1); + expect(interactionMock.message.banArg).toMatchSnapshot(); }); - it("Discord message api is called and error handled", async () => { + it("Discord message api is called with the correct message", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(messageMock.author.send).toHaveBeenCalledTimes(1); + expect(messageMock.sendArg).toMatchSnapshot(); }); it("Reacts with the correct emoji", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(messageMock.react).toHaveBeenCalledTimes(1); - expect(reactArg).toMatchSnapshot(); + expect(messageMock.reactArg).toMatchSnapshot(); }); it("Sends log to the correct channel", async () => { await SpamBanningService.handleInteraction(interactionMock); - guild.channels.cache.forEach((channel) => { + interactionMock.guild.channels.cache.forEach((channel) => { if (channel.id === config.channels.moderationLog) { expect(channel.send).toHaveBeenCalledTimes(1); expect(channel.arg).toMatchSnapshot(); @@ -155,55 +102,121 @@ describe("Banning spammer who has DM set to private", () => { it("Sends back correct interaction reply to calling moderator", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(reply).toMatchSnapshot(); - }); -}); - -describe("Banning spammer that has left the server", () => { - let reactArg; - - const messageMock = { - author: { - id: "123", - send: jest.fn(() => {}), - }, - member: null, - react: jest.fn((arg) => { - reactArg = arg; - }), - }; - - let reply; - const interactionMock = { - reply: jest.fn((message) => { - reply = message; - }), - options: { - getMessage: () => messageMock, - }, - guild, - }; - - it("Author message sending api is not called", async () => { - await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.author.send).not.toHaveBeenCalled(); - }); - - it("Reacts with the correct emoji to automod message", async () => { - await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.react).toHaveBeenCalledTimes(1); - expect(reactArg).toMatchSnapshot(); - }); - - it("Does not log any channel", async () => { - await SpamBanningService.handleInteraction(interactionMock); - guild.channels.cache.forEach((channel) => { - expect(channel.send).not.toHaveBeenCalled(); - }); - }); - - it("Sends back correct interaction reply to calling moderator", async () => { - await SpamBanningService.handleInteraction(interactionMock); - expect(reply).toMatchSnapshot(); + expect(interactionMock.reply).toMatchSnapshot(); }); }); +// describe("Banning spammer who has DM set to private", () => { +// let banArg; +// let reactArg; +// +// const messageMock = { +// author: { +// id: "123", +// send: jest.fn(() => { +// throw new Error("Cannot send DM to user"); +// }), +// }, +// member: { +// ban: jest.fn((arg) => { +// banArg = arg; +// }), +// }, +// react: jest.fn((arg) => { +// reactArg = arg; +// }), +// }; +// +// let reply; +// const interactionMock = { +// reply: jest.fn((message) => { +// reply = message; +// }), +// options: { +// getMessage: () => messageMock, +// }, +// guild: createGuild(), +// }; +// +// it("Discord ban api is called with the correct reason", async () => { +// await SpamBanningService.handleInteraction(interactionMock); +// expect(messageMock.member.ban).toHaveBeenCalledTimes(1); +// expect(banArg).toMatchSnapshot(); +// }); +// +// it("Discord message api is called and error handled", async () => { +// await SpamBanningService.handleInteraction(interactionMock); +// expect(messageMock.author.send).toHaveBeenCalledTimes(1); +// }); +// +// it("Reacts with the correct emoji", async () => { +// await SpamBanningService.handleInteraction(interactionMock); +// expect(messageMock.react).toHaveBeenCalledTimes(1); +// expect(reactArg).toMatchSnapshot(); +// }); +// +// it("Sends log to the correct channel", async () => { +// await SpamBanningService.handleInteraction(interactionMock); +// interactionMock.guild.channels.cache.forEach((channel) => { +// if (channel.id === config.channels.moderationLog) { +// expect(channel.send).toHaveBeenCalledTimes(1); +// expect(channel.arg).toMatchSnapshot(); +// } else { +// expect(channel.send).not.toHaveBeenCalledTimes(1); +// } +// }); +// }); +// +// it("Sends back correct interaction reply to calling moderator", async () => { +// await SpamBanningService.handleInteraction(interactionMock); +// expect(reply).toMatchSnapshot(); +// }); +// }); +// +// describe("Banning spammer that has left the server", () => { +// let reactArg; +// +// const messageMock = { +// author: { +// id: "123", +// send: jest.fn(() => {}), +// }, +// member: null, +// react: jest.fn((arg) => { +// reactArg = arg; +// }), +// }; +// +// let reply; +// const interactionMock = { +// reply: jest.fn((message) => { +// reply = message; +// }), +// options: { +// getMessage: () => messageMock, +// }, +// guild: createGuild(), +// }; +// +// it("Author message sending api is not called", async () => { +// await SpamBanningService.handleInteraction(interactionMock); +// expect(messageMock.author.send).not.toHaveBeenCalled(); +// }); +// +// it("Reacts with the correct emoji to automod message", async () => { +// await SpamBanningService.handleInteraction(interactionMock); +// expect(messageMock.react).toHaveBeenCalledTimes(1); +// expect(reactArg).toMatchSnapshot(); +// }); +// +// it("Does not log any channel", async () => { +// await SpamBanningService.handleInteraction(interactionMock); +// interactionMock.guild.channels.cache.forEach((channel) => { +// expect(channel.send).not.toHaveBeenCalled(); +// }); +// }); +// +// it("Sends back correct interaction reply to calling moderator", async () => { +// await SpamBanningService.handleInteraction(interactionMock); +// expect(reply).toMatchSnapshot(); +// }); +// }); From d9474c00137246329437d5be5ee9bab64f98373f Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 13:59:28 +0200 Subject: [PATCH 32/70] Fix tests mocks --- .../spam-ban/spam-banning.service.test.js | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 090a3b2c..882afb22 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -10,8 +10,17 @@ function createInteractionMock(message, guild) { }), guild, + message, + + // Used by service to retrieve the message options: { getMessage: () => message }, + getReplyArg: () => replyArg, + getAuthorSendArg: () => message.getSendArg(), + getBanArg: () => message.getBanArg(), + getReactArg: () => message.getReactArg(), + getChannelSendArg: () => + guild.channels.cache.map((c) => c.getSendArg()).find((m) => m), }; } @@ -22,6 +31,7 @@ function createMessageMock() { return { author: { + id: "123", send: jest.fn((arg) => { sendArg = arg; }), @@ -40,52 +50,54 @@ function createMessageMock() { }; } -class ChannelMock { - constructor(id) { - this.id = id; - this.send = jest.fn((arg) => { - this.arg = arg; - }); - } +function createChannelMock(id) { + let sendArg; + return { + id, + send: jest.fn((arg) => { + sendArg = arg; + }), + getSendArg: () => sendArg, + }; } -const createGuild = () => ({ +const createGuildMock = () => ({ channels: { cache: [ - new ChannelMock("2342314"), - new ChannelMock("101010"), - new ChannelMock("22223333"), - new ChannelMock(config.channels.moderationLog), - new ChannelMock("2302382"), - new ChannelMock("000000"), + createChannelMock("2342314"), + createChannelMock("101010"), + createChannelMock("22223333"), + createChannelMock(config.channels.moderationLog), + createChannelMock("2302382"), + createChannelMock("000000"), ], }, }); describe("Banning spammer with DM enabled", () => { - const guild = createGuild(); - - const interactionMock = createInteractionMock( - createMessageMock(), - createGuild(), - ); + let interactionMock; + beforeEach(() => { + const messageMock = createMessageMock(); + const guildMock = createGuildMock(); + interactionMock = createInteractionMock(messageMock, guildMock); + }); it("Discord ban api is called with the correct reason", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).toHaveBeenCalledTimes(1); - expect(interactionMock.message.banArg).toMatchSnapshot(); + expect(interactionMock.getBanArg()).toMatchSnapshot(); }); it("Discord message api is called with the correct message", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.author.send).toHaveBeenCalledTimes(1); - expect(messageMock.sendArg).toMatchSnapshot(); + expect(interactionMock.message.author.send).toHaveBeenCalledTimes(1); + expect(interactionMock.getAuthorSendArg()).toMatchSnapshot(); }); it("Reacts with the correct emoji", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(messageMock.react).toHaveBeenCalledTimes(1); - expect(messageMock.reactArg).toMatchSnapshot(); + expect(interactionMock.message.react).toHaveBeenCalledTimes(1); + expect(interactionMock.getReactArg()).toMatchSnapshot(); }); it("Sends log to the correct channel", async () => { @@ -93,7 +105,7 @@ describe("Banning spammer with DM enabled", () => { interactionMock.guild.channels.cache.forEach((channel) => { if (channel.id === config.channels.moderationLog) { expect(channel.send).toHaveBeenCalledTimes(1); - expect(channel.arg).toMatchSnapshot(); + expect(interactionMock.getChannelSendArg()).toMatchSnapshot(); } else { expect(channel.send).not.toHaveBeenCalledTimes(1); } @@ -102,7 +114,7 @@ describe("Banning spammer with DM enabled", () => { it("Sends back correct interaction reply to calling moderator", async () => { await SpamBanningService.handleInteraction(interactionMock); - expect(interactionMock.reply).toMatchSnapshot(); + expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); }); // describe("Banning spammer who has DM set to private", () => { From 91c444a43e526617c4837d88f86a4e055dac76da Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:03:23 +0200 Subject: [PATCH 33/70] Fix second test suite --- .../spam-ban/spam-banning.service.test.js | 114 ++++++++---------- 1 file changed, 47 insertions(+), 67 deletions(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 882afb22..e535a7af 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -117,73 +117,53 @@ describe("Banning spammer with DM enabled", () => { expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); }); -// describe("Banning spammer who has DM set to private", () => { -// let banArg; -// let reactArg; -// -// const messageMock = { -// author: { -// id: "123", -// send: jest.fn(() => { -// throw new Error("Cannot send DM to user"); -// }), -// }, -// member: { -// ban: jest.fn((arg) => { -// banArg = arg; -// }), -// }, -// react: jest.fn((arg) => { -// reactArg = arg; -// }), -// }; -// -// let reply; -// const interactionMock = { -// reply: jest.fn((message) => { -// reply = message; -// }), -// options: { -// getMessage: () => messageMock, -// }, -// guild: createGuild(), -// }; -// -// it("Discord ban api is called with the correct reason", async () => { -// await SpamBanningService.handleInteraction(interactionMock); -// expect(messageMock.member.ban).toHaveBeenCalledTimes(1); -// expect(banArg).toMatchSnapshot(); -// }); -// -// it("Discord message api is called and error handled", async () => { -// await SpamBanningService.handleInteraction(interactionMock); -// expect(messageMock.author.send).toHaveBeenCalledTimes(1); -// }); -// -// it("Reacts with the correct emoji", async () => { -// await SpamBanningService.handleInteraction(interactionMock); -// expect(messageMock.react).toHaveBeenCalledTimes(1); -// expect(reactArg).toMatchSnapshot(); -// }); -// -// it("Sends log to the correct channel", async () => { -// await SpamBanningService.handleInteraction(interactionMock); -// interactionMock.guild.channels.cache.forEach((channel) => { -// if (channel.id === config.channels.moderationLog) { -// expect(channel.send).toHaveBeenCalledTimes(1); -// expect(channel.arg).toMatchSnapshot(); -// } else { -// expect(channel.send).not.toHaveBeenCalledTimes(1); -// } -// }); -// }); -// -// it("Sends back correct interaction reply to calling moderator", async () => { -// await SpamBanningService.handleInteraction(interactionMock); -// expect(reply).toMatchSnapshot(); -// }); -// }); -// + +describe("Banning spammer who has DM set to private", () => { + let interactionMock; + beforeEach(() => { + const guildMock = createGuildMock(); + const messageMock = createMessageMock(); + messageMock.author.send = jest.fn(() => { + throw new Error("Can't contact user"); + }); + interactionMock = createInteractionMock(messageMock, guildMock); + }); + + it("Discord ban api is called with the correct reason", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.member.ban).toHaveBeenCalledTimes(1); + expect(interactionMock.getBanArg()).toMatchSnapshot(); + }); + + it("Discord message api is called and error handled", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.author.send).toHaveBeenCalledTimes(1); + }); + + it("Reacts with the correct emoji", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.react).toHaveBeenCalledTimes(1); + expect(interactionMock.getReactArg()).toMatchSnapshot(); + }); + + it("Sends log to the correct channel", async () => { + await SpamBanningService.handleInteraction(interactionMock); + interactionMock.guild.channels.cache.forEach((channel) => { + if (channel.id === config.channels.moderationLog) { + expect(channel.send).toHaveBeenCalledTimes(1); + expect(channel.getSendArg()).toMatchSnapshot(); + } else { + expect(channel.send).not.toHaveBeenCalledTimes(1); + } + }); + }); + + it("Sends back correct interaction reply to calling moderator", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.getReplyArg()).toMatchSnapshot(); + }); +}); + // describe("Banning spammer that has left the server", () => { // let reactArg; // From 1652dcf8e24aed57ac601fb2d58bf1731d7125dd Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:05:29 +0200 Subject: [PATCH 34/70] Finish up third test suite --- .../spam-ban/spam-banning.service.test.js | 82 ++++++++----------- 1 file changed, 33 insertions(+), 49 deletions(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index e535a7af..65d4245e 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -121,8 +121,8 @@ describe("Banning spammer with DM enabled", () => { describe("Banning spammer who has DM set to private", () => { let interactionMock; beforeEach(() => { - const guildMock = createGuildMock(); const messageMock = createMessageMock(); + const guildMock = createGuildMock(); messageMock.author.send = jest.fn(() => { throw new Error("Can't contact user"); }); @@ -164,51 +164,35 @@ describe("Banning spammer who has DM set to private", () => { }); }); -// describe("Banning spammer that has left the server", () => { -// let reactArg; -// -// const messageMock = { -// author: { -// id: "123", -// send: jest.fn(() => {}), -// }, -// member: null, -// react: jest.fn((arg) => { -// reactArg = arg; -// }), -// }; -// -// let reply; -// const interactionMock = { -// reply: jest.fn((message) => { -// reply = message; -// }), -// options: { -// getMessage: () => messageMock, -// }, -// guild: createGuild(), -// }; -// -// it("Author message sending api is not called", async () => { -// await SpamBanningService.handleInteraction(interactionMock); -// expect(messageMock.author.send).not.toHaveBeenCalled(); -// }); -// -// it("Reacts with the correct emoji to automod message", async () => { -// await SpamBanningService.handleInteraction(interactionMock); -// expect(messageMock.react).toHaveBeenCalledTimes(1); -// expect(reactArg).toMatchSnapshot(); -// }); -// -// it("Does not log any channel", async () => { -// await SpamBanningService.handleInteraction(interactionMock); -// interactionMock.guild.channels.cache.forEach((channel) => { -// expect(channel.send).not.toHaveBeenCalled(); -// }); -// }); -// -// it("Sends back correct interaction reply to calling moderator", async () => { -// await SpamBanningService.handleInteraction(interactionMock); -// expect(reply).toMatchSnapshot(); -// }); -// }); +describe("Banning spammer that has left the server", () => { + let interactionMock; + beforeEach(() => { + const messageMock = createMessageMock(); + const guildMock = createGuildMock(); + messageMock.member = null; + interactionMock = createInteractionMock(messageMock, guildMock); + }); + + it("Author message sending api is not called", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.author.send).not.toHaveBeenCalled(); + }); + + it("Reacts with the correct emoji to automod message", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.react).toHaveBeenCalledTimes(1); + expect(interactionMock.getReactArg()).toMatchSnapshot(); + }); + + it("Does not log any channel", async () => { + await SpamBanningService.handleInteraction(interactionMock); + interactionMock.guild.channels.cache.forEach((channel) => { + expect(channel.send).not.toHaveBeenCalled(); + }); + }); + + it("Sends back correct interaction reply to calling moderator", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.getReplyArg()).toMatchSnapshot(); + }); +}); From 26b5e4e894aa3103e4e0956d66e3d5a87aa8ad07 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:16:11 +0200 Subject: [PATCH 35/70] Refactor to test specifically for channel id arguments --- services/spam-ban/spam-banning.service.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 65d4245e..2659f849 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -20,7 +20,9 @@ function createInteractionMock(message, guild) { getBanArg: () => message.getBanArg(), getReactArg: () => message.getReactArg(), getChannelSendArg: () => - guild.channels.cache.map((c) => c.getSendArg()).find((m) => m), + guild.channels.cache + .find((c) => c.id === config.channels.moderationLog) + .getSendArg(), }; } From 57d990279c5cb096038acb2831e409470b046848 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:43:57 +0200 Subject: [PATCH 36/70] Add tests against banning a bot --- .../spam-ban/spam-banning.service.test.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 2659f849..f0f189bf 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -34,11 +34,15 @@ function createMessageMock() { return { author: { id: "123", + bot: false, send: jest.fn((arg) => { sendArg = arg; }), }, member: { + roles: { + cache: [], + }, ban: jest.fn((arg) => { banArg = arg; }), @@ -198,3 +202,20 @@ describe("Banning spammer that has left the server", () => { expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); }); + +describe("Attempting to bann a bot or a member with admin role", () => { + let interactionMock; + beforeEach(() => { + const messageMock = createMessageMock(); + const guildMock = createGuildMock(); + interactionMock = createInteractionMock(messageMock, guildMock); + }); + + it("Attempting to ban a bot", async () => { + interactionMock.message.author.bot = true; + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); + expect(interactionMock.message.author.send).not.toHaveBeenCalled(); + expect(interactionMock.message.react).not.toHaveBeenCalled(); + }); +}); From 8771039fd3115dc6a6eb4962e24bab8a5336e3d3 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:17:29 +0200 Subject: [PATCH 37/70] Add tests for banning a bot --- .../spam-banning.service.test.js.snap | 2 ++ .../spam-ban/spam-banning.service.test.js | 20 ++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index db0e95a3..95d6ea12 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -1,5 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Attempting to bann a bot Sends back correct reply 1`] = `undefined`; + exports[`Banning spammer that has left the server Reacts with the correct emoji to automod message 1`] = `"❌"`; exports[`Banning spammer that has left the server Sends back correct interaction reply to calling moderator 1`] = ` diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index f0f189bf..c284032b 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -203,19 +203,33 @@ describe("Banning spammer that has left the server", () => { }); }); -describe("Attempting to bann a bot or a member with admin role", () => { +describe("Attempting to bann a bot", () => { let interactionMock; beforeEach(() => { const messageMock = createMessageMock(); const guildMock = createGuildMock(); interactionMock = createInteractionMock(messageMock, guildMock); + interactionMock.message.author.bot = true; }); - it("Attempting to ban a bot", async () => { - interactionMock.message.author.bot = true; + it("Does not call ban api", async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); + }); + + it("Does not call send api", async () => { + await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); expect(interactionMock.message.react).not.toHaveBeenCalled(); }); + + it("Does not call react api", async () => { + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.react).not.toHaveBeenCalled(); + }); + + it("Sends back correct reply", async () => { + expect(interactionMock.getReplyArg()).toMatchSnapshot(); + await SpamBanningService.handleInteraction(interactionMock); + }); }); From f6f1b49649932121fa487b4967edd052c50e5221 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:22:14 +0200 Subject: [PATCH 38/70] Refactor test repitition --- .../spam-banning.service.test.js.snap | 2 +- .../spam-ban/spam-banning.service.test.js | 20 ++++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index 95d6ea12..9ce2d985 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Attempting to bann a bot Sends back correct reply 1`] = `undefined`; +exports[`Attempting to bann a bot or admin Does not ban a bot 1`] = `undefined`; exports[`Banning spammer that has left the server Reacts with the correct emoji to automod message 1`] = `"❌"`; diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index c284032b..89e8d3bf 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -203,33 +203,29 @@ describe("Banning spammer that has left the server", () => { }); }); -describe("Attempting to bann a bot", () => { +describe("Attempting to bann a bot or admin", () => { let interactionMock; beforeEach(() => { const messageMock = createMessageMock(); const guildMock = createGuildMock(); interactionMock = createInteractionMock(messageMock, guildMock); - interactionMock.message.author.bot = true; }); - it("Does not call ban api", async () => { + it("Does not ban a bot", async () => { + interactionMock.message.author.bot = true; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); - }); - - it("Does not call send api", async () => { - await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); expect(interactionMock.message.react).not.toHaveBeenCalled(); + expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); - it("Does not call react api", async () => { + it("Does not ban a moderator", async () => { + interactionMock.message.member.roles.cache = ["moderator"]; await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); + expect(interactionMock.message.author.send).not.toHaveBeenCalled(); expect(interactionMock.message.react).not.toHaveBeenCalled(); - }); - - it("Sends back correct reply", async () => { expect(interactionMock.getReplyArg()).toMatchSnapshot(); - await SpamBanningService.handleInteraction(interactionMock); }); }); From cfca7b44cf2de49eae82069f78beebaffb370e3c Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:27:01 +0200 Subject: [PATCH 39/70] Add logic to prevent banning an admin --- .../spam-banning.service.test.js.snap | 12 +++++++++++- services/spam-ban/spam-banning.service.js | 17 ++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index 9ce2d985..e7db2f40 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -1,6 +1,16 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Attempting to bann a bot or admin Does not ban a bot 1`] = `undefined`; +exports[`Attempting to bann a bot or admin Does not ban a bot 1`] = ` +{ + "content": "You do not have the permission to ban this user", +} +`; + +exports[`Attempting to bann a bot or admin Does not ban a moderator 1`] = ` +{ + "content": "You do not have the permission to ban this user", +} +`; exports[`Banning spammer that has left the server Reacts with the correct emoji to automod message 1`] = `"❌"`; diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 58b3202d..4ab41581 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -4,7 +4,12 @@ const config = require("../../config"); class SpamBanningService { static async handleInteraction(interaction) { const message = interaction.options.getMessage("message"); - if (message.author.bot) return; + if (message.author.bot || SpamBanningService.#isAdmin(message.member)) { + interaction.reply({ + content: "You do not have the permission to ban this user", + }); + return; + } let reply; try { @@ -57,6 +62,16 @@ class SpamBanningService { ); channel.send("Hello fred"); } + + static #isAdmin(member) { + if (!member) { + return false; + } + + return member.roles.cache.some((role) => + config.roles.adminRolesName.includes(role), + ); + } } module.exports = SpamBanningService; From 0f24ae00ab0e64af3d8e856d61a318549172902e Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:33:08 +0200 Subject: [PATCH 40/70] Refactor and add other team members tests --- .../spam-banning.service.test.js.snap | 18 ++++++++-- .../spam-ban/spam-banning.service.test.js | 34 +++++++++++++++++-- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index e7db2f40..b40f20fc 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -1,12 +1,26 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Attempting to bann a bot or admin Does not ban a bot 1`] = ` +exports[`Attempting to bann a bot or team member Does not ban admins 1`] = ` { "content": "You do not have the permission to ban this user", } `; -exports[`Attempting to bann a bot or admin Does not ban a moderator 1`] = ` +exports[`Attempting to bann a bot or team member Does not ban bots 1`] = ` +{ + "content": "You do not have the permission to ban this user", +} +`; + +exports[`Attempting to bann a bot or team member Does not ban core 1`] = `""`; + +exports[`Attempting to bann a bot or team member Does not ban maintainers 1`] = ` +{ + "content": "You do not have the permission to ban this user", +} +`; + +exports[`Attempting to bann a bot or team member Does not ban moderators 1`] = ` { "content": "You do not have the permission to ban this user", } diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 89e8d3bf..b6fcfc8a 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -203,7 +203,7 @@ describe("Banning spammer that has left the server", () => { }); }); -describe("Attempting to bann a bot or admin", () => { +describe("Attempting to bann a bot or team member", () => { let interactionMock; beforeEach(() => { const messageMock = createMessageMock(); @@ -211,7 +211,7 @@ describe("Attempting to bann a bot or admin", () => { interactionMock = createInteractionMock(messageMock, guildMock); }); - it("Does not ban a bot", async () => { + it("Does not ban bots", async () => { interactionMock.message.author.bot = true; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); @@ -220,7 +220,7 @@ describe("Attempting to bann a bot or admin", () => { expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); - it("Does not ban a moderator", async () => { + it("Does not ban moderators", async () => { interactionMock.message.member.roles.cache = ["moderator"]; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); @@ -228,4 +228,32 @@ describe("Attempting to bann a bot or admin", () => { expect(interactionMock.message.react).not.toHaveBeenCalled(); expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); + + it("Does not ban maintainers", async () => { + interactionMock.message.member.roles.cache = ["maintainer"]; + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); + expect(interactionMock.message.author.send).not.toHaveBeenCalled(); + expect(interactionMock.message.react).not.toHaveBeenCalled(); + expect(interactionMock.getReplyArg()).toMatchSnapshot(); + }); + + it("Does not ban core", async () => { + interactionMock.message.member.roles.cache = ["core"]; + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); + expect(interactionMock.message.author.send).not.toHaveBeenCalled(); + expect(interactionMock.message.react).not.toHaveBeenCalled(); + interactionMock.getReplyArg = () => ""; + expect(interactionMock.getReplyArg()).toMatchSnapshot(); + }); + + it("Does not ban admins", async () => { + interactionMock.message.member.roles.cache = ["admin"]; + await SpamBanningService.handleInteraction(interactionMock); + expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); + expect(interactionMock.message.author.send).not.toHaveBeenCalled(); + expect(interactionMock.message.react).not.toHaveBeenCalled(); + expect(interactionMock.getReplyArg()).toMatchSnapshot(); + }); }); From c080030f8d4d444e67e92f2ca01f5f50ab28e564 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:42:33 +0200 Subject: [PATCH 41/70] Fix bug of retrieving user role name without using the name field --- services/spam-ban/spam-banning.service.js | 2 +- services/spam-ban/spam-banning.service.test.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 4ab41581..be896aa2 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -69,7 +69,7 @@ class SpamBanningService { } return member.roles.cache.some((role) => - config.roles.adminRolesName.includes(role), + config.roles.adminRolesName.includes(role.name), ); } } diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index b6fcfc8a..b40d3d88 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -221,7 +221,7 @@ describe("Attempting to bann a bot or team member", () => { }); it("Does not ban moderators", async () => { - interactionMock.message.member.roles.cache = ["moderator"]; + interactionMock.message.member.roles.cache = [{ name: "moderator" }]; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); @@ -230,7 +230,7 @@ describe("Attempting to bann a bot or team member", () => { }); it("Does not ban maintainers", async () => { - interactionMock.message.member.roles.cache = ["maintainer"]; + interactionMock.message.member.roles.cache = [{ name: "maintainer" }]; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); @@ -239,7 +239,7 @@ describe("Attempting to bann a bot or team member", () => { }); it("Does not ban core", async () => { - interactionMock.message.member.roles.cache = ["core"]; + interactionMock.message.member.roles.cache = [{ name: "core" }]; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); @@ -249,7 +249,7 @@ describe("Attempting to bann a bot or team member", () => { }); it("Does not ban admins", async () => { - interactionMock.message.member.roles.cache = ["admin"]; + interactionMock.message.member.roles.cache = [{ name: "admin" }]; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); From e0e2ee15ac09d58b62b1569f7ad46e4702a233cf Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Wed, 12 Jun 2024 12:56:29 +0200 Subject: [PATCH 42/70] Update logging message --- .../spam-banning.service.test.js.snap | 70 ++++++++++++++++++- services/spam-ban/spam-banning.service.js | 40 +++++++++-- .../spam-ban/spam-banning.service.test.js | 9 ++- 3 files changed, 112 insertions(+), 7 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index b40f20fc..81dd9e76 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -48,7 +48,40 @@ exports[`Banning spammer who has DM set to private Sends back correct interactio } `; -exports[`Banning spammer who has DM set to private Sends log to the correct channel 1`] = `"Hello fred"`; +exports[`Banning spammer who has DM set to private Sends log to the correct channel 1`] = ` +{ + "embeds": [ + { + "author": { + "icon_url": "image.jpg", + "name": "Ban | bad.spammer", + }, + "color": 15747399, + "fields": [ + { + "inline": true, + "name": "User", + "value": "<@123>", + }, + { + "inline": true, + "name": "Moderator", + "value": "<@007>", + }, + { + "inline": true, + "name": "Reason", + "value": "Account is compromised and spamming phishing links.", + }, + ], + "footer": { + "text": "ID: 222", + }, + "timestamp": "2024-06-12T10:56:17.844Z", + }, + ], +} +`; exports[`Banning spammer with DM enabled Discord ban api is called with the correct reason 1`] = ` { @@ -78,4 +111,37 @@ exports[`Banning spammer with DM enabled Sends back correct interaction reply to } `; -exports[`Banning spammer with DM enabled Sends log to the correct channel 1`] = `"Hello fred"`; +exports[`Banning spammer with DM enabled Sends log to the correct channel 1`] = ` +{ + "embeds": [ + { + "author": { + "icon_url": "image.jpg", + "name": "Ban | bad.spammer", + }, + "color": 15747399, + "fields": [ + { + "inline": true, + "name": "User", + "value": "<@123>", + }, + { + "inline": true, + "name": "Moderator", + "value": "<@007>", + }, + { + "inline": true, + "name": "Reason", + "value": "Account is compromised and spamming phishing links.", + }, + ], + "footer": { + "text": "ID: 222", + }, + "timestamp": "2024-06-12T10:56:17.836Z", + }, + ], +} +`; diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index be896aa2..84339dc6 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -11,8 +11,9 @@ class SpamBanningService { return; } - let reply; try { + let reply; + if (!message.member) { message.react("❌"); reply = { @@ -20,8 +21,9 @@ class SpamBanningService { }; } else { reply = await SpamBanningService.#banUser(message); - await SpamBanningService.#announceBan(interaction); + await SpamBanningService.#announceBan(interaction, message); } + interaction.reply(reply); } catch (error) { console.error(error); @@ -55,12 +57,42 @@ class SpamBanningService { await author.send({ embeds: [embedMessage] }); } - static async #announceBan(interaction) { + static async #announceBan(interaction, message) { + const embed = { + timestamp: `${new Date().toISOString()}`, + color: 15747399, + footer: { + text: `ID: ${interaction.id}`, + }, + author: { + name: `Ban | ${message.author.username}`, + icon_url: `${message.author.displayAvatarURL()}`, + }, + fields: [ + { + value: `<@${message.author.id}>`, + name: "User", + inline: true, + }, + { + value: `<@${interaction.user.id}>`, + name: "Moderator", + inline: true, + }, + { + value: "Account is compromised and spamming phishing links.", + name: "Reason", + inline: true, + }, + ], + }; + const channelID = config.channels.moderationLog; const channel = interaction.guild.channels.cache.find( (c) => c.id === channelID, ); - channel.send("Hello fred"); + + channel.send({ embeds: [embed] }); } static #isAdmin(member) { diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index b40d3d88..f5b73c41 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -5,13 +5,18 @@ function createInteractionMock(message, guild) { let replyArg; return { + id: "222", reply: jest.fn((arg) => { replyArg = arg; }), - guild, message, + // The mode who initialized the interaction + user: { + id: "007", + }, + // Used by service to retrieve the message options: { getMessage: () => message }, @@ -34,10 +39,12 @@ function createMessageMock() { return { author: { id: "123", + username: "bad.spammer", bot: false, send: jest.fn((arg) => { sendArg = arg; }), + displayAvatarURL: () => "image.jpg", }, member: { roles: { From 90c52c801356bc17003ca23482e28cb5c43d7615 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 13 Jun 2024 09:57:00 +0200 Subject: [PATCH 43/70] Refactor interaction reply to be emphernal --- .../__snapshots__/spam-banning.service.test.js.snap | 11 +++++++++-- services/spam-ban/spam-banning.service.js | 9 ++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index 81dd9e76..f29e37e5 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -3,12 +3,14 @@ exports[`Attempting to bann a bot or team member Does not ban admins 1`] = ` { "content": "You do not have the permission to ban this user", + "ephemeral": true, } `; exports[`Attempting to bann a bot or team member Does not ban bots 1`] = ` { "content": "You do not have the permission to ban this user", + "ephemeral": true, } `; @@ -17,12 +19,14 @@ exports[`Attempting to bann a bot or team member Does not ban core 1`] = `""`; exports[`Attempting to bann a bot or team member Does not ban maintainers 1`] = ` { "content": "You do not have the permission to ban this user", + "ephemeral": true, } `; exports[`Attempting to bann a bot or team member Does not ban moderators 1`] = ` { "content": "You do not have the permission to ban this user", + "ephemeral": true, } `; @@ -31,6 +35,7 @@ exports[`Banning spammer that has left the server Reacts with the correct emoji exports[`Banning spammer that has left the server Sends back correct interaction reply to calling moderator 1`] = ` { "content": "Couldn't bann <@123>. User is not on the server.", + "ephemeral": true, } `; @@ -45,6 +50,7 @@ exports[`Banning spammer who has DM set to private Reacts with the correct emoji exports[`Banning spammer who has DM set to private Sends back correct interaction reply to calling moderator 1`] = ` { "content": "Banned <@123> for spam but wasn't able to contact the user.", + "ephemeral": true, } `; @@ -77,7 +83,7 @@ exports[`Banning spammer who has DM set to private Sends log to the correct chan "footer": { "text": "ID: 222", }, - "timestamp": "2024-06-12T10:56:17.844Z", + "timestamp": "2024-06-13T07:56:40.392Z", }, ], } @@ -108,6 +114,7 @@ exports[`Banning spammer with DM enabled Reacts with the correct emoji 1`] = `" exports[`Banning spammer with DM enabled Sends back correct interaction reply to calling moderator 1`] = ` { "content": "Banned <@123> for spam successfully.", + "ephemeral": true, } `; @@ -140,7 +147,7 @@ exports[`Banning spammer with DM enabled Sends log to the correct channel 1`] = "footer": { "text": "ID: 222", }, - "timestamp": "2024-06-12T10:56:17.836Z", + "timestamp": "2024-06-13T07:56:40.385Z", }, ], } diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 84339dc6..7c9096ec 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -7,6 +7,7 @@ class SpamBanningService { if (message.author.bot || SpamBanningService.#isAdmin(message.member)) { interaction.reply({ content: "You do not have the permission to ban this user", + ephemeral: true, }); return; } @@ -16,15 +17,13 @@ class SpamBanningService { if (!message.member) { message.react("❌"); - reply = { - content: `Couldn't bann <@${message.author.id}>. User is not on the server.`, - }; + reply = `Couldn't bann <@${message.author.id}>. User is not on the server.`; } else { reply = await SpamBanningService.#banUser(message); await SpamBanningService.#announceBan(interaction, message); } - interaction.reply(reply); + interaction.reply({ content: reply, ephemeral: true }); } catch (error) { console.error(error); } @@ -41,7 +40,7 @@ class SpamBanningService { message.member.ban({ reason: "Account is compromised" }); message.react("✅"); - return { content: reply }; + return reply; } static async #sendMessageToUser(author) { From 55d3b4017731a8a1ea544372e36dc1002cdb13f0 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:03:32 +0200 Subject: [PATCH 44/70] Fix mock time to not fail tests that require timestamp snapshot --- .../__snapshots__/spam-banning.service.test.js.snap | 4 ++-- services/spam-ban/spam-banning.service.test.js | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index f29e37e5..f346fa2a 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -83,7 +83,7 @@ exports[`Banning spammer who has DM set to private Sends log to the correct chan "footer": { "text": "ID: 222", }, - "timestamp": "2024-06-13T07:56:40.392Z", + "timestamp": "2024-01-31T23:00:00.000Z", }, ], } @@ -147,7 +147,7 @@ exports[`Banning spammer with DM enabled Sends log to the correct channel 1`] = "footer": { "text": "ID: 222", }, - "timestamp": "2024-06-13T07:56:40.385Z", + "timestamp": "2024-01-31T23:00:00.000Z", }, ], } diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index f5b73c41..7838e816 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -1,6 +1,15 @@ const SpamBanningService = require("./spam-banning.service"); const config = require("../../config"); +beforeAll(() => { + jest.useFakeTimers("modern"); + jest.setSystemTime(new Date(2024, 1, 1)); +}); + +afterAll(() => { + jest.useRealTimers(); +}); + function createInteractionMock(message, guild) { let replyArg; From 11a660bddee45316152521e2242c44ad96c4e076 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:18:21 +0200 Subject: [PATCH 45/70] Fix comment typo --- services/spam-ban/spam-banning.service.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 7838e816..884efac9 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -21,7 +21,7 @@ function createInteractionMock(message, guild) { guild, message, - // The mode who initialized the interaction + // The mod who initialized the interaction user: { id: "007", }, From 84e08dd315be2ca74d56cbb380be5551d1d932c1 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:31:18 +0200 Subject: [PATCH 46/70] Update permission to mods with ability to ban only --- new-era-commands/context-menu/bann-spammer.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/new-era-commands/context-menu/bann-spammer.js b/new-era-commands/context-menu/bann-spammer.js index 4f1e4436..3227d67f 100644 --- a/new-era-commands/context-menu/bann-spammer.js +++ b/new-era-commands/context-menu/bann-spammer.js @@ -1,15 +1,11 @@ -const { - ContextMenuCommandBuilder, - ApplicationCommandType, - PermissionFlagsBits, -} = require("discord.js"); +const { ContextMenuCommandBuilder, ApplicationCommandType, PermissionFlagsBits, } = require("discord.js"); const SpamBanningService = require("../../services/spam-ban/spam-banning.service"); module.exports = { data: new ContextMenuCommandBuilder() .setName("Bann Spammer") .setType(ApplicationCommandType.Message) - .setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages), + .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers), execute: async (interaction) => { await SpamBanningService.handleInteraction(interaction); }, From 7b06e7e19b1dc888afcfa7467d879c9ba8aa5356 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:41:41 +0200 Subject: [PATCH 47/70] Fix tests for core members --- .../__snapshots__/spam-banning.service.test.js.snap | 7 ++++++- services/spam-ban/spam-banning.service.test.js | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index f346fa2a..a4e6fbd6 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -14,7 +14,12 @@ exports[`Attempting to bann a bot or team member Does not ban bots 1`] = ` } `; -exports[`Attempting to bann a bot or team member Does not ban core 1`] = `""`; +exports[`Attempting to bann a bot or team member Does not ban core 1`] = ` +{ + "content": "You do not have the permission to ban this user", + "ephemeral": true, +} +`; exports[`Attempting to bann a bot or team member Does not ban maintainers 1`] = ` { diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 884efac9..c62b9e53 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -260,7 +260,6 @@ describe("Attempting to bann a bot or team member", () => { expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); expect(interactionMock.message.react).not.toHaveBeenCalled(); - interactionMock.getReplyArg = () => ""; expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); From a783143159c61c41f7203e955e09fb02e795ebec Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:10:33 +0200 Subject: [PATCH 48/70] Update to use user ID --- services/spam-ban/spam-banning.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 7c9096ec..cc0b1ca8 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -61,7 +61,7 @@ class SpamBanningService { timestamp: `${new Date().toISOString()}`, color: 15747399, footer: { - text: `ID: ${interaction.id}`, + text: `ID: ${message.author.id}`, }, author: { name: `Ban | ${message.author.username}`, From 6b37c9b81053243acd1456ba33054f4ddf6f5638 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:11:21 +0200 Subject: [PATCH 49/70] Update tests --- .../spam-ban/__snapshots__/spam-banning.service.test.js.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index a4e6fbd6..f0ebbb44 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -86,7 +86,7 @@ exports[`Banning spammer who has DM set to private Sends log to the correct chan }, ], "footer": { - "text": "ID: 222", + "text": "ID: 123", }, "timestamp": "2024-01-31T23:00:00.000Z", }, @@ -150,7 +150,7 @@ exports[`Banning spammer with DM enabled Sends log to the correct channel 1`] = }, ], "footer": { - "text": "ID: 222", + "text": "ID: 123", }, "timestamp": "2024-01-31T23:00:00.000Z", }, From 4c3d730831fdae984aa04d814e0bd4789a95c3cd Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:19:24 +0200 Subject: [PATCH 50/70] Update channel id name --- services/spam-ban/spam-banning.service.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index c62b9e53..f2b3e84d 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -14,7 +14,6 @@ function createInteractionMock(message, guild) { let replyArg; return { - id: "222", reply: jest.fn((arg) => { replyArg = arg; }), From def4298a01ae23cf342b2313806a6c72ab8bf357 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:25:16 +0200 Subject: [PATCH 51/70] Refactor channel name id in tests --- services/spam-ban/spam-banning.service.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index f2b3e84d..859022b2 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -34,7 +34,7 @@ function createInteractionMock(message, guild) { getReactArg: () => message.getReactArg(), getChannelSendArg: () => guild.channels.cache - .find((c) => c.id === config.channels.moderationLog) + .find((c) => c.id === config.channels.moderationLogChannelId) .getSendArg(), }; } @@ -88,7 +88,7 @@ const createGuildMock = () => ({ createChannelMock("2342314"), createChannelMock("101010"), createChannelMock("22223333"), - createChannelMock(config.channels.moderationLog), + createChannelMock(config.channels.moderationLogChannelId), createChannelMock("2302382"), createChannelMock("000000"), ], @@ -124,7 +124,7 @@ describe("Banning spammer with DM enabled", () => { it("Sends log to the correct channel", async () => { await SpamBanningService.handleInteraction(interactionMock); interactionMock.guild.channels.cache.forEach((channel) => { - if (channel.id === config.channels.moderationLog) { + if (channel.id === config.channels.moderationLogChannelId) { expect(channel.send).toHaveBeenCalledTimes(1); expect(interactionMock.getChannelSendArg()).toMatchSnapshot(); } else { @@ -170,7 +170,7 @@ describe("Banning spammer who has DM set to private", () => { it("Sends log to the correct channel", async () => { await SpamBanningService.handleInteraction(interactionMock); interactionMock.guild.channels.cache.forEach((channel) => { - if (channel.id === config.channels.moderationLog) { + if (channel.id === config.channels.moderationLogChannelId) { expect(channel.send).toHaveBeenCalledTimes(1); expect(channel.getSendArg()).toMatchSnapshot(); } else { From 844d413143d637487dc08988a998a5f5cf43e2ff Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:52:27 +0200 Subject: [PATCH 52/70] Update user message --- services/spam-ban/spam-banning.service.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index cc0b1ca8..aa2df4d7 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -30,9 +30,9 @@ class SpamBanningService { } static async #banUser(message) { - // Make sure to send the message before banning otherwise user will not be found let reply = `Banned <@${message.author.id}> for spam successfully.`; try { + // Make sure to send the message before banning otherwise user will not be found await SpamBanningService.#sendMessageToUser(message.author); } catch (error) { reply = `Banned <@${message.author.id}> for spam but wasn't able to contact the user.`; @@ -47,11 +47,11 @@ class SpamBanningService { const embedMessage = new EmbedBuilder() .setTitle("Banned: Compromised account / Spam") .setDescription( - `Account is compromised and is used to spam phishing links. + `Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in [this Discord support article](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised) to secure your account. - If you would still like to continue using our server, make sure to change your password and recover your account. - After that send a detailed contact information to appeal the ban on theodinprojectcontact@gmail.com`, - ); +Once your account is secure, you may appeal your ban by emailing [theodinprojectcontact@gmail.com](mailto:theodinprojectcontact@gmail.com) with your Discord username and that you are appealing your ban due to a compromised account. + +Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.`); await author.send({ embeds: [embedMessage] }); } From 7f47a61643ad648efcbd7e22265f54f71d4df80c Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:52:57 +0200 Subject: [PATCH 53/70] Update channel id name --- services/spam-ban/spam-banning.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index aa2df4d7..12f8bd75 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -86,7 +86,7 @@ Note: It may take several days for our volunteer staff to take action on your ap ], }; - const channelID = config.channels.moderationLog; + const channelID = config.channels.moderationLogChannelId; const channel = interaction.guild.channels.cache.find( (c) => c.id === channelID, ); From 0621b11053844ee2b6e2f64242b9707cc123d4ca Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:53:36 +0200 Subject: [PATCH 54/70] Update tests --- .../__snapshots__/spam-banning.service.test.js.snap | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index f0ebbb44..452282ca 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -104,10 +104,11 @@ exports[`Banning spammer with DM enabled Discord message api is called with the { "embeds": [ { - "description": "Account is compromised and is used to spam phishing links. + "description": "Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in [this Discord support article](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised) to secure your account. - If you would still like to continue using our server, make sure to change your password and recover your account. - After that send a detailed contact information to appeal the ban on theodinprojectcontact@gmail.com", +Once your account is secure, you may appeal your ban by emailing [theodinprojectcontact@gmail.com](mailto:theodinprojectcontact@gmail.com) with your Discord username and that you are appealing your ban due to a compromised account. + +Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.", "title": "Banned: Compromised account / Spam", }, ], From 47e7f750ae9ba5571d778fd96e2d2e34d8c79bf4 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:05:06 +0200 Subject: [PATCH 55/70] Update date object to work with github cli test tools --- .../spam-ban/__snapshots__/spam-banning.service.test.js.snap | 4 ++-- services/spam-ban/spam-banning.service.test.js | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index 452282ca..3d18af5b 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -88,7 +88,7 @@ exports[`Banning spammer who has DM set to private Sends log to the correct chan "footer": { "text": "ID: 123", }, - "timestamp": "2024-01-31T23:00:00.000Z", + "timestamp": "2024-02-01T00:00:00.000Z", }, ], } @@ -153,7 +153,7 @@ exports[`Banning spammer with DM enabled Sends log to the correct channel 1`] = "footer": { "text": "ID: 123", }, - "timestamp": "2024-01-31T23:00:00.000Z", + "timestamp": "2024-02-01T00:00:00.000Z", }, ], } diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 859022b2..f4ef0c16 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -2,8 +2,9 @@ const SpamBanningService = require("./spam-banning.service"); const config = require("../../config"); beforeAll(() => { - jest.useFakeTimers("modern"); - jest.setSystemTime(new Date(2024, 1, 1)); + jest.useFakeTimers(); + // Date.UTC Required so that test snippets match on different timezones + jest.setSystemTime(new Date(Date.UTC(2024, 1, 1))); }); afterAll(() => { From d13b2740d7351af9a15cea3aa4d53b188d866f29 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 15:04:50 +0200 Subject: [PATCH 56/70] Update to use fetch method on getting the channel --- services/spam-ban/spam-banning.service.js | 5 +---- services/spam-ban/spam-banning.service.test.js | 15 ++++++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 12f8bd75..71913aa1 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -87,10 +87,7 @@ Note: It may take several days for our volunteer staff to take action on your ap }; const channelID = config.channels.moderationLogChannelId; - const channel = interaction.guild.channels.cache.find( - (c) => c.id === channelID, - ); - + const channel = interaction.guild.channels.fetch(channelID); channel.send({ embeds: [embed] }); } diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index f4ef0c16..31f9f869 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -83,18 +83,23 @@ function createChannelMock(id) { }; } -const createGuildMock = () => ({ - channels: { +function createGuildMock() { + const channelId = config.channels.moderationLogChannelId; + const moderationLogChannel = createChannelMock(channelId); + return { + channels: { cache: [ createChannelMock("2342314"), createChannelMock("101010"), createChannelMock("22223333"), - createChannelMock(config.channels.moderationLogChannelId), + moderationLogChannel, createChannelMock("2302382"), createChannelMock("000000"), ], - }, -}); + fetch: (id) => id === channelId ? moderationLogChannel : undefined, + } +} +} describe("Banning spammer with DM enabled", () => { let interactionMock; From 5db3444d456661ede0844ac95fd1b30e5a2159a3 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 15:57:35 +0200 Subject: [PATCH 57/70] Update to handle fetch promise --- services/spam-ban/spam-banning.service.js | 8 ++++++-- services/spam-ban/spam-banning.service.test.js | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 71913aa1..9b28ab95 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -87,8 +87,12 @@ Note: It may take several days for our volunteer staff to take action on your ap }; const channelID = config.channels.moderationLogChannelId; - const channel = interaction.guild.channels.fetch(channelID); - channel.send({ embeds: [embed] }); + const channel = await interaction.guild.channels.fetch(channelID); + if (channel == null) { + console.error("No channel of that ID were found"); + } else { + channel.send({ embeds: [embed] }); + } } static #isAdmin(member) { diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 31f9f869..90221b9a 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -96,7 +96,7 @@ function createGuildMock() { createChannelMock("2302382"), createChannelMock("000000"), ], - fetch: (id) => id === channelId ? moderationLogChannel : undefined, + fetch: async (id) => id === channelId ? moderationLogChannel : undefined, } } } From dfc53bc74b561d89cd276795229935f0d887d6a0 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:17:19 +0200 Subject: [PATCH 58/70] Add handling error when channel is not found --- .../spam-banning.service.test.js.snap | 35 +++++++++++++++++++ services/spam-ban/spam-banning.service.js | 14 ++++---- .../spam-ban/spam-banning.service.test.js | 34 +++++++++++++++++- 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index 3d18af5b..bbf68e1d 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -35,6 +35,41 @@ exports[`Attempting to bann a bot or team member Does not ban moderators 1`] = ` } `; +exports[`Attempting to log banned user in moderation log channel Sends log to the correct channel 1`] = ` +{ + "embeds": [ + { + "author": { + "icon_url": "image.jpg", + "name": "Ban | bad.spammer", + }, + "color": 15747399, + "fields": [ + { + "inline": true, + "name": "User", + "value": "<@123>", + }, + { + "inline": true, + "name": "Moderator", + "value": "<@007>", + }, + { + "inline": true, + "name": "Reason", + "value": "Account is compromised and spamming phishing links.", + }, + ], + "footer": { + "text": "ID: 123", + }, + "timestamp": "2024-02-01T00:00:00.000Z", + }, + ], +} +`; + exports[`Banning spammer that has left the server Reacts with the correct emoji to automod message 1`] = `"❌"`; exports[`Banning spammer that has left the server Sends back correct interaction reply to calling moderator 1`] = ` diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 9b28ab95..6411a480 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -57,6 +57,12 @@ Note: It may take several days for our volunteer staff to take action on your ap } static async #announceBan(interaction, message) { + const channelID = config.channels.moderationLogChannelId; + const channel = await interaction.guild.channels.fetch(channelID); + if (channel == null) { + throw new Error(`No channel of the ID ${channelID} were found.`); + } + const embed = { timestamp: `${new Date().toISOString()}`, color: 15747399, @@ -86,13 +92,7 @@ Note: It may take several days for our volunteer staff to take action on your ap ], }; - const channelID = config.channels.moderationLogChannelId; - const channel = await interaction.guild.channels.fetch(channelID); - if (channel == null) { - console.error("No channel of that ID were found"); - } else { - channel.send({ embeds: [embed] }); - } + channel.send({ embeds: [embed] }); } static #isAdmin(member) { diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index 90221b9a..ec07bf11 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -96,7 +96,7 @@ function createGuildMock() { createChannelMock("2302382"), createChannelMock("000000"), ], - fetch: async (id) => id === channelId ? moderationLogChannel : undefined, + fetch: async (id) => id === channelId ? moderationLogChannel : null, } } } @@ -277,3 +277,35 @@ describe("Attempting to bann a bot or team member", () => { expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); }); + +describe("Attempting to log banned user in moderation log channel", () => { + let interactionMock; + beforeEach(() => { + const messageMock = createMessageMock(); + const guildMock = createGuildMock(); + interactionMock = createInteractionMock(messageMock, guildMock); + }); + + it("Sends log to the correct channel", async () => { + await SpamBanningService.handleInteraction(interactionMock); + interactionMock.guild.channels.cache.forEach((channel) => { + if (channel.id === config.channels.moderationLogChannelId) { + expect(channel.send).toHaveBeenCalledTimes(1); + expect(interactionMock.getChannelSendArg()).toMatchSnapshot(); + } else { + expect(channel.send).not.toHaveBeenCalledTimes(1); + } + }); + }); + + it("Error is handled if channel doesn't exist", async () => { + console.error = jest.fn(); + interactionMock.guild.channels.fetch = async () => null; + await SpamBanningService.handleInteraction(interactionMock); + interactionMock.guild.channels.cache.forEach((channel) => { + expect(channel.send).not.toHaveBeenCalledTimes(1); + }); + expect(console.error).toHaveBeenCalledTimes(1); + console.error.mockClear(); + }); +}); From 584817e7a83a2fc4729ae16e3700f1d1db30f047 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 5 Aug 2024 21:28:33 +0200 Subject: [PATCH 59/70] Remove mailto link in contact user message --- .../spam-ban/__snapshots__/spam-banning.service.test.js.snap | 2 +- services/spam-ban/spam-banning.service.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index bbf68e1d..ae1f1d9c 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -141,7 +141,7 @@ exports[`Banning spammer with DM enabled Discord message api is called with the { "description": "Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in [this Discord support article](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised) to secure your account. -Once your account is secure, you may appeal your ban by emailing [theodinprojectcontact@gmail.com](mailto:theodinprojectcontact@gmail.com) with your Discord username and that you are appealing your ban due to a compromised account. +Once your account is secure, you may appeal your ban by emailing \`theodinprojectcontact@gmail.com\` with your Discord username and that you are appealing your ban due to a compromised account. Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.", "title": "Banned: Compromised account / Spam", diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 6411a480..0be3686a 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -49,7 +49,7 @@ class SpamBanningService { .setDescription( `Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in [this Discord support article](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised) to secure your account. -Once your account is secure, you may appeal your ban by emailing [theodinprojectcontact@gmail.com](mailto:theodinprojectcontact@gmail.com) with your Discord username and that you are appealing your ban due to a compromised account. +Once your account is secure, you may appeal your ban by emailing \`theodinprojectcontact@gmail.com\` with your Discord username and that you are appealing your ban due to a compromised account. Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.`); From 5549d23efb8e19778af5aef622cdeedd3d263c12 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Tue, 6 Aug 2024 05:02:26 +0200 Subject: [PATCH 60/70] Send user message to enable embed links --- services/spam-ban/spam-banning.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 0be3686a..ea997761 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -53,7 +53,7 @@ Once your account is secure, you may appeal your ban by emailing \`theodinprojec Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.`); - await author.send({ embeds: [embedMessage] }); + await author.send({content: "Your account has been banned, Please enable the embed option if you cannot see the message bellow.", embeds: [embedMessage] }); } static async #announceBan(interaction, message) { From aaa43167fbad77becf9d6dd0810f89ccbe865734 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 8 Aug 2024 08:01:18 +0200 Subject: [PATCH 61/70] Update message to include new mod email --- services/spam-ban/spam-banning.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index ea997761..72034c74 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -49,7 +49,7 @@ class SpamBanningService { .setDescription( `Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in [this Discord support article](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised) to secure your account. -Once your account is secure, you may appeal your ban by emailing \`theodinprojectcontact@gmail.com\` with your Discord username and that you are appealing your ban due to a compromised account. +Once your account is secure, you may appeal your ban by emailing \`moderation@theodinproject.com\` with your Discord username and that you are appealing your ban due to a compromised account. Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.`); From 38349b1f96a290173abe193592fb3d0eac615917 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 8 Aug 2024 08:01:47 +0200 Subject: [PATCH 62/70] Update test snippets --- .../spam-ban/__snapshots__/spam-banning.service.test.js.snap | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index ae1f1d9c..ee3808e5 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -137,11 +137,12 @@ exports[`Banning spammer with DM enabled Discord ban api is called with the corr exports[`Banning spammer with DM enabled Discord message api is called with the correct message 1`] = ` { + "content": "Your account has been banned, Please enable the embed option if you cannot see the message bellow.", "embeds": [ { "description": "Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in [this Discord support article](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised) to secure your account. -Once your account is secure, you may appeal your ban by emailing \`theodinprojectcontact@gmail.com\` with your Discord username and that you are appealing your ban due to a compromised account. +Once your account is secure, you may appeal your ban by emailing \`moderation@theodinproject.com\` with your Discord username and that you are appealing your ban due to a compromised account. Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.", "title": "Banned: Compromised account / Spam", From f12cc803dd6d6dc8233f6d95f9413604eb2823a1 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 8 Aug 2024 08:15:01 +0200 Subject: [PATCH 63/70] Run prettier --- services/spam-ban/index.js | 2 +- services/spam-ban/spam-banning.service.js | 33 ++++--- .../spam-ban/spam-banning.service.test.js | 96 +++++++++---------- 3 files changed, 68 insertions(+), 63 deletions(-) diff --git a/services/spam-ban/index.js b/services/spam-ban/index.js index d028b450..66fdbf60 100644 --- a/services/spam-ban/index.js +++ b/services/spam-ban/index.js @@ -1,3 +1,3 @@ -const SpamBanningService = require("./spam-banning.service"); +const SpamBanningService = require('./spam-banning.service'); module.exports = SpamBanningService; diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 72034c74..f2d5739f 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -1,12 +1,12 @@ -const { EmbedBuilder } = require("discord.js"); -const config = require("../../config"); +const { EmbedBuilder } = require('discord.js'); +const config = require('../../config'); class SpamBanningService { static async handleInteraction(interaction) { - const message = interaction.options.getMessage("message"); + const message = interaction.options.getMessage('message'); if (message.author.bot || SpamBanningService.#isAdmin(message.member)) { interaction.reply({ - content: "You do not have the permission to ban this user", + content: 'You do not have the permission to ban this user', ephemeral: true, }); return; @@ -16,7 +16,7 @@ class SpamBanningService { let reply; if (!message.member) { - message.react("❌"); + message.react('❌'); reply = `Couldn't bann <@${message.author.id}>. User is not on the server.`; } else { reply = await SpamBanningService.#banUser(message); @@ -38,22 +38,27 @@ class SpamBanningService { reply = `Banned <@${message.author.id}> for spam but wasn't able to contact the user.`; } - message.member.ban({ reason: "Account is compromised" }); - message.react("✅"); + message.member.ban({ reason: 'Account is compromised' }); + message.react('✅'); return reply; } static async #sendMessageToUser(author) { const embedMessage = new EmbedBuilder() - .setTitle("Banned: Compromised account / Spam") + .setTitle('Banned: Compromised account / Spam') .setDescription( `Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in [this Discord support article](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised) to secure your account. Once your account is secure, you may appeal your ban by emailing \`moderation@theodinproject.com\` with your Discord username and that you are appealing your ban due to a compromised account. -Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.`); +Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.`, + ); - await author.send({content: "Your account has been banned, Please enable the embed option if you cannot see the message bellow.", embeds: [embedMessage] }); + await author.send({ + content: + 'Your account has been banned, Please enable the embed option if you cannot see the message bellow.', + embeds: [embedMessage], + }); } static async #announceBan(interaction, message) { @@ -76,17 +81,17 @@ Note: It may take several days for our volunteer staff to take action on your ap fields: [ { value: `<@${message.author.id}>`, - name: "User", + name: 'User', inline: true, }, { value: `<@${interaction.user.id}>`, - name: "Moderator", + name: 'Moderator', inline: true, }, { - value: "Account is compromised and spamming phishing links.", - name: "Reason", + value: 'Account is compromised and spamming phishing links.', + name: 'Reason', inline: true, }, ], diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index ec07bf11..b24e4e1f 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -1,5 +1,5 @@ -const SpamBanningService = require("./spam-banning.service"); -const config = require("../../config"); +const SpamBanningService = require('./spam-banning.service'); +const config = require('../../config'); beforeAll(() => { jest.useFakeTimers(); @@ -23,7 +23,7 @@ function createInteractionMock(message, guild) { // The mod who initialized the interaction user: { - id: "007", + id: '007', }, // Used by service to retrieve the message @@ -47,13 +47,13 @@ function createMessageMock() { return { author: { - id: "123", - username: "bad.spammer", + id: '123', + username: 'bad.spammer', bot: false, send: jest.fn((arg) => { sendArg = arg; }), - displayAvatarURL: () => "image.jpg", + displayAvatarURL: () => 'image.jpg', }, member: { roles: { @@ -87,21 +87,21 @@ function createGuildMock() { const channelId = config.channels.moderationLogChannelId; const moderationLogChannel = createChannelMock(channelId); return { - channels: { - cache: [ - createChannelMock("2342314"), - createChannelMock("101010"), - createChannelMock("22223333"), - moderationLogChannel, - createChannelMock("2302382"), - createChannelMock("000000"), - ], - fetch: async (id) => id === channelId ? moderationLogChannel : null, - } -} + channels: { + cache: [ + createChannelMock('2342314'), + createChannelMock('101010'), + createChannelMock('22223333'), + moderationLogChannel, + createChannelMock('2302382'), + createChannelMock('000000'), + ], + fetch: async (id) => (id === channelId ? moderationLogChannel : null), + }, + }; } -describe("Banning spammer with DM enabled", () => { +describe('Banning spammer with DM enabled', () => { let interactionMock; beforeEach(() => { const messageMock = createMessageMock(); @@ -109,25 +109,25 @@ describe("Banning spammer with DM enabled", () => { interactionMock = createInteractionMock(messageMock, guildMock); }); - it("Discord ban api is called with the correct reason", async () => { + it('Discord ban api is called with the correct reason', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).toHaveBeenCalledTimes(1); expect(interactionMock.getBanArg()).toMatchSnapshot(); }); - it("Discord message api is called with the correct message", async () => { + it('Discord message api is called with the correct message', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.author.send).toHaveBeenCalledTimes(1); expect(interactionMock.getAuthorSendArg()).toMatchSnapshot(); }); - it("Reacts with the correct emoji", async () => { + it('Reacts with the correct emoji', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.react).toHaveBeenCalledTimes(1); expect(interactionMock.getReactArg()).toMatchSnapshot(); }); - it("Sends log to the correct channel", async () => { + it('Sends log to the correct channel', async () => { await SpamBanningService.handleInteraction(interactionMock); interactionMock.guild.channels.cache.forEach((channel) => { if (channel.id === config.channels.moderationLogChannelId) { @@ -139,13 +139,13 @@ describe("Banning spammer with DM enabled", () => { }); }); - it("Sends back correct interaction reply to calling moderator", async () => { + it('Sends back correct interaction reply to calling moderator', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); }); -describe("Banning spammer who has DM set to private", () => { +describe('Banning spammer who has DM set to private', () => { let interactionMock; beforeEach(() => { const messageMock = createMessageMock(); @@ -156,24 +156,24 @@ describe("Banning spammer who has DM set to private", () => { interactionMock = createInteractionMock(messageMock, guildMock); }); - it("Discord ban api is called with the correct reason", async () => { + it('Discord ban api is called with the correct reason', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).toHaveBeenCalledTimes(1); expect(interactionMock.getBanArg()).toMatchSnapshot(); }); - it("Discord message api is called and error handled", async () => { + it('Discord message api is called and error handled', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.author.send).toHaveBeenCalledTimes(1); }); - it("Reacts with the correct emoji", async () => { + it('Reacts with the correct emoji', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.react).toHaveBeenCalledTimes(1); expect(interactionMock.getReactArg()).toMatchSnapshot(); }); - it("Sends log to the correct channel", async () => { + it('Sends log to the correct channel', async () => { await SpamBanningService.handleInteraction(interactionMock); interactionMock.guild.channels.cache.forEach((channel) => { if (channel.id === config.channels.moderationLogChannelId) { @@ -185,13 +185,13 @@ describe("Banning spammer who has DM set to private", () => { }); }); - it("Sends back correct interaction reply to calling moderator", async () => { + it('Sends back correct interaction reply to calling moderator', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); }); -describe("Banning spammer that has left the server", () => { +describe('Banning spammer that has left the server', () => { let interactionMock; beforeEach(() => { const messageMock = createMessageMock(); @@ -200,31 +200,31 @@ describe("Banning spammer that has left the server", () => { interactionMock = createInteractionMock(messageMock, guildMock); }); - it("Author message sending api is not called", async () => { + it('Author message sending api is not called', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); }); - it("Reacts with the correct emoji to automod message", async () => { + it('Reacts with the correct emoji to automod message', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.react).toHaveBeenCalledTimes(1); expect(interactionMock.getReactArg()).toMatchSnapshot(); }); - it("Does not log any channel", async () => { + it('Does not log any channel', async () => { await SpamBanningService.handleInteraction(interactionMock); interactionMock.guild.channels.cache.forEach((channel) => { expect(channel.send).not.toHaveBeenCalled(); }); }); - it("Sends back correct interaction reply to calling moderator", async () => { + it('Sends back correct interaction reply to calling moderator', async () => { await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); }); -describe("Attempting to bann a bot or team member", () => { +describe('Attempting to bann a bot or team member', () => { let interactionMock; beforeEach(() => { const messageMock = createMessageMock(); @@ -232,7 +232,7 @@ describe("Attempting to bann a bot or team member", () => { interactionMock = createInteractionMock(messageMock, guildMock); }); - it("Does not ban bots", async () => { + it('Does not ban bots', async () => { interactionMock.message.author.bot = true; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); @@ -241,8 +241,8 @@ describe("Attempting to bann a bot or team member", () => { expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); - it("Does not ban moderators", async () => { - interactionMock.message.member.roles.cache = [{ name: "moderator" }]; + it('Does not ban moderators', async () => { + interactionMock.message.member.roles.cache = [{ name: 'moderator' }]; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); @@ -250,8 +250,8 @@ describe("Attempting to bann a bot or team member", () => { expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); - it("Does not ban maintainers", async () => { - interactionMock.message.member.roles.cache = [{ name: "maintainer" }]; + it('Does not ban maintainers', async () => { + interactionMock.message.member.roles.cache = [{ name: 'maintainer' }]; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); @@ -259,8 +259,8 @@ describe("Attempting to bann a bot or team member", () => { expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); - it("Does not ban core", async () => { - interactionMock.message.member.roles.cache = [{ name: "core" }]; + it('Does not ban core', async () => { + interactionMock.message.member.roles.cache = [{ name: 'core' }]; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); @@ -268,8 +268,8 @@ describe("Attempting to bann a bot or team member", () => { expect(interactionMock.getReplyArg()).toMatchSnapshot(); }); - it("Does not ban admins", async () => { - interactionMock.message.member.roles.cache = [{ name: "admin" }]; + it('Does not ban admins', async () => { + interactionMock.message.member.roles.cache = [{ name: 'admin' }]; await SpamBanningService.handleInteraction(interactionMock); expect(interactionMock.message.member.ban).not.toHaveBeenCalled(); expect(interactionMock.message.author.send).not.toHaveBeenCalled(); @@ -278,7 +278,7 @@ describe("Attempting to bann a bot or team member", () => { }); }); -describe("Attempting to log banned user in moderation log channel", () => { +describe('Attempting to log banned user in moderation log channel', () => { let interactionMock; beforeEach(() => { const messageMock = createMessageMock(); @@ -286,7 +286,7 @@ describe("Attempting to log banned user in moderation log channel", () => { interactionMock = createInteractionMock(messageMock, guildMock); }); - it("Sends log to the correct channel", async () => { + it('Sends log to the correct channel', async () => { await SpamBanningService.handleInteraction(interactionMock); interactionMock.guild.channels.cache.forEach((channel) => { if (channel.id === config.channels.moderationLogChannelId) { @@ -303,7 +303,7 @@ describe("Attempting to log banned user in moderation log channel", () => { interactionMock.guild.channels.fetch = async () => null; await SpamBanningService.handleInteraction(interactionMock); interactionMock.guild.channels.cache.forEach((channel) => { - expect(channel.send).not.toHaveBeenCalledTimes(1); + expect(channel.send).not.toHaveBeenCalledTimes(1); }); expect(console.error).toHaveBeenCalledTimes(1); console.error.mockClear(); From 62b5a60d24932e2daade31ab128b4249b85e39b8 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 8 Aug 2024 08:25:48 +0200 Subject: [PATCH 64/70] Use new isAdmin util function --- services/spam-ban/spam-banning.service.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index f2d5739f..0540236d 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -1,10 +1,11 @@ const { EmbedBuilder } = require('discord.js'); +const { isAdmin } = require('../../utils/is-admin'); const config = require('../../config'); class SpamBanningService { static async handleInteraction(interaction) { const message = interaction.options.getMessage('message'); - if (message.author.bot || SpamBanningService.#isAdmin(message.member)) { + if (message.author.bot || isAdmin(message.member)) { interaction.reply({ content: 'You do not have the permission to ban this user', ephemeral: true, @@ -99,16 +100,6 @@ Note: It may take several days for our volunteer staff to take action on your ap channel.send({ embeds: [embed] }); } - - static #isAdmin(member) { - if (!member) { - return false; - } - - return member.roles.cache.some((role) => - config.roles.adminRolesName.includes(role.name), - ); - } } module.exports = SpamBanningService; From bda809c8bb4597822cd70c04bbc0e5fbdccedc6d Mon Sep 17 00:00:00 2001 From: Emad Ali <70924991+Mclilzee@users.noreply.github.com> Date: Thu, 8 Aug 2024 14:49:36 +0200 Subject: [PATCH 65/70] Apply suggestions from code review Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- new-era-commands/context-menu/bann-spammer.js | 2 +- services/spam-ban/spam-banning.service.js | 8 ++++---- services/spam-ban/spam-banning.service.test.js | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/new-era-commands/context-menu/bann-spammer.js b/new-era-commands/context-menu/bann-spammer.js index 3227d67f..b7065cf6 100644 --- a/new-era-commands/context-menu/bann-spammer.js +++ b/new-era-commands/context-menu/bann-spammer.js @@ -3,7 +3,7 @@ const SpamBanningService = require("../../services/spam-ban/spam-banning.service module.exports = { data: new ContextMenuCommandBuilder() - .setName("Bann Spammer") + .setName("Ban Spammer") .setType(ApplicationCommandType.Message) .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers), execute: async (interaction) => { diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 0540236d..975caa47 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -18,7 +18,7 @@ class SpamBanningService { if (!message.member) { message.react('❌'); - reply = `Couldn't bann <@${message.author.id}>. User is not on the server.`; + reply = `Couldn't ban <@${message.author.id}>. User is not on the server.`; } else { reply = await SpamBanningService.#banUser(message); await SpamBanningService.#announceBan(interaction, message); @@ -48,7 +48,7 @@ class SpamBanningService { const embedMessage = new EmbedBuilder() .setTitle('Banned: Compromised account / Spam') .setDescription( - `Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in [this Discord support article](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised) to secure your account. + `Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in this [Discord support article about securing your account](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised). Once your account is secure, you may appeal your ban by emailing \`moderation@theodinproject.com\` with your Discord username and that you are appealing your ban due to a compromised account. @@ -57,7 +57,7 @@ Note: It may take several days for our volunteer staff to take action on your ap await author.send({ content: - 'Your account has been banned, Please enable the embed option if you cannot see the message bellow.', + 'Your account has been banned. Please enable embeds in Discord settings if you cannot see the message below.', embeds: [embedMessage], }); } @@ -66,7 +66,7 @@ Note: It may take several days for our volunteer staff to take action on your ap const channelID = config.channels.moderationLogChannelId; const channel = await interaction.guild.channels.fetch(channelID); if (channel == null) { - throw new Error(`No channel of the ID ${channelID} were found.`); + throw new Error(`No channel with the ID ${channelID} was found.`); } const embed = { diff --git a/services/spam-ban/spam-banning.service.test.js b/services/spam-ban/spam-banning.service.test.js index b24e4e1f..81f6cc23 100644 --- a/services/spam-ban/spam-banning.service.test.js +++ b/services/spam-ban/spam-banning.service.test.js @@ -224,7 +224,7 @@ describe('Banning spammer that has left the server', () => { }); }); -describe('Attempting to bann a bot or team member', () => { +describe('Attempting to ban a bot or team member', () => { let interactionMock; beforeEach(() => { const messageMock = createMessageMock(); From df4c76066d1d6e898fb643941342c838063a87a5 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Sat, 10 Aug 2024 15:24:15 +0200 Subject: [PATCH 66/70] Update ban message with appeal template --- services/spam-ban/spam-banning.service.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 975caa47..9ea3393e 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -50,9 +50,15 @@ class SpamBanningService { .setDescription( `Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in this [Discord support article about securing your account](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised). -Once your account is secure, you may appeal your ban by emailing \`moderation@theodinproject.com\` with your Discord username and that you are appealing your ban due to a compromised account. +Once your account is secure, you may appeal your ban by emailing \`moderation@theodinproject.com\` with the following template: -Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.`, +- Banned username: +- Reason for ban: +- Date of ban: +- Steps taken to secure my account: +- Additional comments (optional): + +Please note that it may take at least several days for our volunteer staff to process your request.`, ); await author.send({ From 2bd8cff6a9bf72f85d47212a4558b4dde834b09c Mon Sep 17 00:00:00 2001 From: Emad Ali <70924991+Mclilzee@users.noreply.github.com> Date: Sat, 10 Aug 2024 15:32:58 +0200 Subject: [PATCH 67/70] Refactor sentence structure Co-authored-by: Asartea <76259120+Asartea@users.noreply.github.com> --- services/spam-ban/spam-banning.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/spam-ban/spam-banning.service.js b/services/spam-ban/spam-banning.service.js index 9ea3393e..3de72927 100644 --- a/services/spam-ban/spam-banning.service.js +++ b/services/spam-ban/spam-banning.service.js @@ -31,7 +31,7 @@ class SpamBanningService { } static async #banUser(message) { - let reply = `Banned <@${message.author.id}> for spam successfully.`; + let reply = `Successfully banned <@${message.author.id}> for spam.`; try { // Make sure to send the message before banning otherwise user will not be found await SpamBanningService.#sendMessageToUser(message.author); From c61ac3dac8a25a43c8ed5881b99c84485d282b3e Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Sat, 10 Aug 2024 15:40:45 +0200 Subject: [PATCH 68/70] Update test snippets to reflect newest changes --- .../spam-banning.service.test.js.snap | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap index ee3808e5..9f616d12 100644 --- a/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap +++ b/services/spam-ban/__snapshots__/spam-banning.service.test.js.snap @@ -1,34 +1,34 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Attempting to bann a bot or team member Does not ban admins 1`] = ` +exports[`Attempting to ban a bot or team member Does not ban admins 1`] = ` { "content": "You do not have the permission to ban this user", "ephemeral": true, } `; -exports[`Attempting to bann a bot or team member Does not ban bots 1`] = ` +exports[`Attempting to ban a bot or team member Does not ban bots 1`] = ` { "content": "You do not have the permission to ban this user", "ephemeral": true, } `; -exports[`Attempting to bann a bot or team member Does not ban core 1`] = ` +exports[`Attempting to ban a bot or team member Does not ban core 1`] = ` { "content": "You do not have the permission to ban this user", "ephemeral": true, } `; -exports[`Attempting to bann a bot or team member Does not ban maintainers 1`] = ` +exports[`Attempting to ban a bot or team member Does not ban maintainers 1`] = ` { "content": "You do not have the permission to ban this user", "ephemeral": true, } `; -exports[`Attempting to bann a bot or team member Does not ban moderators 1`] = ` +exports[`Attempting to ban a bot or team member Does not ban moderators 1`] = ` { "content": "You do not have the permission to ban this user", "ephemeral": true, @@ -74,7 +74,7 @@ exports[`Banning spammer that has left the server Reacts with the correct emoji exports[`Banning spammer that has left the server Sends back correct interaction reply to calling moderator 1`] = ` { - "content": "Couldn't bann <@123>. User is not on the server.", + "content": "Couldn't ban <@123>. User is not on the server.", "ephemeral": true, } `; @@ -137,14 +137,20 @@ exports[`Banning spammer with DM enabled Discord ban api is called with the corr exports[`Banning spammer with DM enabled Discord message api is called with the correct message 1`] = ` { - "content": "Your account has been banned, Please enable the embed option if you cannot see the message bellow.", + "content": "Your account has been banned. Please enable embeds in Discord settings if you cannot see the message below.", "embeds": [ { - "description": "Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in [this Discord support article](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised) to secure your account. + "description": "Your account has been banned from The Odin Project Discord server for sending spam. If this account is compromised, please follow the steps linked in this [Discord support article about securing your account](https://support.discord.com/hc/en-us/articles/24160905919511-My-Discord-Account-was-Hacked-or-Compromised). -Once your account is secure, you may appeal your ban by emailing \`moderation@theodinproject.com\` with your Discord username and that you are appealing your ban due to a compromised account. +Once your account is secure, you may appeal your ban by emailing \`moderation@theodinproject.com\` with the following template: -Note: It may take several days for our volunteer staff to take action on your appeal, and unbanning is not guaranteed.", +- Banned username: +- Reason for ban: +- Date of ban: +- Steps taken to secure my account: +- Additional comments (optional): + +Please note that it may take at least several days for our volunteer staff to process your request.", "title": "Banned: Compromised account / Spam", }, ], @@ -155,7 +161,7 @@ exports[`Banning spammer with DM enabled Reacts with the correct emoji 1`] = `" exports[`Banning spammer with DM enabled Sends back correct interaction reply to calling moderator 1`] = ` { - "content": "Banned <@123> for spam successfully.", + "content": "Successfully banned <@123> for spam.", "ephemeral": true, } `; From c7f63ec442343e225d3a5b6cfaa7f058cd870295 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Mon, 12 Aug 2024 08:25:01 +0200 Subject: [PATCH 69/70] Update filename --- new-era-commands/context-menu/{bann-spammer.js => ban-spammer.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename new-era-commands/context-menu/{bann-spammer.js => ban-spammer.js} (100%) diff --git a/new-era-commands/context-menu/bann-spammer.js b/new-era-commands/context-menu/ban-spammer.js similarity index 100% rename from new-era-commands/context-menu/bann-spammer.js rename to new-era-commands/context-menu/ban-spammer.js From c6e0692e2f4e4559516933dfc97952b7a1763e59 Mon Sep 17 00:00:00 2001 From: mclilzee <70924991+Mclilzee@users.noreply.github.com> Date: Sun, 1 Dec 2024 03:48:44 +0100 Subject: [PATCH 70/70] Format for linting --- new-era-commands/context-menu/ban-spammer.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/new-era-commands/context-menu/ban-spammer.js b/new-era-commands/context-menu/ban-spammer.js index b7065cf6..c8137dbd 100644 --- a/new-era-commands/context-menu/ban-spammer.js +++ b/new-era-commands/context-menu/ban-spammer.js @@ -1,9 +1,13 @@ -const { ContextMenuCommandBuilder, ApplicationCommandType, PermissionFlagsBits, } = require("discord.js"); -const SpamBanningService = require("../../services/spam-ban/spam-banning.service"); +const { + ContextMenuCommandBuilder, + ApplicationCommandType, + PermissionFlagsBits, +} = require('discord.js'); +const SpamBanningService = require('../../services/spam-ban/spam-banning.service'); module.exports = { data: new ContextMenuCommandBuilder() - .setName("Ban Spammer") + .setName('Ban Spammer') .setType(ApplicationCommandType.Message) .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers), execute: async (interaction) => {