diff options
32 files changed, 694 insertions, 297 deletions
diff --git a/.eslintrc.json b/.eslintrc.json index 1d9ffcf..5209b65 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -10,7 +10,7 @@ "sourceType": "module", "project": "./tsconfig.json" }, - "plugins": ["@typescript-eslint", "deprecation", "node", "import"], + "plugins": ["@typescript-eslint", "deprecation", "import"], "ignorePatterns": ["dist"], "rules": { "no-return-await": "off", @@ -61,8 +61,24 @@ "deprecation/deprecation": "warn", "@typescript-eslint/explicit-member-accessibility": ["warn", { "accessibility": "explicit" }], "@typescript-eslint/switch-exhaustiveness-check": "warn", - "node/file-extension-in-import": ["error", "always", { "tryExtensions": [".js", ".json"] }], "import/no-commonjs": "error", - "import/extensions": ["error", "ignorePackages"] + "import/extensions": ["error", "ignorePackages"], + "@typescript-eslint/no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "discord-api-types", + "message": "Please use discord-api-types/v9 instead.", + "allowTypeImports": true + }, + { + "name": "discord-api-types-next", + "message": "Please use discord-api-types-next/v9 instead.", + "allowTypeImports": true + } + ] + } + ] } } diff --git a/package.json b/package.json index 3489b35..c3ea3e6 100644 --- a/package.json +++ b/package.json @@ -34,10 +34,11 @@ "build:esbuild": "yarn rimraf dist && yarn esbuild --sourcemap=inline --outdir=dist --platform=node --target=es2020 --format=esm --log-level=warning src/**/*.ts", "build:tsc": "yarn rimraf dist && yarn tsc", "build:tsc:no-emit": "yarn rimraf dist && yarn tsc --noEmit", - "_start": "yarn build:esbuild && node --enable-source-maps --experimental-json-modules --no-warnings dist/src/bot.js", - "start": "yarn build:tsc && node --enable-source-maps --experimental-json-modules --no-warnings dist/src/bot.js", + "start:raw": "node --enable-source-maps --experimental-json-modules --no-warnings dist/src/bot.js", + "start:esbuild": "yarn build:esbuild && yarn start:raw", + "start": "yarn build:tsc && yarn start:raw", "start:dry": "yarn start dry", - "dev": "yarn build:tsc && node --enable-source-maps --experimental-json-modules --no-warnings dist/src/bot.js", + "dev": "yarn build:tsc && yarn start:raw", "test": "yarn lint && yarn tsc --noEmit", "format": "yarn prettier . --write", "lint": "yarn eslint --ext js,jsx,ts,tsx src", @@ -55,14 +56,15 @@ "@notenoughupdates/humanize-duration": "^4.0.1", "@notenoughupdates/simplify-number": "^1.0.1", "@notenoughupdates/wolfram-alpha-api": "^1.0.1", - "@sentry/integrations": "^6.17.6", - "@sentry/node": "^6.17.6", - "@sentry/tracing": "^6.17.6", + "@sentry/integrations": "^6.17.7", + "@sentry/node": "^6.17.7", + "@sentry/tracing": "^6.17.7", "canvas": "^2.9.0", "chalk": "^5.0.0", "deep-lock": "^1.0.0", "discord-akairo": "npm:@notenoughupdates/discord-akairo@dev", - "discord-api-types": "0.26.1", + "discord-api-types": "0.27.0", + "discord-api-types-next": "npm:discord-api-types@next", "discord.js": "npm:@notenoughupdates/discord.js@dev", "fuse.js": "^6.5.3", "got": "^12.0.1", @@ -74,7 +76,7 @@ "pg": "^8.7.3", "pg-hstore": "^2.3.4", "prettier": "^2.5.1", - "pretty-bytes": "^5.6.0", + "pretty-bytes": "^6.0.0", "rimraf": "^3.0.2", "sequelize": "6.16.1", "tinycolor2": "^1.4.2", @@ -83,7 +85,7 @@ }, "devDependencies": { "@sapphire/snowflake": "^3.1.0", - "@sentry/types": "^6.17.6", + "@sentry/types": "^6.17.7", "@types/eslint": "^8.4.1", "@types/express": "^4.17.13", "@types/lodash": "^4.14.178", @@ -97,12 +99,14 @@ "@types/validator": "^13.7.1", "@typescript-eslint/eslint-plugin": "^5.11.0", "@typescript-eslint/parser": "^5.11.0", - "eslint": "^8.8.0", + "eslint": "^8.9.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-deprecation": "^1.3.2", "eslint-plugin-import": "^2.25.4", - "eslint-plugin-node": "^11.1.0", "node-fetch": "^3.2.0" }, + "resolutions": { + "@discordjs/rest@npm:^0.4.0-dev": "0.3.0" + }, "packageManager": "yarn@3.1.1" } diff --git a/src/arguments/discordEmoji.ts b/src/arguments/discordEmoji.ts index d9428e1..efaa4dd 100644 --- a/src/arguments/discordEmoji.ts +++ b/src/arguments/discordEmoji.ts @@ -1,5 +1,5 @@ -import { type BushArgumentTypeCaster } from '#lib'; -import { type Snowflake } from 'discord-api-types'; +import type { BushArgumentTypeCaster } from '#lib'; +import type { Snowflake } from 'discord-api-types'; export const discordEmoji: BushArgumentTypeCaster<DiscordEmojiInfo | null> = (_, phrase) => { if (!phrase) return null; diff --git a/src/commands/config/config.ts b/src/commands/config/config.ts index 2fae2fd..5346924 100644 --- a/src/commands/config/config.ts +++ b/src/commands/config/config.ts @@ -354,6 +354,7 @@ export default class ConfigCommand extends BushCommand { }; const components = new ActionRow().addComponents( + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Primary).setCustomId('command_settingsBack').setLabel('Back') ); settingsEmbed.setDescription( diff --git a/src/commands/config/features.ts b/src/commands/config/features.ts index 2e7d623..7fa82a9 100644 --- a/src/commands/config/features.ts +++ b/src/commands/config/features.ts @@ -90,7 +90,7 @@ export default class FeaturesCommand extends BushCommand { .setMaxValues(1) .setMinValues(1) .setOptions( - guildFeatures.map((f) => + ...guildFeatures.map((f) => new SelectMenuOption().setLabel(guildFeaturesObj[f].name).setValue(f).setDescription(guildFeaturesObj[f].description) ) ) diff --git a/src/commands/dev/servers.ts b/src/commands/dev/servers.ts index 173970b..378893e 100644 --- a/src/commands/dev/servers.ts +++ b/src/commands/dev/servers.ts @@ -1,6 +1,6 @@ import { BushCommand, ButtonPaginator, type BushMessage, type BushSlashMessage } from '#lib'; -import { APIEmbed } from 'discord-api-types'; -import { type Guild } from 'discord.js'; +import type { APIEmbed } from 'discord-api-types'; +import type { Guild } from 'discord.js'; export default class ServersCommand extends BushCommand { public constructor() { diff --git a/src/commands/dev/test.ts b/src/commands/dev/test.ts index 669001f..9784412 100644 --- a/src/commands/dev/test.ts +++ b/src/commands/dev/test.ts @@ -1,5 +1,4 @@ import { BushCommand, ButtonPaginator, Shared, type BushMessage } from '#lib'; -// eslint-disable-next-line node/file-extension-in-import import { Routes } from 'discord-api-types/rest/v9'; import { ActionRow, @@ -55,10 +54,15 @@ export default class TestCommand extends BushCommand { if (['button', 'buttons'].includes(args?.feature?.toLowerCase())) { const ButtonRow = new ActionRow().addComponents( + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Primary).setCustomId('primaryButton').setLabel('Primary'), + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Secondary).setCustomId('secondaryButton').setLabel('Secondary'), + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Success).setCustomId('successButton').setLabel('Success'), + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Danger).setCustomId('dangerButton').setLabel('Danger'), + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Link').setURL('https://www.youtube.com/watch?v=dQw4w9WgXcQ') ); return await message.util.reply({ content: 'buttons', components: [ButtonRow] }); @@ -78,6 +82,7 @@ export default class TestCommand extends BushCommand { .setTitle('Title'); const buttonRow = new ActionRow().addComponents( + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Link').setURL('https://google.com/') ); return await message.util.reply({ content: 'Test', embeds: [embed], components: [buttonRow] }); @@ -87,6 +92,7 @@ export default class TestCommand extends BushCommand { const row = new ActionRow(); for (let b = 1; b <= 5; b++) { const id = (a + 5 * (b - 1)).toString(); + // @ts-expect-error: outdated @discord.js/builders const button = new ButtonComponent().setStyle(ButtonStyle.Primary).setCustomId(id).setLabel(id); row.addComponents(button); } @@ -119,6 +125,7 @@ export default class TestCommand extends BushCommand { const row = new ActionRow(); for (let b = 1; b <= 5; b++) { const id = (a + 5 * (b - 1)).toString(); + // @ts-expect-error: outdated @discord.js/builders const button = new ButtonComponent().setStyle(ButtonStyle.Secondary).setCustomId(id).setLabel(id); row.addComponents(button); } @@ -151,6 +158,7 @@ export default class TestCommand extends BushCommand { content: 'Click for modal', components: [ new ActionRow().addComponents( + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Primary).setLabel('Modal').setCustomId('test;modal') ) ] diff --git a/src/commands/info/guildInfo.ts b/src/commands/info/guildInfo.ts index a4b7fb9..ed8a973 100644 --- a/src/commands/info/guildInfo.ts +++ b/src/commands/info/guildInfo.ts @@ -1,6 +1,6 @@ import { BushCommand, type ArgType, type BushMessage, type BushSlashMessage, type OptionalArgType } from '#lib'; import assert from 'assert'; -import { GuildDefaultMessageNotifications, GuildExplicitContentFilter } from 'discord-api-types'; +import { GuildDefaultMessageNotifications, GuildExplicitContentFilter } from 'discord-api-types/v9'; import { ApplicationCommandOptionType, Embed, diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts index 2383566..ef3ef30 100644 --- a/src/commands/info/help.ts +++ b/src/commands/info/help.ts @@ -143,14 +143,17 @@ export default class HelpCommand extends BushCommand { const row = new ActionRow(); if (!client.config.isDevelopment && !client.guilds.cache.some((guild) => guild.ownerId === message.author.id)) { + // @ts-expect-error: outdated @discord.js/builders row.addComponents(new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Invite Me').setURL(util.invite)); } if (!client.guilds.cache.get(client.config.supportGuild.id)?.members.cache.has(message.author.id)) { row.addComponents( + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Support Server').setURL(client.config.supportGuild.invite) ); } if (packageDotJSON?.repository) + // @ts-expect-error: outdated @discord.js/builders row.addComponents(new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('GitHub').setURL(packageDotJSON.repository)); else void message.channel?.send('Error importing package.json, please report this to my developer.'); diff --git a/src/commands/info/links.ts b/src/commands/info/links.ts index 25b040c..d9d5b8a 100644 --- a/src/commands/info/links.ts +++ b/src/commands/info/links.ts @@ -22,10 +22,13 @@ export default class LinksCommand extends BushCommand { public override async exec(message: BushMessage | BushSlashMessage) { const buttonRow = new ActionRow(); if (!client.config.isDevelopment || message.author.isOwner()) { + // @ts-expect-error: outdated @discord.js/builders buttonRow.addComponents(new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Invite Me').setURL(util.invite)); } buttonRow.addComponents( + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('Support Server').setURL(client.config.supportGuild.invite), + // @ts-expect-error: outdated @discord.js/builders new ButtonComponent().setStyle(ButtonStyle.Link).setLabel('GitHub').setURL(packageDotJSON.repository) ); return await message.util.reply({ content: 'Here are some useful links:', components: [buttonRow] }); diff --git a/src/commands/info/userInfo.ts b/src/commands/info/userInfo.ts index 97cdc30..02a3be6 100644 --- a/src/commands/info/userInfo.ts +++ b/src/commands/info/userInfo.ts @@ -7,7 +7,7 @@ import { type BushSlashMessage, type BushUser } from '#lib'; -import { APIApplication, TeamMemberMembershipState } from 'discord-api-types'; +import { TeamMemberMembershipState, type APIApplication } from 'discord-api-types/v9'; import { ActivityType, ApplicationCommandOptionType, diff --git a/src/commands/moulberry-bush/capes.ts b/src/commands/moulberry-bush/capes.ts index 032f62d..47a4ea6 100644 --- a/src/commands/moulberry-bush/capes.ts +++ b/src/commands/moulberry-bush/capes.ts @@ -1,6 +1,6 @@ import { BushCommand, ButtonPaginator, DeleteButton, type BushMessage, type OptionalArgType } from '#lib'; import assert from 'assert'; -import { APIEmbed } from 'discord-api-types'; +import { APIEmbed } from 'discord-api-types/v9'; import { ApplicationCommandOptionType, AutocompleteInteraction, PermissionFlagsBits } from 'discord.js'; import Fuse from 'fuse.js'; import got from 'got'; diff --git a/src/commands/utilities/highlight-!.ts b/src/commands/utilities/highlight-!.ts index 332af03..687990f 100644 --- a/src/commands/utilities/highlight-!.ts +++ b/src/commands/utilities/highlight-!.ts @@ -1,6 +1,6 @@ import { BushCommand, Highlight, HighlightWord, type BushSlashMessage } from '#lib'; import { Flag, type ArgumentGeneratorReturn, type SlashOption } from 'discord-akairo'; -import { ApplicationCommandOptionType } from 'discord-api-types'; +import { ApplicationCommandOptionType } from 'discord-api-types/v9'; import { ApplicationCommandSubCommandData, AutocompleteInteraction, CacheType } from 'discord.js'; type Unpacked<T> = T extends (infer U)[] ? U : T; diff --git a/src/commands/utilities/reminders.ts b/src/commands/utilities/reminders.ts index 509da67..10206c1 100644 --- a/src/commands/utilities/reminders.ts +++ b/src/commands/utilities/reminders.ts @@ -1,6 +1,6 @@ import { BushCommand, ButtonPaginator, Reminder, type BushMessage, type BushSlashMessage } from '#lib'; import assert from 'assert'; -import { APIEmbed } from 'discord-api-types'; +import { APIEmbed } from 'discord-api-types/v9'; import { PermissionFlagsBits } from 'discord.js'; import { Op } from 'sequelize'; diff --git a/src/lib/common/AutoMod.ts b/src/lib/common/AutoMod.ts index 784085d..9024260 100644 --- a/src/lib/common/AutoMod.ts +++ b/src/lib/common/AutoMod.ts @@ -156,6 +156,7 @@ export class AutoMod { ? [ new ActionRow().addComponents( new ButtonComponent() + // @ts-expect-error: outdated @discord.js/builders .setStyle(ButtonStyle.Danger) .setLabel('Ban User') .setCustomId(`automod;ban;${this.message.author.id};everyone mention and scam phrase`) @@ -277,6 +278,7 @@ export class AutoMod { ? [ new ActionRow().addComponents( new ButtonComponent() + // @ts-expect-error: outdated @discord.js/builders .setStyle(ButtonStyle.Danger) .setLabel('Ban User') .setCustomId(`automod;ban;${this.message.author.id};${highestOffence.reason}`) diff --git a/src/lib/common/ButtonPaginator.ts b/src/lib/common/ButtonPaginator.ts index 0399e74..09e059c 100644 --- a/src/lib/common/ButtonPaginator.ts +++ b/src/lib/common/ButtonPaginator.ts @@ -1,6 +1,6 @@ import { DeleteButton, type BushMessage, type BushSlashMessage } from '#lib'; import { CommandUtil } from 'discord-akairo'; -import { APIEmbed } from 'discord-api-types'; +import { APIEmbed } from 'discord-api-types/v9'; import { ActionRow, ActionRowComponent, ButtonComponent, ButtonStyle, Embed, type MessageComponentInteraction } from 'discord.js'; /** @@ -173,26 +173,31 @@ export class ButtonPaginator { protected getPaginationRow(disableAll = false): ActionRow<ActionRowComponent> { return new ActionRow().addComponents( new ButtonComponent() + // @ts-expect-error: outdated @discord.js/builders .setStyle(ButtonStyle.Primary) .setCustomId('paginate_beginning') .setEmoji(PaginateEmojis.BEGINNING) .setDisabled(disableAll || this.curPage === 0), new ButtonComponent() + // @ts-expect-error: outdated @discord.js/builders .setStyle(ButtonStyle.Primary) .setCustomId('paginate_back') .setEmoji(PaginateEmojis.BACK) .setDisabled(disableAll || this.curPage === 0), new ButtonComponent() + // @ts-expect-error: outdated @discord.js/builders .setStyle(ButtonStyle.Primary) .setCustomId('paginate_stop') .setEmoji(PaginateEmojis.STOP) .setDisabled(disableAll), new ButtonComponent() + // @ts-expect-error: outdated @discord.js/builders .setStyle(ButtonStyle.Primary) .setCustomId('paginate_next') .setEmoji(PaginateEmojis.FORWARD) .setDisabled(disableAll || this.curPage === this.embeds.length - 1), new ButtonComponent() + // @ts-expect-error: outdated @discord.js/builders .setStyle(ButtonStyle.Primary) .setCustomId('paginate_end') .setEmoji(PaginateEmojis.END) diff --git a/src/lib/common/ConfirmationPrompt.ts b/src/lib/common/ConfirmationPrompt.ts index bd11c5c..1f027ef 100644 --- a/src/lib/common/ConfirmationPrompt.ts +++ b/src/lib/common/ConfirmationPrompt.ts @@ -31,11 +31,13 @@ export class ConfirmationPrompt { this.messageOptions.components = [ new ActionRow().addComponents( new ButtonComponent() + // @ts-expect-error: outdated @discord.js/builders .setStyle(ButtonStyle.Primary) .setCustomId('confirmationPrompt_confirm') .setEmoji({ id: util.emojisRaw.successFull, name: 'successFull', animated: false }) .setLabel('Yes'), new ButtonComponent() + // @ts-expect-error: outdated @discord.js/builders .setStyle(ButtonStyle.Danger) .setCustomId('confirmationPrompt_cancel') .setEmoji({ id: util.emojisRaw.errorFull, name: 'errorFull', animated: false }) diff --git a/src/lib/common/DeleteButton.ts b/src/lib/common/DeleteButton.ts index cf3b416..f2e0ff3 100644 --- a/src/lib/common/DeleteButton.ts +++ b/src/lib/common/DeleteButton.ts @@ -68,6 +68,7 @@ export class DeleteButton { this.messageOptions.components = [ new ActionRow().addComponents( new ButtonComponent() + // @ts-expect-error: outdated @discord.js/builders .setStyle(ButtonStyle.Primary) .setCustomId('paginate__stop') .setEmoji(PaginateEmojis.STOP) diff --git a/src/lib/common/util/Moderation.ts b/src/lib/common/util/Moderation.ts index 0ba6fca..c2236ab 100644 --- a/src/lib/common/util/Moderation.ts +++ b/src/lib/common/util/Moderation.ts @@ -10,7 +10,33 @@ import { type BushUserResolvable, type ModLogType } from '#lib'; -import { Embed, PermissionFlagsBits, type Snowflake } from 'discord.js'; +import assert from 'assert'; +import { ActionRow, ButtonComponent, ButtonStyle, ComponentType, Embed, PermissionFlagsBits, type Snowflake } from 'discord.js'; + +enum punishMap { + 'warned' = 'warn', + 'muted' = 'mute', + 'unmuted' = 'unmute', + 'kicked' = 'kick', + 'banned' = 'ban', + 'unbanned' = 'unban', + 'timedout' = 'timeout', + 'untimedout' = 'untimeout', + 'blocked' = 'block', + 'unblocked' = 'unblock' +} +enum reversedPunishMap { + 'warn' = 'warned', + 'mute' = 'muted', + 'unmute' = 'unmuted', + 'kick' = 'kicked', + 'ban' = 'banned', + 'unban' = 'unbanned', + 'timeout' = 'timedout', + 'untimeout' = 'untimedout', + 'block' = 'blocked', + 'unblock' = 'unblocked' +} /** * A utility class with moderation-related methods. @@ -204,6 +230,19 @@ export class Moderation { return typeMap[type]; } + public static punishmentToPresentTense(punishment: PunishmentTypeDM): PunishmentTypePresent { + return punishMap[punishment]; + } + + public static punishmentToPastTense(punishment: PunishmentTypePresent): PunishmentTypeDM { + return reversedPunishMap[punishment]; + } + + /** + * Notifies the specified user of their punishment. + * @param options Options for notifying the user. + * @returns Whether or not the dm was successfully sent. + */ public static async punishDM(options: PunishDMOptions): Promise<boolean> { const ending = await options.guild.getSetting('punishmentEnding'); const dmEmbed = @@ -211,16 +250,45 @@ export class Moderation { ? new Embed().setDescription(ending).setColor(util.colors.newBlurple) : undefined; + const appealsEnabled = !!( + (await options.guild.hasFeature('punishmentAppeals')) && (await options.guild.getLogChannel('appeals')) + ); + + let content = `You have been ${options.punishment} `; + if (options.punishment.includes('blocked')) { + assert(options.channel); + content += `from <#${options.channel}> `; + } + content += `in ${util.format.input(options.guild.name)} `; + if (options.duration !== null && options.duration !== undefined) + content += options.duration ? `for ${util.humanizeDuration(options.duration)} ` : 'permanently '; + const reason = options.reason?.trim() ? options.reason?.trim() : 'No reason provided'; + content += `for ${util.format.input(reason)}.`; + + let components; + if (appealsEnabled && options.modlog) + components = [ + new ActionRow({ + type: ComponentType.ActionRow, + components: [ + // @ts-expect-error: outdated @discord.js/builders + new ButtonComponent({ + custom_id: `appeal;${this.punishmentToPresentTense(options.punishment)};${ + options.guild.id + };${client.users.resolveId(options.user)};${options.modlog}`, + style: ButtonStyle.Primary, + type: ComponentType.Button, + label: 'Appeal' + }) + ] + }) + ]; + const dmSuccess = await client.users .send(options.user, { - content: `You have been ${options.punishment} in **${options.guild.name}** ${ - options.duration !== null && options.duration !== undefined - ? options.duration - ? `for ${util.humanizeDuration(options.duration)} ` - : 'permanently ' - : '' - }for **${options.reason?.trim() ? options.reason?.trim() : 'No reason provided'}**.`, - embeds: dmEmbed ? [dmEmbed] : undefined + content, + embeds: dmEmbed ? [dmEmbed] : undefined, + components }) .catch(() => false); return !!dmSuccess; @@ -342,6 +410,11 @@ export interface RemovePunishmentEntryOptions { */ export interface PunishDMOptions { /** + * The modlog case id so the user can make an appeal. + */ + modlog?: string; + + /** * The guild that the punishment is taking place in. */ guild: BushGuild; @@ -354,7 +427,7 @@ export interface PunishDMOptions { /** * The punishment that the user has received. */ - punishment: string; + punishment: PunishmentTypeDM; /** * The reason the user's punishment. @@ -371,4 +444,35 @@ export interface PunishDMOptions { * @default true */ sendFooter: boolean; + + /** + * The channel that the user was (un)blocked from. + */ + channel?: Snowflake; } + +export type PunishmentTypeDM = + | 'warned' + | 'muted' + | 'unmuted' + | 'kicked' + | 'banned' + | 'unbanned' + | 'timedout' + | 'untimedout' + | 'blocked' + | 'unblocked'; + +export type PunishmentTypePresent = + | 'warn' + | 'mute' + | 'unmute' + | 'kick' + | 'ban' + | 'unban' + | 'timeout' + | 'untimeout' + | 'block' + | 'unblock'; + +export type AppealButtonId = `appeal;${PunishmentTypePresent};${Snowflake};${Snowflake};${string}`; diff --git a/src/lib/extensions/discord-akairo/BushClientUtil.ts b/src/lib/extensions/discord-akairo/BushClientUtil.ts index 41d16f7..bf4dfaf 100644 --- a/src/lib/extensions/discord-akairo/BushClientUtil.ts +++ b/src/lib/extensions/discord-akairo/BushClientUtil.ts @@ -21,7 +21,7 @@ import assert from 'assert'; import { exec } from 'child_process'; import deepLock from 'deep-lock'; import { ClientUtil, Util as AkairoUtil } from 'discord-akairo'; -import { APIMessage } from 'discord-api-types'; +import type { APIMessage } from 'discord-api-types/v9'; import { Constants as DiscordConstants, GuildMember, diff --git a/src/lib/extensions/discord-akairo/BushCommand.ts b/src/lib/extensions/discord-akairo/BushCommand.ts index 650b538..ff3748e 100644 --- a/src/lib/extensions/discord-akairo/BushCommand.ts +++ b/src/lib/extensions/discord-akairo/BushCommand.ts @@ -44,7 +44,7 @@ import { type ContextMenuCommand, type MissingPermissionSupplier, type SlashOption, - type SlashResolveTypes + type SlashResolveType } from 'discord-akairo'; import { type ApplicationCommandOptionChoice, @@ -147,7 +147,7 @@ interface BaseBushArgumentOptions extends Omit<ArgumentOptions, 'type' | 'prompt * * ex. get the resolved member object when the type is `USER` */ - slashResolve?: SlashResolveTypes; + slashResolve?: SlashResolveType; /** * The choices of the option for the user to pick from @@ -340,7 +340,7 @@ export interface ArgsInfo { description: string; optional?: boolean; slashType: AkairoApplicationCommandOptionData['type'] | false; - slashResolve?: SlashResolveTypes; + slashResolve?: SlashResolveType; only?: 'slash' | 'text'; type: string; } diff --git a/src/lib/extensions/discord.js/BushGuild.ts b/src/lib/extensions/discord.js/BushGuild.ts index 93875b8..80799fd 100644 --- a/src/lib/extensions/discord.js/BushGuild.ts +++ b/src/lib/extensions/discord.js/BushGuild.ts @@ -173,8 +173,22 @@ export class BushGuild extends Guild { if ((await this.bans.fetch()).has(user.id)) return banResponse.ALREADY_BANNED; const ret = await (async () => { + // add modlog entry + const { log: modlog } = await Moderation.createModLogEntry({ + type: options.duration ? ModLogType.TEMP_BAN : ModLogType.PERM_BAN, + user: user, + moderator: moderator.id, + reason: options.reason, + duration: options.duration, + guild: this, + evidence: options.evidence + }); + if (!modlog) return banResponse.MODLOG_ERROR; + caseID = modlog.id; + // dm user dmSuccessEvent = await Moderation.punishDM({ + modlog: modlog.id, guild: this, user: user, punishment: 'banned', @@ -187,24 +201,11 @@ export class BushGuild extends Guild { const banSuccess = await this.bans .create(user?.id ?? options.user, { reason: `${moderator.tag} | ${options.reason ?? 'No reason provided.'}`, - days: options.deleteDays + deleteMessageDays: options.deleteDays }) .catch(() => false); if (!banSuccess) return banResponse.ACTION_ERROR; - // add modlog entry - const { log: modlog } = await Moderation.createModLogEntry({ - type: options.duration ? ModLogType.TEMP_BAN : ModLogType.PERM_BAN, - user: user, - moderator: moderator.id, - reason: options.reason, - duration: options.duration, - guild: this, - evidence: options.evidence - }); - if (!modlog) return banResponse.MODLOG_ERROR; - caseID = modlog.id; - // add punishment entry so they can be unbanned later const punishmentEntrySuccess = await Moderation.createPunishmentEntry({ type: 'ban', diff --git a/src/lib/extensions/discord.js/BushGuildMember.ts b/src/lib/extensions/discord.js/BushGuildMember.ts index 84fdf13..5d7144b 100644 --- a/src/lib/extensions/discord.js/BushGuildMember.ts +++ b/src/lib/extensions/discord.js/BushGuildMember.ts @@ -3,6 +3,8 @@ import { BushClientEvents, Moderation, ModLogType, |
