-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit f955cea
Showing
38 changed files
with
1,786 additions
and
0 deletions.
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,5 @@ | ||
node_modules/ | ||
package-lock.json | ||
old/ | ||
databases/* | ||
config.json |
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,61 @@ | ||
# BluBot | ||
|
||
A self-hosted Discord bot with various moderation features and fun commands. Features a simple CLI and setup script for easy management. | ||
|
||
## Features | ||
|
||
- Automatic moderation | ||
- Censor list (deprecated by Discord AutoMod?) | ||
- Phish protection (powered by phish.sinking.yachts) | ||
- Moderation | ||
- Ban, kick, timeout members | ||
- Purge messages by channel and/or user | ||
- Lock channels | ||
- Logging | ||
- Any moderation action | ||
- Deleted and edited messages | ||
- Automatic moderation actions | ||
- Misc | ||
- Get user avatar | ||
- Define a word using Urban Dictionary | ||
- Neofetch-like status command | ||
- Ping command | ||
- Your Mom jokes (powered by yomomma.info) | ||
- Setup | ||
- Guided setup with customization options | ||
- CLI | ||
- Simple CLI with ASCII art and uptime command (more coming soon) | ||
|
||
## Setup | ||
|
||
0. Install NodeJS | ||
1. Clone this repository | ||
2. Run `npm run setup` and follow the steps | ||
3. Run `npm install` to install dependencies | ||
4. Run `npm start` to start the bot | ||
|
||
## Screenshots | ||
|
||
### Direct Messages | ||
|
||
![](assets/dms.png) | ||
|
||
### Logs | ||
|
||
![](assets/logs.png) | ||
|
||
### Neofetch command (Discord ANSI support) | ||
|
||
![](assets/neofetch.png) | ||
|
||
### CLI | ||
|
||
![](assets/cli.png) | ||
|
||
## Support | ||
|
||
Want to request a new feature or report a bug? | ||
|
||
[Join my Discord Server](https://blnk.ga/dc) | ||
or | ||
[send me an email](mailto:[email protected])! |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,31 @@ | ||
const { SlashCommandBuilder } = require('@discordjs/builders') | ||
const { | ||
customization: { accent } | ||
} = require('../config.json') | ||
|
||
module.exports = { | ||
data: new SlashCommandBuilder() | ||
.setName('avatar') | ||
.setDescription("Get your or another user's avatar") | ||
.addUserOption(option => | ||
option.setName('target').setDescription('User to show avatar for') | ||
), | ||
async execute(interaction) { | ||
const user = interaction.options.getUser('target') || interaction.user | ||
const avatar = format => user.avatarURL({ format }) | ||
interaction.reply({ | ||
embeds: [ | ||
{ | ||
title: `${user.username}'s avatar`, | ||
description: `Download as [png](${avatar('png')}), [jpeg](${avatar( | ||
'jpeg' | ||
)}) or [webp](${avatar('webp')}).`, | ||
color: accent, | ||
image: { | ||
url: avatar('png') | ||
} | ||
} | ||
] | ||
}) | ||
} | ||
} |
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,76 @@ | ||
const { SlashCommandBuilder } = require('@discordjs/builders') | ||
const { | ||
customization: { accent } | ||
} = require('../config.json') | ||
const checkUserPerms = require('../utils/checkUserPerms') | ||
const directMessage = require('../utils/directMessage') | ||
const log = require('../utils/log') | ||
|
||
module.exports = { | ||
data: new SlashCommandBuilder() | ||
.setName('ban') | ||
.setDescription('Ban a member.') | ||
.addUserOption(option => | ||
option.setName('target').setDescription('User to ban').setRequired(true) | ||
) | ||
.addStringOption(option => | ||
option.setName('reason').setDescription('Reason for the ban') | ||
) | ||
.addNumberOption(option => | ||
option.setName('deletedays').setDescription('Days to delete messages') | ||
), | ||
async execute(interaction) { | ||
if (!checkUserPerms(interaction)) | ||
return interaction.reply({ | ||
content: 'You do not have permission to do that!', | ||
ephemeral: true | ||
}) | ||
const target = interaction.options.getUser('target') | ||
const reason = interaction.options.getString('reason') || 'N/A' | ||
const days = interaction.options.getNumber('deletedays') || 0 | ||
const member = await interaction.guild.members | ||
.fetch({ user: target, force: true }) | ||
.catch(() => null) | ||
if (!member) | ||
return interaction.reply({ | ||
content: "I can't find that user!", | ||
ephemeral: true | ||
}) | ||
if (!member.bannable) | ||
return interaction.reply({ | ||
content: "I can't ban that user!", | ||
ephemeral: true | ||
}) | ||
await interaction.reply({ | ||
embeds: [ | ||
{ | ||
title: `${target.tag} banned.`, | ||
color: accent | ||
} | ||
], | ||
ephemeral: true | ||
}) | ||
const dm = await directMessage(interaction.guild, target, 'ban', { | ||
reason, | ||
moderator: { | ||
id: interaction.user.id | ||
} | ||
}) | ||
if (!dm) | ||
await interaction.followUp({ | ||
content: 'I could not message that user!', | ||
ephemeral: true | ||
}) | ||
await member.ban(target, { days: days, reason: reason }) | ||
log(interaction.guild, 'ban', { | ||
target: { | ||
id: target.id, | ||
tag: target.tag | ||
}, | ||
moderator: { | ||
id: interaction.user.id | ||
}, | ||
reason | ||
}) | ||
} | ||
} |
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,93 @@ | ||
const { SlashCommandBuilder } = require('@discordjs/builders') | ||
const { | ||
customization: { accent } | ||
} = require('../config.json') | ||
const fs = require('fs') | ||
const checkUserPerms = require('../utils/checkUserPerms') | ||
|
||
module.exports = { | ||
data: new SlashCommandBuilder() | ||
.setName('censor') | ||
.setDescription('Configure censored words') | ||
.addSubcommand(subcommand => | ||
subcommand | ||
.setName('add') | ||
.setDescription('Add a censored word') | ||
.addStringOption(option => | ||
option | ||
.setName('word') | ||
.setDescription('The word to censor') | ||
.setRequired(true) | ||
) | ||
) | ||
.addSubcommand(subcommand => | ||
subcommand | ||
.setName('remove') | ||
.setDescription('Remove a censored word') | ||
.addStringOption(option => | ||
option | ||
.setName('word') | ||
.setDescription('The word to remove') | ||
.setRequired(true) | ||
) | ||
) | ||
.addSubcommand(subcommand => | ||
subcommand.setName('list').setDescription('List all censored words') | ||
), | ||
async execute(interaction) { | ||
const word = interaction.options.getString('word')?.toLowerCase() | ||
if (!checkUserPerms(interaction)) | ||
return interaction.reply({ | ||
content: 'You do not have permission to do that!', | ||
ephemeral: true | ||
}) | ||
|
||
if (interaction.options.getSubcommand() === 'add') { | ||
const censored = JSON.parse(fs.readFileSync('./databases/censored.json')) | ||
if (censored.map(c => c.word).includes(word)) | ||
return await interaction.reply({ | ||
content: 'This word is already censored!', | ||
ephemeral: true | ||
}) | ||
censored.push({ | ||
user: interaction.user.id, | ||
word | ||
}) | ||
fs.writeFileSync('./databases/censored.json', JSON.stringify(censored)) | ||
await interaction.reply({ | ||
content: `Censored the word ${word}!`, | ||
ephemeral: true | ||
}) | ||
} else if (interaction.options.getSubcommand() === 'remove') { | ||
const censored = JSON.parse(fs.readFileSync('./databases/censored.json')) | ||
const found = censored.find(c => c.word === word) | ||
if (!found) | ||
return await interaction.reply({ | ||
content: 'This word is not censored!', | ||
ephemeral: true | ||
}) | ||
const index = censored.indexOf(found) | ||
censored.splice(index, 1) | ||
fs.writeFileSync('./databases/censored.json', JSON.stringify(censored)) | ||
await interaction.reply({ | ||
content: `Removed censor for the word ${word}!`, | ||
ephemeral: true | ||
}) | ||
} else if (interaction.options.getSubcommand() === 'list') { | ||
const censored = JSON.parse(fs.readFileSync('./databases/censored.json')) | ||
await interaction.reply({ | ||
embeds: [ | ||
{ | ||
title: 'Censored words', | ||
color: accent, | ||
fields: censored.map(c => ({ | ||
name: c.word, | ||
value: `Added by <@${c.user}>` | ||
})) | ||
} | ||
], | ||
ephemeral: true | ||
}) | ||
} else return interaction.reply('Invalid option.') | ||
} | ||
} |
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,30 @@ | ||
const { SlashCommandBuilder } = require('@discordjs/builders') | ||
const { | ||
customization: { accent } | ||
} = require('../config.json') | ||
const checkUserPerms = require('../utils/checkUserPerms') | ||
|
||
module.exports = { | ||
data: new SlashCommandBuilder() | ||
.setName('check') | ||
.setDescription('Check if are allowed to moderate using this bot.'), | ||
async execute(interaction) { | ||
if (checkUserPerms(interaction)) | ||
return interaction.reply({ | ||
embeds: [ | ||
{ | ||
title: `You are allowed to moderate using this bot!`, | ||
color: accent | ||
} | ||
] | ||
}) | ||
return interaction.reply({ | ||
embeds: [ | ||
{ | ||
title: `You are not allowed to moderate using this bot.`, | ||
color: accent | ||
} | ||
] | ||
}) | ||
} | ||
} |
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,38 @@ | ||
const { SlashCommandBuilder } = require('@discordjs/builders') | ||
const { | ||
customization: { accent } | ||
} = require('../config.json') | ||
const axios = require('axios').default | ||
|
||
module.exports = { | ||
data: new SlashCommandBuilder() | ||
.setName('define') | ||
.setDescription('Define a word with Urban Dictionary!') | ||
.addStringOption(option => | ||
option | ||
.setName('query') | ||
.setDescription('Word to search for') | ||
.setRequired(true) | ||
), | ||
async execute(interaction) { | ||
// my api ;) | ||
const api = 'https://urbanapi.up.railway.app' | ||
const query = interaction.options.getString('query') | ||
interaction.deferReply() | ||
const res = await axios | ||
.get(`${api}/define/${query}`, { | ||
validateStatus: false | ||
}) | ||
.catch(() => null) | ||
if (!res?.data?.success) | ||
return interaction.editReply('An error has occured!') | ||
if (res.status === 404) | ||
return interaction.editReply('Could not find that word!') | ||
const embed = { | ||
color: accent, | ||
title: res.data.result[0].word, | ||
description: res.data.result[0].description | ||
} | ||
return interaction.editReply({ embeds: [embed] }) | ||
} | ||
} |
Oops, something went wrong.