Skip to content

Commit

Permalink
feat: global ban command (beta) (#79)
Browse files Browse the repository at this point in the history
* feat: global ban command (ban users from using the bot itself)

* remove blacklist.ts

* fix typo

* style(ban): attach reason to the ban msg

* feat: functional ban command (preview)
  • Loading branch information
dev-737 authored Jun 9, 2024
1 parent 8b6689d commit 6be9db8
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 18 deletions.
6 changes: 5 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ type hubLogReports {
roleId String?
}

type userBan {
reason String
}

type hubBlacklist {
reason String
expires DateTime?
Expand Down Expand Up @@ -162,7 +166,7 @@ model userData {
username String?
locale String?
lastVoted DateTime?
banned Boolean? @default(false)
banMeta userBan?
blacklistedFrom hubBlacklist[]
// if user has seen the welcome message when they first use the network
viewedNetworkWelcome Boolean @default(false)
Expand Down
30 changes: 25 additions & 5 deletions src/commands/slash/Staff/ban.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import BaseCommand from '../../../core/BaseCommand.js';
import db from '../../../utils/Db.js';
import { simpleEmbed } from '../../../utils/Utils.js';
import { emojis } from '../../../utils/Constants.js';
import { DeveloperIds, emojis } from '../../../utils/Constants.js';

export default class Ban extends BaseCommand {
readonly staffOnly = true;
Expand All @@ -20,12 +20,30 @@ export default class Ban extends BaseCommand {
description: '🔨 The user to ban.',
required: true,
},
{
type: ApplicationCommandOptionType.String,
name: 'reason',
description: 'Reson for the ban',
required: true,
},
],
};
override async execute(interaction: ChatInputCommandInteraction): Promise<unknown> {
if (!DeveloperIds.includes(interaction.user.id)) return;

const user = interaction.options.getUser('user', true);
const reason = interaction.options.getString('reason', true);

if (user.id === interaction.user.id) {
await interaction.reply({
content: `Let's not go there. ${emojis.bruhcat}`,
ephemeral: true,
});
return;
}

const alreadyBanned = await db.userData.findFirst({
where: { userId: user.id, banned: true },
where: { userId: user.id, banMeta: { isNot: null } },
});

if (alreadyBanned) {
Expand All @@ -42,16 +60,18 @@ export default class Ban extends BaseCommand {
username: user.username,
viewedNetworkWelcome: false,
voteCount: 0,
banned: true,
banMeta: { reason },
},
update: {
banned: true,
banMeta: { reason },
},
});

await interaction.reply({
embeds: [
simpleEmbed(`${emojis.tick} Successfully banned **${user.username}**. They can no longer use the bot.`),
simpleEmbed(
`${emojis.tick} Successfully banned \`${user.username}\`. They can no longer use the bot.`,
),
],
});
}
Expand Down
5 changes: 4 additions & 1 deletion src/commands/slash/Staff/respawn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export default class Respawn extends BaseCommand {
return;
}

await interaction.reply(`${emojis.tick} Request to respawn shards received. I'll be back!`);
await interaction.reply({
content: `${emojis.tick} Request to respawn shards received. I'll be back!`,
ephemeral: true,
});

interaction.client.cluster.respawnAll();
}
Expand Down
10 changes: 6 additions & 4 deletions src/commands/slash/Staff/unban.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default class Unban extends BaseCommand {
override async execute(interaction: ChatInputCommandInteraction): Promise<unknown> {
const user = interaction.options.getUser('user', true);
const alreadyBanned = await db.userData.findFirst({
where: { userId: user.id, banned: true },
where: { userId: user.id, banMeta: { isSet: true } },
});

if (!alreadyBanned) {
Expand All @@ -42,16 +42,18 @@ export default class Unban extends BaseCommand {
username: user.username,
viewedNetworkWelcome: false,
voteCount: 0,
banned: false,
banMeta: { set: null },
},
update: {
banned: false,
banMeta: { set: null },
},
});

await interaction.reply({
embeds: [
simpleEmbed(`${emojis.tick} Successfully banned **${user.username}**. They can no longer use the bot.`),
simpleEmbed(
`${emojis.tick} Successfully unbanned \`${user.username}\`. They can use the bot again.`,
),
],
});
}
Expand Down
35 changes: 32 additions & 3 deletions src/managers/EventManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ import {
Interaction,
Client,
} from 'discord.js';
import {
checkIfStaff,
getAttachmentURL,
getUserLocale,
handleError,
simpleEmbed,
wait,
} from '../utils/Utils.js';
import db from '../utils/Db.js';
import Logger from '../utils/Logger.js';
import SuperClient from '../core/Client.js';
Expand All @@ -29,7 +37,6 @@ import { logGuildJoin, logGuildLeave } from '../scripts/guilds/goals.js';
import { channels, emojis, colors, LINKS } from '../utils/Constants.js';
import { getReferredMsgData, sendWelcomeMsg } from '../scripts/network/helpers.js';
import { HubSettingsBitField } from '../utils/BitFields.js';
import { getAttachmentURL, getUserLocale, handleError, simpleEmbed, wait } from '../utils/Utils.js';
import { addReaction, updateReactions } from '../scripts/reaction/actions.js';
import { checkBlacklists } from '../scripts/reaction/helpers.js';
import { CustomID } from '../utils/CustomID.js';
Expand Down Expand Up @@ -314,6 +321,23 @@ export default abstract class EventManager {
const userData = await db.userData.findFirst({ where: { userId: interaction.user.id } });
interaction.user.locale = getUserLocale(userData);

if (userData?.banMeta?.reason) {
if (interaction.isRepliable()) {
await interaction.reply({
content: t(
{ phrase: 'errors.banned', locale: interaction.user.locale },
{
emoji: emojis.no,
reason: userData.banMeta.reason,
support_invite: LINKS.SUPPORT_INVITE,
},
),
ephemeral: true,
});
}
return;
}

if (interaction.isMessageComponent() || interaction.isModalSubmit()) {
const ignoreList = ['page_', 'onboarding_'];
const customId = CustomID.parseCustomId(interaction.customId);
Expand Down Expand Up @@ -346,8 +370,13 @@ export default abstract class EventManager {
}

const command = commands.get(interaction.commandName);
if (!interaction.isAutocomplete()) await command?.execute(interaction); // slash commands
else if (command?.autocomplete) await command.autocomplete(interaction); // autocomplete

if (command?.staffOnly && !checkIfStaff(interaction.user.id)) return;

// slash commands
if (!interaction.isAutocomplete()) await command?.execute(interaction);
// autocompletes
else if (command?.autocomplete) await command.autocomplete(interaction);
}
catch (e) {
handleError(e, interaction);
Expand Down
5 changes: 2 additions & 3 deletions src/scripts/network/runChecks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,13 @@ export const runChecks = async (
const { locale } = message.author;
const { hasProfanity, hasSlurs } = checkProfanity(message.content);
const { settings, userData, attachmentURL } = opts;
const isUserBlacklisted = userData.blacklistedFrom.some((b) => b.hubId === hubId);

if (await isCaughtSpam(message, settings, hubId)) return false;
if (containsLinks(message, settings)) message.content = replaceLinks(message.content);

// banned / blacklisted
if (userData.banned || userData.blacklistedFrom.some((b) => b.hubId === hubId)) {
return false;
}
if (userData.banMeta?.reason || isUserBlacklisted) return false;

// send a log to the log channel set by the hub
if (hasProfanity || hasSlurs) {
Expand Down

0 comments on commit 6be9db8

Please sign in to comment.