Compare commits

...

5 commits

Author SHA1 Message Date
powermaker450 e24b163a34 Separate user and confession bans 2024-10-21 12:37:14 -04:00
powermaker450 4564cfb6a2 Cleanup involving destructures and prettier 2024-10-20 15:16:49 -04:00
powermaker450 aec01905b5 Differentiate between checking if a user is banned by user or id 2024-10-20 14:26:45 -04:00
powermaker450 7fbc7f4308 Add update command to update slash commands 2024-10-20 10:50:43 -04:00
powermaker450 e7bc0a32f6 Don't react to message deletes if the guild hasn't been set up yet 2024-10-18 15:25:40 -04:00
9 changed files with 252 additions and 86 deletions

View file

@ -52,9 +52,12 @@ export const data = new SlashCommandBuilder()
export async function execute(interaction: ChatInputCommandInteraction) { export async function execute(interaction: ChatInputCommandInteraction) {
// TODO: This all works as intended, but I'd like for it so be a reusable function // TODO: This all works as intended, but I'd like for it so be a reusable function
// instead because all of this is used in src/main.ts // instead because all of this is used in src/main.ts
const { id: guildId } = interaction.guild!;
const { id: userId } = interaction.user;
try { try {
// If the user is banned in this guild, don't let them post // If the user is banned in this guild, don't let them post
if (dt.isBanned(interaction.guild?.id!, interaction.user.id)) { if (dt.isBannedByUser(guildId, userId)) {
return interaction.reply({ return interaction.reply({
content: "You are banned from confessions in this server!", content: "You are banned from confessions in this server!",
ephemeral: true ephemeral: true
@ -62,7 +65,7 @@ export async function execute(interaction: ChatInputCommandInteraction) {
} }
// If no guild info is present for this guild, don't let the user post // If no guild info is present for this guild, don't let the user post
if (!dt.getGuildInfo(interaction.guild?.id!)) { if (!dt.getGuildInfo(guildId)) {
return interaction.reply({ return interaction.reply({
content: content:
"The bot hasn't been set up yet! Ask the server admins to set it up.", "The bot hasn't been set up yet! Ask the server admins to set it up.",
@ -70,10 +73,8 @@ export async function execute(interaction: ChatInputCommandInteraction) {
}); });
} }
const confessChannel = dt.getGuildInfo(interaction.guild?.id!)?.settings const confessChannel = dt.getGuildInfo(guildId)?.settings.confessChannel;
.confessChannel; const adminChannel = dt.getGuildInfo(guildId)?.settings.modChannel;
const adminChannel = dt.getGuildInfo(interaction.guild?.id!)?.settings
.modChannel;
const messageContent = `"${interaction.options.getString("message")}"`; const messageContent = `"${interaction.options.getString("message")}"`;
const attachment = interaction.options.getString("attachment")!; const attachment = interaction.options.getString("attachment")!;
@ -121,11 +122,11 @@ export async function execute(interaction: ChatInputCommandInteraction) {
.addFields( .addFields(
{ {
name: "Author", name: "Author",
value: `<@${interaction.user.id}>` value: `<@${userId}>`
}, },
{ {
name: "Author ID", name: "Author ID",
value: interaction.user.id value: userId
} }
); );
@ -153,9 +154,10 @@ export async function execute(interaction: ChatInputCommandInteraction) {
components: [actionRow] components: [actionRow]
}); });
adminChannel && await (BotClient.channels.cache.get(adminChannel!) as TextChannel).send({ adminChannel &&
(await (BotClient.channels.cache.get(adminChannel!) as TextChannel).send({
embeds: [adminConfessionEmbed] embeds: [adminConfessionEmbed]
}); }));
dt.addConfession( dt.addConfession(
message, message,
@ -166,8 +168,7 @@ export async function execute(interaction: ChatInputCommandInteraction) {
attachment attachment
); );
const confessionsLength = dt.getGuildInfo(interaction.guild?.id!) const confessionsLength = dt.getGuildInfo(guildId)!.confessions.length;
?.confessions.length!;
// If there are 2 or more confessions, remove the previous confession's button components // If there are 2 or more confessions, remove the previous confession's button components
if (confessionsLength >= 2) { if (confessionsLength >= 2) {
@ -175,9 +176,7 @@ export async function execute(interaction: ChatInputCommandInteraction) {
BotClient.channels.cache.get(confessChannel!) as TextChannel BotClient.channels.cache.get(confessChannel!) as TextChannel
).messages ).messages
.fetch( .fetch(
dt.getGuildInfo(interaction.guild?.id!)?.confessions[ dt.getGuildInfo(guildId)!.confessions[confessionsLength - 2].messageId
confessionsLength - 2
].messageId!
) )
.then(message => { .then(message => {
message.edit({ components: [] }); message.edit({ components: [] });

View file

@ -38,8 +38,11 @@ export const data = new SlashCommandBuilder()
); );
export async function execute(interaction: ChatInputCommandInteraction) { export async function execute(interaction: ChatInputCommandInteraction) {
const { id: guildId } = interaction.guild!;
const { id: userId } = interaction.user;
// If there is no guild info, don't let the user delete anything // If there is no guild info, don't let the user delete anything
if (!dt.getGuildInfo(interaction.guild?.id!)) { if (!dt.getGuildInfo(guildId)) {
return interaction.reply({ return interaction.reply({
content: content:
"The bot hasn't been set up yet! Ask the server admins to set it up.", "The bot hasn't been set up yet! Ask the server admins to set it up.",
@ -48,9 +51,9 @@ export async function execute(interaction: ChatInputCommandInteraction) {
} }
const idVal = interaction.options.getString("id")!; const idVal = interaction.options.getString("id")!;
const result = dt.getConfession(interaction.guild?.id!, idVal); const result = dt.getConfession(guildId, idVal);
// If there is a result, and the user is either an author or has manage messages // If there is a result, and the user is either an author or has manage messages
const allowedByUser = result && result.authorId === interaction.user.id; const allowedByUser = result && result.authorId === userId;
const allowedByMod = const allowedByMod =
result && result &&
interaction.memberPermissions?.has(PermissionFlagsBits.ManageMessages); interaction.memberPermissions?.has(PermissionFlagsBits.ManageMessages);
@ -58,12 +61,8 @@ export async function execute(interaction: ChatInputCommandInteraction) {
// If a confession is found with the given ID, check if the user is the one that posted it, and delete it if they are. // If a confession is found with the given ID, check if the user is the one that posted it, and delete it if they are.
// Otherwise, don't let the user delete anything. // Otherwise, don't let the user delete anything.
if (allowedByUser || allowedByMod) { if (allowedByUser || allowedByMod) {
const confession = dt.getConfession( const confession = dt.getConfession(guildId, idVal)!.messageId;
interaction.guild?.id!, const channelId = dt.getGuildInfo(guildId)!.settings.confessChannel;
idVal
)?.messageId;
const channelId = dt.getGuildInfo(interaction.guild?.id!)?.settings
.confessChannel!;
const emptyEmbed = new EmbedBuilder() const emptyEmbed = new EmbedBuilder()
.setColor(getRandomColor()) .setColor(getRandomColor())
.setTitle("Confession Deleted") .setTitle("Confession Deleted")
@ -76,7 +75,7 @@ export async function execute(interaction: ChatInputCommandInteraction) {
try { try {
// Replace the given confession with an empty embed // Replace the given confession with an empty embed
await (BotClient.channels.cache.get(channelId) as TextChannel).messages await (BotClient.channels.cache.get(channelId) as TextChannel).messages
.fetch(confession!) .fetch(confession)
.then(e => { .then(e => {
e.edit({ e.edit({
embeds: [emptyEmbed] embeds: [emptyEmbed]

View file

@ -18,11 +18,16 @@
import { import {
ChatInputCommandInteraction, ChatInputCommandInteraction,
heading,
HeadingLevel,
inlineCode,
italic,
PermissionFlagsBits, PermissionFlagsBits,
SlashCommandBuilder SlashCommandBuilder
} from "discord.js"; } from "discord.js";
import { dt } from "../main"; import { dt } from "../main";
import Logger from "../utils/Logger"; import Logger from "../utils/Logger";
import { BanReason } from "../storeman";
const logger = new Logger("(/) confessban"); const logger = new Logger("(/) confessban");
@ -33,7 +38,7 @@ export const data = new SlashCommandBuilder()
.addSubcommand(ban => .addSubcommand(ban =>
ban ban
.setName("ban") .setName("ban")
.setDescription("Ban a user from confessions") .setDescription("Ban an ID from confessions")
.addStringOption(option => .addStringOption(option =>
option option
.setName("id") .setName("id")
@ -43,6 +48,14 @@ export const data = new SlashCommandBuilder()
.setRequired(true) .setRequired(true)
) )
) )
.addSubcommand(banuser =>
banuser
.setName("banuser")
.setDescription("Ban a user from confessions")
.addUserOption(user =>
user.setName("user").setDescription("The user to ban").setRequired(true)
)
)
.addSubcommand(list => .addSubcommand(list =>
list.setName("list").setDescription("Show the list of banned users") list.setName("list").setDescription("Show the list of banned users")
) )
@ -61,13 +74,13 @@ export const data = new SlashCommandBuilder()
); );
export async function execute(interaction: ChatInputCommandInteraction) { export async function execute(interaction: ChatInputCommandInteraction) {
const guildId = interaction.guild?.id!; const { id: guildId } = interaction.guild!;
// /confessmod ban <id> // /confessmod ban <id>
if (interaction.options.getSubcommand() === "ban") { if (interaction.options.getSubcommand() === "ban") {
const confessionId = interaction.options.getString("id")!; const confessionId = interaction.options.getString("id")!;
if (dt.isBanned(guildId, confessionId)) { if (dt.isBannedById(guildId, confessionId)) {
try { try {
return interaction.reply({ return interaction.reply({
content: "That user is already banned!", content: "That user is already banned!",
@ -78,7 +91,7 @@ export async function execute(interaction: ChatInputCommandInteraction) {
} }
} }
const result = dt.addBan(guildId, confessionId); const result = dt.addBanById(guildId, confessionId);
try { try {
return result return result
@ -93,41 +106,76 @@ export async function execute(interaction: ChatInputCommandInteraction) {
} catch (err) { } catch (err) {
logger.error("A ban interaction error occured:", err); logger.error("A ban interaction error occured:", err);
} }
// /confessmod banuser <user>
} else if (interaction.options.getSubcommand() === "banuser") {
const { id: userId } = interaction.options.getUser("user")!;
const result = dt.addBanByUser(guildId, userId);
try {
return result
? interaction.reply({
content: "User was banned.",
ephemeral: true
})
: interaction.reply({
content: "How did we get here? (An error occured.)}",
ephemeral: true
});
} catch (err) {
logger.error("A banuser interaction error occured:", err);
}
// /confessmod list // /confessmod list
} else if (interaction.options.getSubcommand() === "list") { } else if (interaction.options.getSubcommand() === "list") {
const bannedMembers = dt.getBans(interaction.guild?.id!); const bannedMembers = dt.getBans(guildId);
let content = bannedMembers.length const determineContent = () => {
? "Banned Members:\n" if (!bannedMembers.length) {
: "There are no banned members."; return "There are no bans.";
}
// For each member, add them to the message content. let userHead = heading("Users:", HeadingLevel.Two);
// It will end up looking something like this: let userCount = false;
//
// Banned Members: let idHead = "\n" + heading("Confessions:", HeadingLevel.Two);
// let idCount = false;
// @user1 | a1b2
// @user2 | c3d4
// @user3 | e5f6
//
for (const member of bannedMembers) { for (const member of bannedMembers) {
content += `\n<@${member.user}> | \`${member.confessionId}\``;
if (member.method === BanReason.ByUser) {
userHead += "\n" + `<@${member.user}>`;
userCount = true;
} else if (member.method === BanReason.ById) {
const confession = dt.getConfession(guildId, member.confessionId!)!;
idHead += `\nConfession ${inlineCode(member.confessionId!)}: ${italic(confession.content)}`;
idCount = true;
}
}
// If there are users and confessions use both headers, otherwise use whichever is populated
if (userCount && idCount) {
return userHead + idHead;
} else {
return userCount
? userHead
: idHead;
}
} }
try { try {
return interaction.reply({ return interaction.reply({
content: content, content: determineContent(),
ephemeral: true ephemeral: true
}); });
} catch (err) { } catch (err) {
logger.error("A banlist interaction error occured:", err); logger.error("A banlist interaction error occured:", err);
return interaction.reply({
content: "A server-side error occurred when getting the ban list.",
ephemeral: true
});
} }
// /confessmod pardon <id> // /confessmod pardon <id>
} else if (interaction.options.getSubcommand() === "pardon") { } else if (interaction.options.getSubcommand() === "pardon") {
const result = dt.removeBan( const result = dt.removeBan(guildId, interaction.options.getString("id")!);
interaction.guild?.id!,
interaction.options.getString("id")!
);
try { try {
return result return result

View file

@ -21,11 +21,13 @@ import * as confessdel from "./confessdel";
import * as confessmod from "./confessmod"; import * as confessmod from "./confessmod";
import * as ping from "./ping"; import * as ping from "./ping";
import * as setup from "./setup"; import * as setup from "./setup";
import * as update from "./update";
export const commands = { export const commands = {
confess, confess,
confessdel, confessdel,
confessmod, confessmod,
ping, ping,
setup setup,
update
}; };

View file

@ -38,14 +38,16 @@ export const data = new SlashCommandBuilder()
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild); .setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild);
export async function execute(interaction: CommandInteraction) { export async function execute(interaction: CommandInteraction) {
if (dt.checkSetup(interaction.guild?.id!)) { const { id: guildId } = interaction.guild!;
const { displayName: username } = interaction.user;
if (dt.checkSetup(guildId)) {
return interaction.reply({ return interaction.reply({
content: "This guild has already been set up!", content: "This guild has already been set up!",
ephemeral: true ephemeral: true
}); });
} }
const guildId = interaction.guild?.id;
let confessChannel: string, logChannel: string; let confessChannel: string, logChannel: string;
const channelList = new ChannelSelectMenuBuilder() const channelList = new ChannelSelectMenuBuilder()
@ -56,17 +58,18 @@ export async function execute(interaction: CommandInteraction) {
const skipButton = new ButtonBuilder() const skipButton = new ButtonBuilder()
.setCustomId("skipModChannel") .setCustomId("skipModChannel")
.setLabel("Skip") .setLabel("Skip")
.setStyle(ButtonStyle.Secondary) .setStyle(ButtonStyle.Secondary);
const channelRow = const channelRow =
new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(channelList); new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(channelList);
const buttonRow = new ActionRowBuilder<ButtonBuilder>() const buttonRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
.addComponents(skipButton); skipButton
);
try { try {
const response = await interaction.reply({ const response = await interaction.reply({
content: `# Let's get started, ${interaction.user.displayName}!\nFirst, let's choose a channel for your confessions.`, content: `# Let's get started, ${username}!\nFirst, let's choose a channel for your confessions.`,
ephemeral: true, ephemeral: true,
components: [channelRow] components: [channelRow]
}); });
@ -122,7 +125,7 @@ export async function execute(interaction: CommandInteraction) {
components: [] components: []
}); });
dt.setup(guildId!, { dt.setup(guildId, {
confessChannel: confessChannel, confessChannel: confessChannel,
modChannel: logChannel, modChannel: logChannel,
bans: [] bans: []
@ -148,11 +151,12 @@ export async function execute(interaction: CommandInteraction) {
logCollector.stop(); logCollector.stop();
skipCollector.stop(); skipCollector.stop();
} }
}) });
logCollector.on("end", content => { logCollector.on("end", content => {
// If there is no content and the channel hasn't been skipped, follow up with an error message. // If there is no content and the channel hasn't been skipped, follow up with an error message.
(!content.size && !skipped) && !content.size &&
!skipped &&
interaction.followUp({ interaction.followUp({
content: "No channel selected. Please try again.", content: "No channel selected. Please try again.",
ephemeral: true, ephemeral: true,

63
src/commands/update.ts Normal file
View file

@ -0,0 +1,63 @@
/*
* Confoss: Anonymous confessions for Discord, free as in freedom and price!
* Copyright (C) 2024 powermaker450
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {
ChatInputCommandInteraction,
PermissionFlagsBits,
SlashCommandBuilder
} from "discord.js";
import { deployCommands } from "../bot";
import Logger from "../utils/Logger";
const logger = new Logger("(/) update");
const minutes = 5;
const cooldownList = new Set();
export const data = new SlashCommandBuilder()
.setName("update")
.setDescription("Update the bot with new data if available")
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild);
export async function execute(interaction: ChatInputCommandInteraction) {
const { id: guildId, name: guildName } = interaction.guild!;
if (cooldownList.has(guildId)) {
return interaction.reply({
content: `You can only run the update command once every ${minutes} minutes.`,
ephemeral: true
});
}
deployCommands({ guildId: guildId });
cooldownList.add(guildId);
logger.log(`Applied cooldown to "${guildName}"`);
setTimeout(
() => {
cooldownList.delete(guildId);
logger.log(`Removed cooldown from "${guildName}"`);
},
minutes * 60 * 1000
);
return interaction.reply({
content: "Commands refreshed.",
ephemeral: true
});
}

View file

@ -65,8 +65,12 @@ BotClient.on(Events.InteractionCreate, async interaction => {
}); });
BotClient.on(Events.MessageDelete, async message => { BotClient.on(Events.MessageDelete, async message => {
try {
const guildId = message.guild?.id!; const guildId = message.guild?.id!;
if (!dt.getGuildInfo(guildId)) {
return;
}
try {
const messageId = message.id; const messageId = message.id;
const confessions = dt.getGuildInfo(guildId)?.confessions!; const confessions = dt.getGuildInfo(guildId)?.confessions!;
@ -93,7 +97,7 @@ BotClient.on(Events.InteractionCreate, async interaction => {
if (requestSubmit) { if (requestSubmit) {
// Check if the user is banned from confessions before showing the modal // Check if the user is banned from confessions before showing the modal
dt.isBanned(interaction.guild?.id!, interaction.user.id) dt.isBannedByUser(interaction.guild?.id!, interaction.user.id)
? interaction.reply({ ? interaction.reply({
content: "You are banned from confessions in this server!", content: "You are banned from confessions in this server!",
ephemeral: true ephemeral: true
@ -114,7 +118,7 @@ BotClient.on(Events.InteractionCreate, async interaction => {
); );
try { try {
if (dt.isBanned(interaction.guild?.id!, interaction.user.id)) { if (dt.isBannedByUser(interaction.guild?.id!, interaction.user.id)) {
return interaction.reply({ return interaction.reply({
content: "You are banned from confessions in this server!", content: "You are banned from confessions in this server!",
ephemeral: true ephemeral: true
@ -179,9 +183,12 @@ BotClient.on(Events.InteractionCreate, async interaction => {
components: [actionRow] components: [actionRow]
}); });
adminChannel && await (BotClient.channels.cache.get(adminChannel!) as TextChannel).send({ adminChannel &&
(await (
BotClient.channels.cache.get(adminChannel!) as TextChannel
).send({
embeds: [adminConfessionEmbed] embeds: [adminConfessionEmbed]
}); }));
dt.addConfession( dt.addConfession(
message, message,

View file

@ -18,7 +18,13 @@
import fs from "fs"; import fs from "fs";
import crypto from "crypto"; import crypto from "crypto";
import { Confession, ConfessionBan, GuildData, GuildSettings } from "./types"; import {
BanReason,
Confession,
ConfessionBan,
GuildData,
GuildSettings
} from "./types";
import { DATA_DIR } from "./config"; import { DATA_DIR } from "./config";
import { CommandInteraction, Message } from "discord.js"; import { CommandInteraction, Message } from "discord.js";
import Logger from "../utils/Logger"; import Logger from "../utils/Logger";
@ -82,9 +88,9 @@ export class StoreMan {
} }
// Checks if a guild is not set up // Checks if a guild is not set up
public checkSetup(id: string): boolean { public checkSetup(guildId: string): boolean {
for (const guild of this.data) { for (const guild of this.data) {
if (guild.id === id) { if (guild.id === guildId) {
return true; return true;
} }
} }
@ -93,9 +99,9 @@ export class StoreMan {
} }
// Sets up a guild and stores it in the persistent file // Sets up a guild and stores it in the persistent file
public setup(id: string, opts: GuildSettings): void { public setup(guildId: string, opts: GuildSettings): void {
this.data.push({ this.data.push({
id: id, id: guildId,
confessions: [], confessions: [],
settings: opts settings: opts
}); });
@ -104,16 +110,16 @@ export class StoreMan {
} }
// Clear the settings for a given guild // Clear the settings for a given guild
public clearSettings(id: string): void { public clearSettings(guildId: string): void {
this.data = this.data.filter(guild => { this.data = this.data.filter(guild => {
return guild.id !== id; return guild.id !== guildId;
}); });
this.saveFile(); this.saveFile();
} }
public getGuildInfo(id: string): GuildData | null { public getGuildInfo(guildId: string): GuildData | null {
for (const guild of this.data) { for (const guild of this.data) {
if (guild.id === id) { if (guild.id === guildId) {
return guild; return guild;
} }
} }
@ -130,12 +136,12 @@ export class StoreMan {
content: string, content: string,
attachment?: string attachment?: string
): boolean { ): boolean {
const guildId = message.guild?.id; const { id: guildId } = message.guild!;
for (const guild of this.data) { for (const guild of this.data) {
if (guild.id === guildId) { if (guild.id === guildId) {
// If the author's user ID is in the ban list, don't let them post a confession. // If the author's user ID is in the ban list, don't let them post a confession.
if (this.isBanned(guildId, author)) { if (this.isBannedByUser(guildId, author)) {
return false; return false;
} }
@ -215,7 +221,7 @@ export class StoreMan {
} }
// Check if a certain user is banned within a guild. // Check if a certain user is banned within a guild.
public isBanned(guildId: string, userId: string): boolean { public isBannedByUser(guildId: string, userId: string): boolean {
for (const guild of this.data) { for (const guild of this.data) {
if (guild.id === guildId) { if (guild.id === guildId) {
for (const ban of guild.settings.bans) { for (const ban of guild.settings.bans) {
@ -229,6 +235,20 @@ export class StoreMan {
return false; return false;
} }
public isBannedById(guildId: string, confessionId: string): boolean {
for (const guild of this.data) {
if (guild.id === guildId) {
for (const ban of guild.settings.bans) {
if (ban.confessionId === confessionId) {
return true;
}
}
}
}
return false;
}
public getBans(guildId: string): ConfessionBan[] { public getBans(guildId: string): ConfessionBan[] {
for (const guild of this.data) { for (const guild of this.data) {
if (guild.id === guildId) { if (guild.id === guildId) {
@ -240,17 +260,18 @@ export class StoreMan {
} }
// Attempts to ban a user from confessions. // Attempts to ban a user from confessions.
public addBan(guildId: string, confessionId: string): boolean { public addBanById(guildId: string, confessionId: string): boolean {
const confession = this.getConfession(guildId, confessionId); const confession = this.getConfession(guildId, confessionId);
for (const guild of this.data) { for (const guild of this.data) {
if (guild.id === guildId) { if (guild.id === guildId) {
if (confession) { if (confession) {
// Only add the user to the ban list if they aren't banned already // Only add the user to the ban list if they aren't banned already
!this.isBanned(guildId, confession.authorId) && !this.isBannedByUser(guildId, confession.authorId) &&
guild.settings.bans.push({ guild.settings.bans.push({
user: confession.authorId, user: confession.authorId,
confessionId: confessionId confessionId: confessionId,
method: BanReason.ById
}); });
this.saveFile(); this.saveFile();
@ -262,6 +283,23 @@ export class StoreMan {
return false; return false;
} }
public addBanByUser(guildId: string, userId: string): boolean {
for (const guild of this.data) {
if (guild.id === guildId) {
// Only add the user to the ban list if they aren't banned already
!this.isBannedByUser(guildId, userId) && guild.settings.bans.push({
user: userId,
method: BanReason.ByUser
});
this.saveFile();
return true;
}
}
return false;
}
// Attempts to pardon a user from a ban. If sucessfully completed, returns true, false if otherwise. // Attempts to pardon a user from a ban. If sucessfully completed, returns true, false if otherwise.
public removeBan(guildId: string, confessionId: string): boolean { public removeBan(guildId: string, confessionId: string): boolean {
for (const guild of this.data) { for (const guild of this.data) {

View file

@ -25,9 +25,15 @@ export interface Confession {
attachment?: string; attachment?: string;
} }
export enum BanReason {
ById,
ByUser
}
export interface ConfessionBan { export interface ConfessionBan {
user: string; user: string;
confessionId: string; confessionId?: string;
method: BanReason;
} }
export interface GuildSettings { export interface GuildSettings {