-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Context menu button, Ban Spammer #548
Open
Mclilzee
wants to merge
70
commits into
TheOdinProject:main
Choose a base branch
from
Mclilzee:automated-spam-bann
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
70 commits
Select commit
Hold shift + click to select a range
8ec607b
Create context button
Mclilzee bc93656
Fix calling wrong service
Mclilzee df980ad
Refactor naming
Mclilzee e8664f0
Update logic to spammer-banning service
Mclilzee 765abce
Reformat message to contain new line
Mclilzee 3615580
Fix contact email
Mclilzee e693636
Reverse to send message directly
Mclilzee 9b351cf
Fix message sending issue
Mclilzee 2928b70
Update structure of calls
Mclilzee 818c395
Add announcing user banning and failure
Mclilzee 0384dcf
Refactor
Mclilzee 9c9a895
Update sending error to stderr channel
Mclilzee 21dafe4
Refactor modules
Mclilzee c1508f3
Add tests
Mclilzee 75cb035
Update tests and use snapshot
Mclilzee 310f677
Finalize first full test
Mclilzee 680184f
Add second test for users that isn't able to recieve messages
Mclilzee 1f748a9
Add test for user that is not on the server anymore
Mclilzee 133c0e8
Add function to announce the ban
Mclilzee 282e02f
Refactor naming
Mclilzee 94ddcb9
Update tests
Mclilzee 349be4a
Refactor seperate tests
Mclilzee cad7b18
Refactor testing to seperate ideas
Mclilzee 9afb67f
Add reaction testing
Mclilzee 2c82062
Update snapshot
Mclilzee a0dcf98
Add testing channel sending
Mclilzee 233b998
Refactor fix issue with snapshots
Mclilzee beda9d5
Add tests to users who has left the server
Mclilzee caf9b75
Update logic
Mclilzee 4b7a513
Update testing to test number of calls
Mclilzee e1df63b
Refactor to use creation mocks
Mclilzee d9474c0
Fix tests mocks
Mclilzee 91c444a
Fix second test suite
Mclilzee 1652dcf
Finish up third test suite
Mclilzee 26b5e4e
Refactor to test specifically for channel id arguments
Mclilzee 57d9902
Add tests against banning a bot
Mclilzee 8771039
Add tests for banning a bot
Mclilzee f6f1b49
Refactor test repitition
Mclilzee cfca7b4
Add logic to prevent banning an admin
Mclilzee 0f24ae0
Refactor and add other team members tests
Mclilzee c080030
Fix bug of retrieving user role name without using the name field
Mclilzee e0e2ee1
Update logging message
Mclilzee 90c52c8
Refactor interaction reply to be emphernal
Mclilzee 55d3b40
Fix mock time to not fail tests that require timestamp snapshot
Mclilzee 11a660b
Fix comment typo
Mclilzee 84e08dd
Update permission to mods with ability to ban only
Mclilzee 7b06e7e
Fix tests for core members
Mclilzee a783143
Update to use user ID
Mclilzee 6b37c9b
Update tests
Mclilzee 4c3d730
Update channel id name
Mclilzee def4298
Refactor channel name id in tests
Mclilzee 844d413
Update user message
Mclilzee 7f47a61
Update channel id name
Mclilzee 0621b11
Update tests
Mclilzee 47e7f75
Update date object to work with github cli test tools
Mclilzee d13b274
Update to use fetch method on getting the channel
Mclilzee 5db3444
Update to handle fetch promise
Mclilzee dfc53bc
Add handling error when channel is not found
Mclilzee 584817e
Remove mailto link in contact user message
Mclilzee 5549d23
Send user message to enable embed links
Mclilzee aaa4316
Update message to include new mod email
Mclilzee 38349b1
Update test snippets
Mclilzee f12cc80
Run prettier
Mclilzee 62b5a60
Use new isAdmin util function
Mclilzee bda809c
Apply suggestions from code review
Mclilzee df4c760
Update ban message with appeal template
Mclilzee 2bd8cff
Refactor sentence structure
Mclilzee c61ac3d
Update test snippets to reflect newest changes
Mclilzee c7f63ec
Update filename
Mclilzee c6e0692
Format for linting
Mclilzee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
const { | ||
ContextMenuCommandBuilder, | ||
ApplicationCommandType, | ||
PermissionFlagsBits, | ||
} = require('discord.js'); | ||
const SpamBanningService = require('../../services/spam-ban/spam-banning.service'); | ||
|
||
module.exports = { | ||
data: new ContextMenuCommandBuilder() | ||
.setName('Ban Spammer') | ||
.setType(ApplicationCommandType.Message) | ||
.setDefaultMemberPermissions(PermissionFlagsBits.BanMembers), | ||
execute: async (interaction) => { | ||
await SpamBanningService.handleInteraction(interaction); | ||
}, | ||
}; |
202 changes: 202 additions & 0 deletions
202
services/spam-ban/__snapshots__/spam-banning.service.test.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
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 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 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 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 ban a bot or team member Does not ban moderators 1`] = ` | ||
{ | ||
"content": "You do not have the permission to ban this user", | ||
"ephemeral": true, | ||
} | ||
`; | ||
|
||
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`] = ` | ||
{ | ||
"content": "Couldn't ban <@123>. User is not on the server.", | ||
"ephemeral": true, | ||
} | ||
`; | ||
|
||
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.", | ||
"ephemeral": true, | ||
} | ||
`; | ||
|
||
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: 123", | ||
}, | ||
"timestamp": "2024-02-01T00:00:00.000Z", | ||
}, | ||
], | ||
} | ||
`; | ||
|
||
exports[`Banning spammer with DM enabled Discord ban api is called with the correct reason 1`] = ` | ||
{ | ||
"reason": "Account is compromised", | ||
} | ||
`; | ||
|
||
exports[`Banning spammer with DM enabled Discord message api is called with the correct message 1`] = ` | ||
{ | ||
"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 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 \`[email protected]\` with the following template: | ||
|
||
- 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", | ||
}, | ||
], | ||
} | ||
`; | ||
|
||
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": "Successfully banned <@123> for spam.", | ||
"ephemeral": true, | ||
} | ||
`; | ||
|
||
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: 123", | ||
}, | ||
"timestamp": "2024-02-01T00:00:00.000Z", | ||
}, | ||
], | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const SpamBanningService = require('./spam-banning.service'); | ||
|
||
module.exports = SpamBanningService; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
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 || isAdmin(message.member)) { | ||
interaction.reply({ | ||
content: 'You do not have the permission to ban this user', | ||
ephemeral: true, | ||
}); | ||
return; | ||
} | ||
|
||
try { | ||
let reply; | ||
|
||
if (!message.member) { | ||
message.react('❌'); | ||
reply = `Couldn't ban <@${message.author.id}>. User is not on the server.`; | ||
} else { | ||
reply = await SpamBanningService.#banUser(message); | ||
await SpamBanningService.#announceBan(interaction, message); | ||
} | ||
|
||
interaction.reply({ content: reply, ephemeral: true }); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
} | ||
|
||
static async #banUser(message) { | ||
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); | ||
} 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 reply; | ||
} | ||
|
||
static async #sendMessageToUser(author) { | ||
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 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 \`[email protected]\` with the following template: | ||
|
||
- 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({ | ||
content: | ||
'Your account has been banned. Please enable embeds in Discord settings if you cannot see the message below.', | ||
embeds: [embedMessage], | ||
}); | ||
} | ||
|
||
static async #announceBan(interaction, message) { | ||
const channelID = config.channels.moderationLogChannelId; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add this channel id in the config file? |
||
const channel = await interaction.guild.channels.fetch(channelID); | ||
if (channel == null) { | ||
throw new Error(`No channel with the ID ${channelID} was found.`); | ||
} | ||
|
||
const embed = { | ||
timestamp: `${new Date().toISOString()}`, | ||
color: 15747399, | ||
footer: { | ||
text: `ID: ${message.author.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, | ||
}, | ||
], | ||
}; | ||
|
||
channel.send({ embeds: [embed] }); | ||
} | ||
} | ||
|
||
module.exports = SpamBanningService; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming we'll be calling this command only inside the automod channel. We'll add this condition in our discord server's setting. Though a sanity check here won't hurt. Can we add a guard here to check if this command is only called in that channel?