aboutsummaryrefslogtreecommitdiff
path: root/src/lib/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/common')
-rw-r--r--src/lib/common/Format.ts107
-rw-r--r--src/lib/common/Moderation.ts293
2 files changed, 0 insertions, 400 deletions
diff --git a/src/lib/common/Format.ts b/src/lib/common/Format.ts
deleted file mode 100644
index 6cb6edc..0000000
--- a/src/lib/common/Format.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-import { type CodeBlockLang } from '#lib';
-import { EscapeMarkdownOptions, Formatters, Util } from 'discord.js';
-
-/**
- * Formats and escapes content for formatting
- */
-export class Format {
- /**
- * Wraps the content inside a codeblock with no language.
- * @param content The content to wrap.
- */
- public static codeBlock(content: string): string;
-
- /**
- * Wraps the content inside a codeblock with the specified language.
- * @param language The language for the codeblock.
- * @param content The content to wrap.
- */
- public static codeBlock(language: CodeBlockLang, content: string): string;
- public static codeBlock(languageOrContent: string, content?: string): string {
- return typeof content === 'undefined'
- ? Formatters.codeBlock(Util.escapeCodeBlock(`${languageOrContent}`))
- : Formatters.codeBlock(`${languageOrContent}`, Util.escapeCodeBlock(`${content}`));
- }
-
- /**
- * Wraps the content inside \`backticks\`, which formats it as inline code.
- * @param content The content to wrap.
- */
- public static inlineCode(content: string): string {
- return Formatters.inlineCode(Util.escapeInlineCode(`${content}`));
- }
-
- /**
- * Formats the content into italic text.
- * @param content The content to wrap.
- */
- public static italic(content: string): string {
- return Formatters.italic(Util.escapeItalic(`${content}`));
- }
-
- /**
- * Formats the content into bold text.
- * @param content The content to wrap.
- */
- public static bold(content: string): string {
- return Formatters.bold(Util.escapeBold(`${content}`));
- }
-
- /**
- * Formats the content into underscored text.
- * @param content The content to wrap.
- */
- public static underscore(content: string): string {
- return Formatters.underscore(Util.escapeUnderline(`${content}`));
- }
-
- /**
- * Formats the content into strike-through text.
- * @param content The content to wrap.
- */
- public static strikethrough(content: string): string {
- return Formatters.strikethrough(Util.escapeStrikethrough(`${content}`));
- }
-
- /**
- * Wraps the content inside spoiler (hidden text).
- * @param content The content to wrap.
- */
- public static spoiler(content: string): string {
- return Formatters.spoiler(Util.escapeSpoiler(`${content}`));
- }
-
- /**
- * Escapes any Discord-flavour markdown in a string.
- * @param text Content to escape
- * @param options Options for escaping the markdown
- */
- public static escapeMarkdown(text: string, options?: EscapeMarkdownOptions): string {
- return Util.escapeMarkdown(`${text}`, options);
- }
-
- /**
- * Formats input: makes it bold and escapes any other markdown
- * @param text The input
- */
- public static input(text: string): string {
- return this.bold(this.escapeMarkdown(this.sanitizeWtlAndControl(`${text}`)));
- }
-
- /**
- * Formats input for logs: makes it highlighted
- * @param text The input
- */
- public static inputLog(text: string): string {
- return `<<${this.sanitizeWtlAndControl(`${text}`)}>>`;
- }
-
- /**
- * Removes all characters in a string that are either control characters or change the direction of text etc.
- * @param str The string you would like sanitized
- */
- public static sanitizeWtlAndControl(str: string) {
- // eslint-disable-next-line no-control-regex
- return `${str}`.replace(/[\u0000-\u001F\u007F-\u009F\u200B]/g, '');
- }
-}
diff --git a/src/lib/common/Moderation.ts b/src/lib/common/Moderation.ts
deleted file mode 100644
index ab2943b..0000000
--- a/src/lib/common/Moderation.ts
+++ /dev/null
@@ -1,293 +0,0 @@
-import {
- ActivePunishment,
- ActivePunishmentType,
- Guild,
- ModLog,
- ModLogType,
- type BushGuildMember,
- type BushGuildMemberResolvable,
- type BushGuildResolvable
-} from '#lib';
-import { type Snowflake } from 'discord.js';
-
-/**
- * A utility class with moderation-related methods.
- */
-export class Moderation {
- /**
- * Checks if a moderator can perform a moderation action on another user.
- * @param moderator The person trying to perform the action.
- * @param victim The person getting punished.
- * @param type The type of punishment - used to format the response.
- * @param checkModerator Whether or not to check if the victim is a moderator.
- * @param force Override permissions checks.
- * @returns `true` if the moderator can perform the action otherwise a reason why they can't.
- */
- public static async permissionCheck(
- moderator: BushGuildMember,
- victim: BushGuildMember,
- type: 'mute' | 'unmute' | 'warn' | 'kick' | 'ban' | 'unban' | 'add a punishment role to' | 'remove a punishment role from',
- checkModerator = true,
- force = false
- ): Promise<true | string> {
- if (force) return true;
-
- // If the victim is not in the guild anymore it will be undefined
- if ((!victim || !victim.guild) && !['ban', 'unban'].includes(type)) return true;
-
- if (moderator.guild.id !== victim.guild.id) {
- throw new Error('moderator and victim not in same guild');
- }
-
- const isOwner = moderator.guild.ownerId === moderator.id;
- if (moderator.id === victim.id && !type.startsWith('un')) {
- return `${util.emojis.error} You cannot ${type} yourself.`;
- }
- if (
- moderator.roles.highest.position <= victim.roles.highest.position &&
- !isOwner &&
- !(type.startsWith('un') && moderator.id === victim.id)
- ) {
- return `${util.emojis.error} You cannot ${type} **${victim.user.tag}** because they have higher or equal role hierarchy as you do.`;
- }
- if (
- victim.roles.highest.position >= victim.guild.me!.roles.highest.position &&
- !(type.startsWith('un') && moderator.id === victim.id)
- ) {
- return `${util.emojis.error} You cannot ${type} **${victim.user.tag}** because they have higher or equal role hierarchy as I do.`;
- }
- if (checkModerator && victim.permissions.has('MANAGE_MESSAGES') && !(type.startsWith('un') && moderator.id === victim.id)) {
- if (await moderator.guild.hasFeature('modsCanPunishMods')) {
- return true;
- } else {
- return `${util.emojis.error} You cannot ${type} **${victim.user.tag}** because they are a moderator.`;
- }
- }
- return true;
- }
-
- /**
- * Creates a modlog entry for a punishment.
- * @param options Options for creating a modlog entry.
- * @param getCaseNumber Whether or not to get the case number of the entry.
- * @returns An object with the modlog and the case number.
- */
- public static async createModLogEntry(
- options: CreateModLogEntryOptions,
- getCaseNumber = false
- ): Promise<{ log: ModLog | null; caseNum: number | null }> {
- const user = (await util.resolveNonCachedUser(options.user))!.id;
- const moderator = (await util.resolveNonCachedUser(options.moderator))!.id;
- const guild = client.guilds.resolveId(options.guild)!;
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- const duration = options.duration || undefined;
-
- // If guild does not exist create it so the modlog can reference a guild.
- await Guild.findOrCreate({
- where: {
- id: guild
- },
- defaults: {
- id: guild
- }
- });
-
- const modLogEntry = ModLog.build({
- type: options.type,
- user,
- moderator,
- reason: options.reason,
- duration: duration,
- guild,
- pseudo: options.pseudo ?? false,
- evidence: options.evidence
- });
- const saveResult: ModLog | null = await modLogEntry.save().catch(async (e) => {
- await util.handleError('createModLogEntry', e);
- return null;
- });
-
- if (!getCaseNumber) return { log: saveResult, caseNum: null };
-
- const caseNum = (await ModLog.findAll({ where: { type: options.type, user: user, guild: guild, hidden: 'false' } }))?.length;
- return { log: saveResult, caseNum };
- }
-
- /**
- * Creates a punishment entry.
- * @param options Options for creating the punishment entry.
- * @returns The database entry, or null if no entry is created.
- */
- public static async createPunishmentEntry(options: CreatePunishmentEntryOptions): Promise<ActivePunishment | null> {
- const expires = options.duration ? new Date(+new Date() + options.duration ?? 0) : undefined;
- const user = (await util.resolveNonCachedUser(options.user))!.id;
- const guild = client.guilds.resolveId(options.guild)!;
- const type = this.findTypeEnum(options.type)!;
-
- const entry = ActivePunishment.build(
- options.extraInfo
- ? { user, type, guild, expires, modlog: options.modlog, extraInfo: options.extraInfo }
- : { user, type, guild, expires, modlog: options.modlog }
- );
- return await entry.save().catch(async (e) => {
- await util.handleError('createPunishmentEntry', e);
- return null;
- });
- }
-
- /**
- * Destroys a punishment entry.
- * @param options Options for destroying the punishment entry.
- * @returns Whether or not the entry was destroyed.
- */
- public static async removePunishmentEntry(options: RemovePunishmentEntryOptions): Promise<boolean> {
- const user = await util.resolveNonCachedUser(options.user);
- const guild = client.guilds.resolveId(options.guild);
- const type = this.findTypeEnum(options.type);
-
- if (!user || !guild) return false;
-
- let success = true;
-
- const entries = await ActivePunishment.findAll({
- // finding all cases of a certain type incase there were duplicates or something
- where: options.extraInfo
- ? { user: user.id, guild: guild, type, extraInfo: options.extraInfo }
- : { user: user.id, guild: guild, type }
- }).catch(async (e) => {
- await util.handleError('removePunishmentEntry', e);
- success = false;
- });
- if (entries) {
- const promises = entries.map(async (entry) =>
- entry.destroy().catch(async (e) => {
- await util.handleError('removePunishmentEntry', e);
- success = false;
- })
- );
-
- await Promise.all(promises);
- }
- return success;
- }
-
- /**
- * Returns the punishment type enum for the given type.
- * @param type The type of the punishment.
- * @returns The punishment type enum.
- */
- private static findTypeEnum(type: 'mute' | 'ban' | 'role' | 'block') {
- const typeMap = {
- ['mute']: ActivePunishmentType.MUTE,
- ['ban']: ActivePunishmentType.BAN,
- ['role']: ActivePunishmentType.ROLE,
- ['block']: ActivePunishmentType.BLOCK
- };
- return typeMap[type];
- }
-}
-
-/**
- * Options for creating a modlog entry.
- */
-export interface CreateModLogEntryOptions {
- /**
- * The type of modlog entry.
- */
- type: ModLogType;
-
- /**
- * The user that a modlog entry is created for.
- */
- user: BushGuildMemberResolvable;
-
- /**
- * The moderator that created the modlog entry.
- */
- moderator: BushGuildMemberResolvable;
-
- /**
- * The reason for the punishment.
- */
- reason: string | undefined | null;
-
- /**
- * The duration of the punishment.
- */
- duration?: number;
-
- /**
- * The guild that the punishment is created for.
- */
- guild: BushGuildResolvable;
-
- /**
- * Whether the punishment is a pseudo punishment.
- */
- pseudo?: boolean;
-
- /**
- * The evidence for the punishment.
- */
- evidence?: string;
-}
-
-/**
- * Options for creating a punishment entry.
- */
-export interface CreatePunishmentEntryOptions {
- /**
- * The type of punishment.
- */
- type: 'mute' | 'ban' | 'role' | 'block';
-
- /**
- * The user that the punishment is created for.
- */
- user: BushGuildMemberResolvable;
-
- /**
- * The length of time the punishment lasts for.
- */
- duration: number | undefined;
-
- /**
- * The guild that the punishment is created for.
- */
- guild: BushGuildResolvable;
-
- /**
- * The id of the modlog that is linked to the punishment entry.
- */
- modlog: string;
-
- /**
- * The role id if the punishment is a role punishment.
- */
- extraInfo?: Snowflake;
-}
-
-/**
- * Options for removing a punishment entry.
- */
-export interface RemovePunishmentEntryOptions {
- /**
- * The type of punishment.
- */
- type: 'mute' | 'ban' | 'role' | 'block';
-
- /**
- * The user that the punishment is destroyed for.
- */
- user: BushGuildMemberResolvable;
-
- /**
- * The guild that the punishment was in.
- */
- guild: BushGuildResolvable;
-
- /**
- * The role id if the punishment is a role punishment.
- */
- extraInfo?: Snowflake;
-}