From 52a446838bfd55d88f8b3a5f7e4dd7fbd490986b Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Wed, 13 May 2026 04:28:18 -0600 Subject: [PATCH 01/12] Fix node requirement --- CHANGELOG.md | 2 +- README.md | 2 +- package-lock.json | 2 +- package.json | 8 +------- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 113e5871..8bfcf58a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update dependencies - Modernize TypeScript and ESLint configurations - Refactor GitHub workflows -- **Breaking:** set minimum Node version to 22.18.0 +- **Breaking:** set minimum Node version to `^22.18.0 || >=24.0.0` - **Breaking:** upgrade to Node 24 - Replace `nodemon` with `node --watch` for the `npm run dev` script - Use `clientReady` event instead of `ready` to fix deprecation warning diff --git a/README.md b/README.md index 84aef27d..6e7c5be0 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ If you've read this far, and don't plan to run or develop on the bot yourself, o ### Prerequisites -This project requires [NodeJS](https://nodejs.org/) (version 22.12.0 or later) and [NPM](https://npmjs.org/). To make sure you have them available on your machine, try running the following command: +This project requires [NodeJS](https://nodejs.org/) and [NPM](https://npmjs.org/). To make sure you have them available on your machine, try running the following command: ```sh $ node -v && npm -v diff --git a/package-lock.json b/package-lock.json index 45cf8574..ea006aee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,7 +45,7 @@ "vitest-mock-extended": "4.0.0" }, "engines": { - "node": ">=22.18.0" + "node": "^22.18.0 || >=24.0.0" } }, "node_modules/@aashutoshrathi/word-wrap": { diff --git a/package.json b/package.json index 70ce1a84..e6ab33f1 100644 --- a/package.json +++ b/package.json @@ -80,12 +80,6 @@ "vitest-mock-extended": "4.0.0" }, "engines": { - "node": ">=22.18.0" - }, - "devEngines": { - "runtime": { - "name": "node", - "version": ">=22.18.0" - } + "node": "^22.18.0 || >=24.0.0" } } From c1b69c8c74718549b17efead4d8d7c489c3b9caa Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Wed, 13 May 2026 04:38:11 -0600 Subject: [PATCH 02/12] Rewrite all internal imports from .js to .ts --- src/__mocks__/logger.ts | 2 +- src/buttons/hangmanLessButton.test.ts | 2 +- src/buttons/hangmanLessButton.ts | 2 +- src/buttons/hangmanLetterButton.test.ts | 4 +-- src/buttons/hangmanLetterButton.ts | 6 ++-- src/buttons/hangmanMoreButton.test.ts | 2 +- src/buttons/hangmanMoreButton.ts | 4 +-- src/buttons/index.test.ts | 2 +- src/buttons/index.ts | 6 ++-- src/commandContext/followUp.test.ts | 10 +++---- src/commandContext/followUp.ts | 4 +-- .../prepareForLongRunningTasks.test.ts | 6 ++-- .../prepareForLongRunningTasks.ts | 2 +- src/commandContext/reply.test.ts | 6 ++-- src/commandContext/reply.ts | 4 +-- src/commandContext/replyPrivately.test.ts | 10 +++---- src/commandContext/replyPrivately.ts | 6 ++-- src/commandContext/sendTyping.test.ts | 4 +-- src/commandContext/sendTyping.ts | 2 +- src/commands/contextMenu/altText.test.ts | 2 +- src/commands/contextMenu/altText.ts | 2 +- src/commands/contextMenu/fxtwitter.test.ts | 2 +- src/commands/contextMenu/fxtwitter.ts | 2 +- src/commands/contextMenu/talk.test.ts | 8 ++--- src/commands/contextMenu/talk.ts | 2 +- src/commands/emoji.test.ts | 4 +-- src/commands/emoji.ts | 2 +- src/commands/findRoom.test.ts | 6 ++-- src/commands/findRoom.ts | 4 +-- src/commands/help.test.ts | 6 ++-- src/commands/help.ts | 2 +- src/commands/index.test.ts | 2 +- src/commands/index.ts | 30 +++++++++---------- src/commands/isCasDown.test.ts | 2 +- src/commands/profile.test.ts | 6 ++-- src/commands/profile.ts | 2 +- src/commands/sendtag.test.ts | 2 +- src/commands/setReactboard.test.ts | 6 ++-- src/commands/setReactboard.ts | 4 +-- src/commands/stats.test.ts | 10 +++---- src/commands/stats.ts | 6 ++-- src/commands/talk.test.ts | 4 +-- src/commands/talk.ts | 2 +- src/commands/toTheGallows.test.ts | 6 ++-- src/commands/toTheGallows.ts | 4 +-- src/commands/xkcd.test.ts | 12 ++++---- src/commands/xkcd.ts | 6 ++-- src/constants/meta.ts | 2 +- src/events/clientReady.test.ts | 18 +++++------ src/events/clientReady.ts | 16 +++++----- src/events/error.test.ts | 6 ++-- src/events/error.ts | 4 +-- src/events/index.test.ts | 4 +-- src/events/index.ts | 12 ++++---- src/events/interactionCreate.test.ts | 12 ++++---- src/events/interactionCreate.ts | 24 +++++++-------- src/events/messageReaction.test.ts | 2 +- src/events/messageReactionAdd.ts | 6 ++-- src/events/messageReactionRemove.ts | 6 ++-- src/evilHangman/evilHangmanAsciiArt.test.ts | 2 +- src/evilHangman/evilHangmanGame.test.ts | 2 +- src/evilHangman/evilHangmanGame.ts | 6 ++-- src/evilHangman/evilHangmanMessage.test.ts | 4 +-- src/evilHangman/evilHangmanMessage.ts | 18 +++++------ src/evilHangman/gameInfoParser.ts | 2 +- src/evilHangman/hangmanLetterButtons.test.ts | 2 +- src/evilHangman/hangmanLetterButtons.ts | 4 +-- .../parseEvilHangmanMessage.test.ts | 2 +- src/evilHangman/parseEvilHangmanMessage.ts | 4 +-- src/helpers/NetworkError.ts | 4 +-- src/helpers/actions/deployCommands.test.ts | 10 +++---- src/helpers/actions/deployCommands.ts | 8 ++--- .../actions/messages/replyToMessage.test.ts | 6 ++-- .../actions/messages/replyToMessage.ts | 4 +-- src/helpers/actions/revokeCommands.test.ts | 4 +-- src/helpers/actions/revokeCommands.ts | 2 +- .../actions/verifyCommandDeployments.test.ts | 8 ++--- .../actions/verifyCommandDeployments.ts | 4 +-- src/helpers/fetch.test.ts | 6 ++-- src/helpers/fetch.ts | 4 +-- src/helpers/format.test.ts | 2 +- src/helpers/guards/isError.test.ts | 2 +- src/helpers/guards/isNonEmptyArray.test.ts | 2 +- src/helpers/logUser.test.ts | 2 +- src/helpers/onEvent.test.ts | 2 +- src/helpers/parseArgs.test.ts | 2 +- src/helpers/positionsOfUriInText.test.ts | 4 +-- src/logger.ts | 2 +- src/main.test.ts | 10 +++---- src/main.ts | 4 +-- src/reactionHandlers/add.test.ts | 2 +- src/reactionHandlers/add.ts | 4 +-- src/reactionHandlers/duplicate.test.ts | 4 +-- src/reactionHandlers/duplicate.ts | 4 +-- src/reactionHandlers/remove.test.ts | 2 +- src/reactionHandlers/remove.ts | 2 +- src/reactionHandlers/updateReactboard.test.ts | 6 ++-- src/reactionHandlers/updateReactboard.ts | 4 +-- tsconfig.json | 1 + 99 files changed, 255 insertions(+), 254 deletions(-) diff --git a/src/__mocks__/logger.ts b/src/__mocks__/logger.ts index cfbd50a2..470c8cd8 100644 --- a/src/__mocks__/logger.ts +++ b/src/__mocks__/logger.ts @@ -1,6 +1,6 @@ import { vi } from 'vitest'; -import type * as logger from '../logger.js'; +import type * as logger from '../logger.ts'; /** * The mock function serving as the `debug` method of the logger. diff --git a/src/buttons/hangmanLessButton.test.ts b/src/buttons/hangmanLessButton.test.ts index 850526e7..9d66d622 100644 --- a/src/buttons/hangmanLessButton.test.ts +++ b/src/buttons/hangmanLessButton.test.ts @@ -1,6 +1,6 @@ import { assert, beforeEach, describe, expect, test, vi } from 'vitest'; -import { hangmanLessButton } from './hangmanLessButton.js'; +import { hangmanLessButton } from './hangmanLessButton.ts'; describe('hangmanLessButton', () => { const mockUpdate = vi.fn(); diff --git a/src/buttons/hangmanLessButton.ts b/src/buttons/hangmanLessButton.ts index 8898b108..b8464069 100644 --- a/src/buttons/hangmanLessButton.ts +++ b/src/buttons/hangmanLessButton.ts @@ -1,7 +1,7 @@ import { ButtonBuilder } from '@discordjs/builders'; import { ButtonStyle } from 'discord.js'; -import { parseEvilHangmanMessage } from '../evilHangman/parseEvilHangmanMessage.js'; +import { parseEvilHangmanMessage } from '../evilHangman/parseEvilHangmanMessage.ts'; const customId = 'hangmanLessButton'; export const hangmanLessButton: Button = { diff --git a/src/buttons/hangmanLetterButton.test.ts b/src/buttons/hangmanLetterButton.test.ts index 72c0b17f..45108b78 100644 --- a/src/buttons/hangmanLetterButton.test.ts +++ b/src/buttons/hangmanLetterButton.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; -import { letterButtons } from '../evilHangman/hangmanLetterButtons.js'; -import { UserMessageError } from '../helpers/UserMessageError.js'; +import { letterButtons } from '../evilHangman/hangmanLetterButtons.ts'; +import { UserMessageError } from '../helpers/UserMessageError.ts'; describe('hangmanMoreButton', () => { const mockUpdate = vi.fn(); diff --git a/src/buttons/hangmanLetterButton.ts b/src/buttons/hangmanLetterButton.ts index 6fe0b91a..d08f0400 100644 --- a/src/buttons/hangmanLetterButton.ts +++ b/src/buttons/hangmanLetterButton.ts @@ -1,7 +1,7 @@ import { ButtonBuilder, ButtonStyle } from 'discord.js'; -import { parseEvilHangmanMessage } from '../evilHangman/parseEvilHangmanMessage.js'; -import { UserMessageError } from '../helpers/UserMessageError.js'; +import { parseEvilHangmanMessage } from '../evilHangman/parseEvilHangmanMessage.ts'; +import { UserMessageError } from '../helpers/UserMessageError.ts'; export type Letter = | 'a' @@ -36,7 +36,7 @@ export function hangmanLetterButton(letter: Letter): Button { return { customId, async execute({ interaction, message }): Promise { - const { buildEvilHangmanMessage } = await import('../evilHangman/evilHangmanMessage.js'); + const { buildEvilHangmanMessage } = await import('../evilHangman/evilHangmanMessage.ts'); const game = parseEvilHangmanMessage(message); const guessErrorMessage = game.checkGuess(letter); diff --git a/src/buttons/hangmanMoreButton.test.ts b/src/buttons/hangmanMoreButton.test.ts index 27426c0a..5b9d1848 100644 --- a/src/buttons/hangmanMoreButton.test.ts +++ b/src/buttons/hangmanMoreButton.test.ts @@ -1,6 +1,6 @@ import { assert, beforeEach, describe, expect, test, vi } from 'vitest'; -import { hangmanMoreButton } from './hangmanMoreButton.js'; +import { hangmanMoreButton } from './hangmanMoreButton.ts'; describe('hangmanMoreButton', () => { const mockUpdate = vi.fn(); diff --git a/src/buttons/hangmanMoreButton.ts b/src/buttons/hangmanMoreButton.ts index b2c8a4f2..a71ade1e 100644 --- a/src/buttons/hangmanMoreButton.ts +++ b/src/buttons/hangmanMoreButton.ts @@ -1,13 +1,13 @@ import { ButtonBuilder } from '@discordjs/builders'; import { ButtonStyle } from 'discord.js'; -import { parseEvilHangmanMessage } from '../evilHangman/parseEvilHangmanMessage.js'; +import { parseEvilHangmanMessage } from '../evilHangman/parseEvilHangmanMessage.ts'; const customId = 'hangmanMoreButton'; export const hangmanMoreButton: Button = { customId, async execute({ message, interaction }): Promise { - const { buildEvilHangmanMessage } = await import('../evilHangman/evilHangmanMessage.js'); + const { buildEvilHangmanMessage } = await import('../evilHangman/evilHangmanMessage.ts'); const game = parseEvilHangmanMessage(message); const displayInfo = game.getDisplayInfo(); diff --git a/src/buttons/index.test.ts b/src/buttons/index.test.ts index 0316306f..d42bfda6 100644 --- a/src/buttons/index.test.ts +++ b/src/buttons/index.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { allButtons, _add } from './index.js'; +import { allButtons, _add } from './index.ts'; describe('allButtons', () => { test('index is not empty', () => { diff --git a/src/buttons/index.ts b/src/buttons/index.ts index 6b9a3492..00eedcf3 100644 --- a/src/buttons/index.ts +++ b/src/buttons/index.ts @@ -1,6 +1,6 @@ -import { letterButtons } from '../evilHangman/hangmanLetterButtons.js'; -import { hangmanLessButton } from './hangmanLessButton.js'; -import { hangmanMoreButton } from './hangmanMoreButton.js'; +import { letterButtons } from '../evilHangman/hangmanLetterButtons.ts'; +import { hangmanLessButton } from './hangmanLessButton.ts'; +import { hangmanMoreButton } from './hangmanMoreButton.ts'; /** * The private list of all buttons. You can use this to edit the list within this file. diff --git a/src/commandContext/followUp.test.ts b/src/commandContext/followUp.test.ts index 381da102..719e759e 100644 --- a/src/commandContext/followUp.test.ts +++ b/src/commandContext/followUp.test.ts @@ -3,15 +3,15 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import type { Message, RepliableInteraction } from 'discord.js'; -vi.mock('../helpers/actions/messages/replyToMessage.js'); -import { sendMessageInChannel } from '../helpers/actions/messages/replyToMessage.js'; +vi.mock('../helpers/actions/messages/replyToMessage.ts'); +import { sendMessageInChannel } from '../helpers/actions/messages/replyToMessage.ts'; const mockSendMessageInChannel = sendMessageInChannel as Mock; // Mock the logger to track output -vi.mock('../logger.js'); -import { error as mockLoggerError } from '../logger.js'; +vi.mock('../logger.ts'); +import { error as mockLoggerError } from '../logger.ts'; -import { followUpFactory as factory } from './followUp.js'; +import { followUpFactory as factory } from './followUp.ts'; describe('follow-up message', () => { const testMessage = { id: 'test-message' } as Message; diff --git a/src/commandContext/followUp.ts b/src/commandContext/followUp.ts index 85a1a86a..623b05d8 100644 --- a/src/commandContext/followUp.ts +++ b/src/commandContext/followUp.ts @@ -1,7 +1,7 @@ import type { InteractionReplyOptions, RepliableInteraction } from 'discord.js'; -import { sendMessageInChannel } from '../helpers/actions/messages/replyToMessage.js'; -import { error } from '../logger.js'; +import { sendMessageInChannel } from '../helpers/actions/messages/replyToMessage.ts'; +import { error } from '../logger.ts'; export function followUpFactory(interaction: RepliableInteraction): CommandContext['followUp'] { return async function followUp(options) { diff --git a/src/commandContext/prepareForLongRunningTasks.test.ts b/src/commandContext/prepareForLongRunningTasks.test.ts index ea3b0995..20995b61 100644 --- a/src/commandContext/prepareForLongRunningTasks.test.ts +++ b/src/commandContext/prepareForLongRunningTasks.test.ts @@ -3,10 +3,10 @@ import { describe, expect, test, vi } from 'vitest'; import type { RepliableInteraction } from 'discord.js'; // Mock the logger to track output -vi.mock('../logger.js'); -import { error as mockLoggerError } from '../logger.js'; +vi.mock('../logger.ts'); +import { error as mockLoggerError } from '../logger.ts'; -import { prepareForLongRunningTasksFactory as factory } from './prepareForLongRunningTasks.js'; +import { prepareForLongRunningTasksFactory as factory } from './prepareForLongRunningTasks.ts'; describe('prepareForLongRunningTasks', () => { const mockInteractionDeferReply = vi.fn(); diff --git a/src/commandContext/prepareForLongRunningTasks.ts b/src/commandContext/prepareForLongRunningTasks.ts index 65692195..821bd12b 100644 --- a/src/commandContext/prepareForLongRunningTasks.ts +++ b/src/commandContext/prepareForLongRunningTasks.ts @@ -1,6 +1,6 @@ import type { RepliableInteraction } from 'discord.js'; -import { error } from '../logger.js'; +import { error } from '../logger.ts'; export function prepareForLongRunningTasksFactory( interaction: RepliableInteraction diff --git a/src/commandContext/reply.test.ts b/src/commandContext/reply.test.ts index 4dda6ad9..e947ee3b 100644 --- a/src/commandContext/reply.test.ts +++ b/src/commandContext/reply.test.ts @@ -3,10 +3,10 @@ import { describe, expect, test, vi } from 'vitest'; import type { RepliableInteraction } from 'discord.js'; // Mock the logger to track output -vi.mock('../logger.js'); -import { error as mockLoggerError } from '../logger.js'; +vi.mock('../logger.ts'); +import { error as mockLoggerError } from '../logger.ts'; -import { replyFactory as factory } from './reply.js'; +import { replyFactory as factory } from './reply.ts'; describe('public reply', () => { const mockInteractionReply = vi.fn(); diff --git a/src/commandContext/reply.ts b/src/commandContext/reply.ts index 24bb8ff3..dd6b1b6c 100644 --- a/src/commandContext/reply.ts +++ b/src/commandContext/reply.ts @@ -1,7 +1,7 @@ import type { InteractionReplyOptions, RepliableInteraction } from 'discord.js'; -import { logUser } from '../helpers/logUser.js'; -import { error, info } from '../logger.js'; +import { logUser } from '../helpers/logUser.ts'; +import { error, info } from '../logger.ts'; export function replyFactory(interaction: RepliableInteraction): CommandContext['reply'] { return async function reply(options) { diff --git a/src/commandContext/replyPrivately.test.ts b/src/commandContext/replyPrivately.test.ts index f04a5306..ff984f37 100644 --- a/src/commandContext/replyPrivately.test.ts +++ b/src/commandContext/replyPrivately.test.ts @@ -3,15 +3,15 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import type { RepliableInteraction } from 'discord.js'; -vi.mock('../helpers/actions/messages/replyToMessage.js'); -import { replyWithPrivateMessage } from '../helpers/actions/messages/replyToMessage.js'; +vi.mock('../helpers/actions/messages/replyToMessage.ts'); +import { replyWithPrivateMessage } from '../helpers/actions/messages/replyToMessage.ts'; const mockSendDM = replyWithPrivateMessage as Mock; // Mock the logger to track output -vi.mock('../logger.js'); -import { info as mockLoggerInfo, error as mockLoggerError } from '../logger.js'; +vi.mock('../logger.ts'); +import { info as mockLoggerInfo, error as mockLoggerError } from '../logger.ts'; -import { replyPrivatelyFactory as factory } from './replyPrivately.js'; +import { replyPrivatelyFactory as factory } from './replyPrivately.ts'; describe('ephemeral and DM replies', () => { mockSendDM.mockResolvedValue(true); diff --git a/src/commandContext/replyPrivately.ts b/src/commandContext/replyPrivately.ts index d1d868c1..ebb4465e 100644 --- a/src/commandContext/replyPrivately.ts +++ b/src/commandContext/replyPrivately.ts @@ -1,8 +1,8 @@ import type { RepliableInteraction } from 'discord.js'; -import { replyWithPrivateMessage } from '../helpers/actions/messages/replyToMessage.js'; -import { logUser } from '../helpers/logUser.js'; -import { error, info } from '../logger.js'; +import { replyWithPrivateMessage } from '../helpers/actions/messages/replyToMessage.ts'; +import { logUser } from '../helpers/logUser.ts'; +import { error, info } from '../logger.ts'; export function replyPrivatelyFactory( interaction: RepliableInteraction diff --git a/src/commandContext/sendTyping.test.ts b/src/commandContext/sendTyping.test.ts index e58c0c06..ccab0132 100644 --- a/src/commandContext/sendTyping.test.ts +++ b/src/commandContext/sendTyping.test.ts @@ -4,9 +4,9 @@ import type { RepliableInteraction, TextBasedChannelFields } from 'discord.js'; import { ChannelType } from 'discord.js'; // Mock the logger so nothing is printed -vi.mock('../logger.js'); +vi.mock('../logger.ts'); -import { sendTypingFactory as factory } from './sendTyping.js'; +import { sendTypingFactory as factory } from './sendTyping.ts'; describe('typing indicator', () => { const mockSendTyping = vi.fn(); diff --git a/src/commandContext/sendTyping.ts b/src/commandContext/sendTyping.ts index 7763a4c2..f2f7fdda 100644 --- a/src/commandContext/sendTyping.ts +++ b/src/commandContext/sendTyping.ts @@ -1,7 +1,7 @@ import { PartialGroupDMChannel } from 'discord.js'; import type { RepliableInteraction } from 'discord.js'; -import { debug } from '../logger.js'; +import { debug } from '../logger.ts'; export function sendTypingFactory(interaction: RepliableInteraction): CommandContext['sendTyping'] { return function sendTyping() { diff --git a/src/commands/contextMenu/altText.test.ts b/src/commands/contextMenu/altText.test.ts index 5d5e3701..7c272333 100644 --- a/src/commands/contextMenu/altText.test.ts +++ b/src/commands/contextMenu/altText.test.ts @@ -3,7 +3,7 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import type { Attachment } from 'discord.js'; import { Collection } from 'discord.js'; -import { altText } from './altText.js'; +import { altText } from './altText.ts'; describe('Get Alt Text', () => { const mockReplyPrivately = vi.fn(); diff --git a/src/commands/contextMenu/altText.ts b/src/commands/contextMenu/altText.ts index 60f2e478..4be51429 100644 --- a/src/commands/contextMenu/altText.ts +++ b/src/commands/contextMenu/altText.ts @@ -1,7 +1,7 @@ import type { Attachment } from 'discord.js'; import { ApplicationCommandType, ContextMenuCommandBuilder } from 'discord.js'; -import { isNonEmptyArray } from '../../helpers/guards/isNonEmptyArray.js'; +import { isNonEmptyArray } from '../../helpers/guards/isNonEmptyArray.ts'; export const altText: MessageContextMenuCommand = { info: new ContextMenuCommandBuilder().setName('Get Alt Text'), diff --git a/src/commands/contextMenu/fxtwitter.test.ts b/src/commands/contextMenu/fxtwitter.test.ts index ff02516a..d2e7ee48 100644 --- a/src/commands/contextMenu/fxtwitter.test.ts +++ b/src/commands/contextMenu/fxtwitter.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; -import { fxtwitter } from './fxtwitter.js'; +import { fxtwitter } from './fxtwitter.ts'; describe('Fix Twitter Links', () => { const mockReplyPrivately = vi.fn(); diff --git a/src/commands/contextMenu/fxtwitter.ts b/src/commands/contextMenu/fxtwitter.ts index 61adc2b1..e14592cc 100644 --- a/src/commands/contextMenu/fxtwitter.ts +++ b/src/commands/contextMenu/fxtwitter.ts @@ -1,7 +1,7 @@ import { ApplicationCommandType, ContextMenuCommandBuilder } from 'discord.js'; import { URL } from 'node:url'; -import { positionsOfUriInText } from '../../helpers/positionsOfUriInText.js'; +import { positionsOfUriInText } from '../../helpers/positionsOfUriInText.ts'; const twitter = 'twitter.com'; const twitterPermutations = new Set([twitter, `www.${twitter}`]); diff --git a/src/commands/contextMenu/talk.test.ts b/src/commands/contextMenu/talk.test.ts index 52cc797c..e73c85b0 100644 --- a/src/commands/contextMenu/talk.test.ts +++ b/src/commands/contextMenu/talk.test.ts @@ -1,18 +1,18 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; -import type { speak } from '../talk.js'; +import type { speak } from '../talk.ts'; // Mock the talkMessage functionality const speakMock = vi.hoisted(() => vi.fn()); -vi.mock('../talk.js', () => ({ +vi.mock('../talk.ts', () => ({ speak: speakMock, })); // Mock the logger so nothing is printed -vi.mock('../../logger.js'); +vi.mock('../../logger.ts'); // Import the code to test -import { talk } from './talk.js'; +import { talk } from './talk.ts'; describe('Talk Context Menu Command', () => { let context: MessageContextMenuCommandContext; diff --git a/src/commands/contextMenu/talk.ts b/src/commands/contextMenu/talk.ts index 82210413..f23f340e 100644 --- a/src/commands/contextMenu/talk.ts +++ b/src/commands/contextMenu/talk.ts @@ -1,6 +1,6 @@ import { ApplicationCommandType, ContextMenuCommandBuilder } from 'discord.js'; -import { speak } from '../talk.js'; +import { speak } from '../talk.ts'; const builder = new ContextMenuCommandBuilder().setName('Talk'); diff --git a/src/commands/emoji.test.ts b/src/commands/emoji.test.ts index f3be259e..f544f97b 100644 --- a/src/commands/emoji.test.ts +++ b/src/commands/emoji.test.ts @@ -3,9 +3,9 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import type { GuildEmoji } from 'discord.js'; import { EmbedBuilder } from 'discord.js'; -import { emoji } from './emoji.js'; +import { emoji } from './emoji.ts'; -vi.mock('../logger.js'); +vi.mock('../logger.ts'); describe('profile', () => { const mockReply = vi.fn(); diff --git a/src/commands/emoji.ts b/src/commands/emoji.ts index d3ac23f5..442b6692 100644 --- a/src/commands/emoji.ts +++ b/src/commands/emoji.ts @@ -1,6 +1,6 @@ import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; -import { UserMessageError } from '../helpers/UserMessageError.js'; +import { UserMessageError } from '../helpers/UserMessageError.ts'; const EmojiName = 'emojiname'; const ShouldRespondEphemeral = 'respondephemeral'; diff --git a/src/commands/findRoom.test.ts b/src/commands/findRoom.test.ts index a8ce89dc..0e7ed9b0 100644 --- a/src/commands/findRoom.test.ts +++ b/src/commands/findRoom.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test, vi } from 'vitest'; -vi.mock('../constants/meta.js', async () => { +vi.mock('../constants/meta.ts', async () => { const { repo } = - await vi.importActual('../constants/meta.js'); + await vi.importActual('../constants/meta.ts'); return { // Version changes frequently, so use a consistent version number to test with: appVersion: 'X.X.X', @@ -10,7 +10,7 @@ vi.mock('../constants/meta.js', async () => { }; }); -import { convertTo12Hour } from './findRoom.js'; +import { convertTo12Hour } from './findRoom.ts'; describe('findRoom', () => { test('convertTo12Hour 8AM', () => { diff --git a/src/commands/findRoom.ts b/src/commands/findRoom.ts index 96f97bf3..08287e18 100644 --- a/src/commands/findRoom.ts +++ b/src/commands/findRoom.ts @@ -2,8 +2,8 @@ import { array, boolean, string, tuple, type as schema } from 'superstruct'; import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import { URL } from 'node:url'; -import { fetchJson } from '../helpers/fetch.js'; -import { error } from '../logger.js'; +import { fetchJson } from '../helpers/fetch.ts'; +import { error } from '../logger.ts'; const getRoomInfoResponse = schema({ busySince: string(), diff --git a/src/commands/help.test.ts b/src/commands/help.test.ts index 56e4da46..38758261 100644 --- a/src/commands/help.test.ts +++ b/src/commands/help.test.ts @@ -1,9 +1,9 @@ import type { EmbedBuilder } from 'discord.js'; import { beforeEach, describe, expect, test, vi } from 'vitest'; -vi.mock('../constants/meta.js', async () => { +vi.mock('../constants/meta.ts', async () => { const { repo } = - await vi.importActual('../constants/meta.js'); + await vi.importActual('../constants/meta.ts'); return { // Version changes frequently, so use a consistent version number to test with: appVersion: 'X.X.X', @@ -11,7 +11,7 @@ vi.mock('../constants/meta.js', async () => { }; }); -import { help } from './help.js'; +import { help } from './help.ts'; describe('help', () => { const mockReply = vi.fn(); diff --git a/src/commands/help.ts b/src/commands/help.ts index 293054d0..140c6c6f 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -1,6 +1,6 @@ import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; -import { appVersion, repo } from '../constants/meta.js'; +import { appVersion, repo } from '../constants/meta.ts'; const builder = new SlashCommandBuilder() .setName('help') diff --git a/src/commands/index.test.ts b/src/commands/index.test.ts index 1b5f0b0a..82454f79 100644 --- a/src/commands/index.test.ts +++ b/src/commands/index.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { _add, allCommands } from './index.js'; +import { _add, allCommands } from './index.ts'; describe('allCommands', () => { test('index is not empty', () => { diff --git a/src/commands/index.ts b/src/commands/index.ts index 4ac92508..4db046a4 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -29,21 +29,21 @@ export function _add(cmd: Command): void { } /** Install commands here: **/ -import { emoji } from './emoji.js'; -import { findRoom } from './findRoom.js'; -import { help } from './help.js'; -import { isCasDown } from './isCasDown.js'; -import { profile } from './profile.js'; -import { sendtag } from './sendtag.js'; -import { setReactboard } from './setReactboard.js'; -import { stats } from './stats.js'; -import { talk } from './talk.js'; -import { toTheGallows } from './toTheGallows.js'; -import { xkcd } from './xkcd.js'; - -import { altText } from './contextMenu/altText.js'; -import { fxtwitter } from './contextMenu/fxtwitter.js'; -import { talk as talk_context } from './contextMenu/talk.js'; +import { emoji } from './emoji.ts'; +import { findRoom } from './findRoom.ts'; +import { help } from './help.ts'; +import { isCasDown } from './isCasDown.ts'; +import { profile } from './profile.ts'; +import { sendtag } from './sendtag.ts'; +import { setReactboard } from './setReactboard.ts'; +import { stats } from './stats.ts'; +import { talk } from './talk.ts'; +import { toTheGallows } from './toTheGallows.ts'; +import { xkcd } from './xkcd.ts'; + +import { altText } from './contextMenu/altText.ts'; +import { fxtwitter } from './contextMenu/fxtwitter.ts'; +import { talk as talk_context } from './contextMenu/talk.ts'; _add(emoji); _add(findRoom); diff --git a/src/commands/isCasDown.test.ts b/src/commands/isCasDown.test.ts index 133f8c2c..c6e762b7 100644 --- a/src/commands/isCasDown.test.ts +++ b/src/commands/isCasDown.test.ts @@ -6,7 +6,7 @@ const fetchMock = vi.fn(); vi.stubGlobal('fetch', fetchMock); // Import the code to test -import { isCasDown } from './isCasDown.js'; +import { isCasDown } from './isCasDown.ts'; describe('isCasDown', () => { const mockReply = vi.fn(); diff --git a/src/commands/profile.test.ts b/src/commands/profile.test.ts index 407a22de..55e03449 100644 --- a/src/commands/profile.test.ts +++ b/src/commands/profile.test.ts @@ -3,10 +3,10 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import type { ClientUser, GuildMember, User, UserResolvable } from 'discord.js'; import { DiscordAPIError, EmbedBuilder, userMention } from 'discord.js'; -import { DiscordErrorCode } from '../helpers/DiscordErrorCode.js'; -import { profile } from './profile.js'; +import { DiscordErrorCode } from '../helpers/DiscordErrorCode.ts'; +import { profile } from './profile.ts'; -vi.mock('../logger.js'); +vi.mock('../logger.ts'); describe('profile', () => { const mockReply = vi.fn(); diff --git a/src/commands/profile.ts b/src/commands/profile.ts index ac481838..3488a71e 100644 --- a/src/commands/profile.ts +++ b/src/commands/profile.ts @@ -1,7 +1,7 @@ import type { User } from 'discord.js'; import { DiscordAPIError, EmbedBuilder, SlashCommandBuilder, userMention } from 'discord.js'; -import { DiscordErrorCode } from '../helpers/DiscordErrorCode.js'; +import { DiscordErrorCode } from '../helpers/DiscordErrorCode.ts'; const UserParamName = 'user'; diff --git a/src/commands/sendtag.test.ts b/src/commands/sendtag.test.ts index b2385c32..459e6723 100644 --- a/src/commands/sendtag.test.ts +++ b/src/commands/sendtag.test.ts @@ -2,7 +2,7 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import type { AutocompleteInteraction } from 'discord.js'; -import { sendtag } from './sendtag.js'; +import { sendtag } from './sendtag.ts'; describe('sendtag', () => { const mockReply = vi.fn(); diff --git a/src/commands/setReactboard.test.ts b/src/commands/setReactboard.test.ts index 566c499f..b24a294e 100644 --- a/src/commands/setReactboard.test.ts +++ b/src/commands/setReactboard.test.ts @@ -5,9 +5,9 @@ import { mockDeep } from 'vitest-mock-extended'; import type { PrismaClient } from '@prisma/client'; import type { TextChannel } from 'discord.js'; -import { setReactboard } from './setReactboard.js'; -import { db } from '../database/index.js'; -import { UserMessageError } from '../helpers/UserMessageError.js'; +import { setReactboard } from './setReactboard.ts'; +import { db } from '../database/index.ts'; +import { UserMessageError } from '../helpers/UserMessageError.ts'; vi.mock('../database', () => ({ db: mockDeep(), diff --git a/src/commands/setReactboard.ts b/src/commands/setReactboard.ts index 926160ac..aee2c546 100644 --- a/src/commands/setReactboard.ts +++ b/src/commands/setReactboard.ts @@ -7,8 +7,8 @@ import { SlashCommandStringOption, } from 'discord.js'; -import { UserMessageError } from '../helpers/UserMessageError.js'; -import { db } from '../database/index.js'; +import { UserMessageError } from '../helpers/UserMessageError.ts'; +import { db } from '../database/index.ts'; const channelOption = 'channel'; const thresholdOption = 'threshold'; diff --git a/src/commands/stats.test.ts b/src/commands/stats.test.ts index 43398722..762c8a83 100644 --- a/src/commands/stats.test.ts +++ b/src/commands/stats.test.ts @@ -4,9 +4,9 @@ import { mockDeep } from 'vitest-mock-extended'; import type { PrismaClient, Scoreboard } from '@prisma/client'; -vi.mock('../constants/meta.js', async () => { +vi.mock('../constants/meta.ts', async () => { const { repo } = - await vi.importActual('../constants/meta.js'); + await vi.importActual('../constants/meta.ts'); return { // Version changes frequently, so use a consistent version number to test with: appVersion: 'X.X.X', @@ -14,12 +14,12 @@ vi.mock('../constants/meta.js', async () => { }; }); -vi.mock('../database', () => ({ +vi.mock('../database/index.ts', () => ({ db: mockDeep(), })); -import { stats } from './stats.js'; -import { db } from '../database/index.js'; +import { stats } from './stats.ts'; +import { db } from '../database/index.ts'; describe('stats', () => { const dbMock = db as DeepMockProxy; diff --git a/src/commands/stats.ts b/src/commands/stats.ts index 52c7bae6..a5ea1080 100644 --- a/src/commands/stats.ts +++ b/src/commands/stats.ts @@ -1,9 +1,9 @@ import type { ChatInputCommandInteraction } from 'discord.js'; import { EmbedBuilder, SlashCommandBuilder, userMention } from 'discord.js'; -import { db } from '../database/index.js'; -import { sanitize } from '../helpers/sanitize.js'; -import { UserMessageError } from '../helpers/UserMessageError.js'; +import { db } from '../database/index.ts'; +import { sanitize } from '../helpers/sanitize.ts'; +import { UserMessageError } from '../helpers/UserMessageError.ts'; const StatNameOption = 'statname'; const AmountOption = 'amount'; diff --git a/src/commands/talk.test.ts b/src/commands/talk.test.ts index 3a54c085..fec77c2b 100644 --- a/src/commands/talk.test.ts +++ b/src/commands/talk.test.ts @@ -8,10 +8,10 @@ const dectalkMock = vi.hoisted(() => vi.fn()); vi.mock('dectalk-tts', () => ({ default: dectalkMock })); // Mock the logger so nothing is printed -vi.mock('../logger'); +vi.mock('../logger.ts'); // Import the code to test -import { Speaker, talk } from './talk.js'; +import { Speaker, talk } from './talk.ts'; describe('Talk Slash Command', () => { const speakerMock = vi.fn<() => Speaker | null>(); diff --git a/src/commands/talk.ts b/src/commands/talk.ts index 03295e8a..afd76829 100644 --- a/src/commands/talk.ts +++ b/src/commands/talk.ts @@ -15,7 +15,6 @@ import dectalk from 'dectalk-tts'; import { writeFileSync, createReadStream } from 'node:fs'; import { fileSync } from 'tmp'; -import { info } from '../logger.js'; export enum Speaker { Paul = 'PAUL', @@ -28,6 +27,7 @@ export enum Speaker { Rita = 'RITA', Wendy = 'WENDY', } +import { info } from '../logger.ts'; const builder = new SlashCommandBuilder() .setName('talk') diff --git a/src/commands/toTheGallows.test.ts b/src/commands/toTheGallows.test.ts index 6494fd91..7b93cd4c 100644 --- a/src/commands/toTheGallows.test.ts +++ b/src/commands/toTheGallows.test.ts @@ -1,10 +1,10 @@ import { assert, beforeEach, describe, expect, test, vi } from 'vitest'; -import { toTheGallows } from './toTheGallows.js'; +import { toTheGallows } from './toTheGallows.ts'; -vi.mock('../constants/meta.js', async () => { +vi.mock('../constants/meta.ts', async () => { const { repo } = - await vi.importActual('../constants/meta.js'); + await vi.importActual('../constants/meta.ts'); return { // Version changes frequently, so use a consistent version number to test with: appVersion: 'X.X.X', diff --git a/src/commands/toTheGallows.ts b/src/commands/toTheGallows.ts index 660cd629..02066251 100644 --- a/src/commands/toTheGallows.ts +++ b/src/commands/toTheGallows.ts @@ -1,7 +1,7 @@ import { SlashCommandBuilder } from 'discord.js'; -import { EvilHangmanGame } from '../evilHangman/evilHangmanGame.js'; -import { buildEvilHangmanMessage } from '../evilHangman/evilHangmanMessage.js'; +import { EvilHangmanGame } from '../evilHangman/evilHangmanGame.ts'; +import { buildEvilHangmanMessage } from '../evilHangman/evilHangmanMessage.ts'; const LengthOption = 'wordlength'; const GuessesOption = 'numguesses'; diff --git a/src/commands/xkcd.test.ts b/src/commands/xkcd.test.ts index eeca92cb..c0b6a226 100644 --- a/src/commands/xkcd.test.ts +++ b/src/commands/xkcd.test.ts @@ -1,16 +1,16 @@ import type { Mock } from 'vitest'; import { beforeEach, describe, expect, test, vi } from 'vitest'; -import { fetchJson } from '../helpers/fetch.js'; -import { HttpStatusCode } from '../helpers/HttpStatusCode.js'; -import { NetworkError } from '../helpers/NetworkError.js'; +import { fetchJson } from '../helpers/fetch.ts'; +import { HttpStatusCode } from '../helpers/HttpStatusCode.ts'; +import { NetworkError } from '../helpers/NetworkError.ts'; -vi.mock('../helpers/fetch.js', () => ({ fetchJson: vi.fn() })); +vi.mock('../helpers/fetch.ts', () => ({ fetchJson: vi.fn() })); const mockedFetchJson = fetchJson as Mock; // Mock the logger so nothing is printed -vi.mock('../logger.js'); +vi.mock('../logger.ts'); const latestGood = { month: '9', @@ -44,7 +44,7 @@ const chosen = { const badResponse = new NetworkError(HttpStatusCode.BAD_REQUEST); // Import the code to test -import { xkcd } from './xkcd.js'; +import { xkcd } from './xkcd.ts'; describe('xkcd', () => { const mockReply = vi.fn(); diff --git a/src/commands/xkcd.ts b/src/commands/xkcd.ts index 9e2939e9..c4119246 100644 --- a/src/commands/xkcd.ts +++ b/src/commands/xkcd.ts @@ -2,9 +2,9 @@ import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import { URL } from 'node:url'; import { number, string, type as schema } from 'superstruct'; -import { fetchJson } from '../helpers/fetch.js'; -import { UserMessageError } from '../helpers/UserMessageError.js'; -import { error } from '../logger.js'; +import { fetchJson } from '../helpers/fetch.ts'; +import { UserMessageError } from '../helpers/UserMessageError.ts'; +import { error } from '../logger.ts'; const getComicResponse = schema({ month: string(), diff --git a/src/constants/meta.ts b/src/constants/meta.ts index cf02c06b..18030e40 100644 --- a/src/constants/meta.ts +++ b/src/constants/meta.ts @@ -6,4 +6,4 @@ import { URL } from 'node:url'; export const repo = new URL('https://github.com/BYU-CS-Discord/CSBot'); // If TS throws errors here, run `npm run lint` or `npm run export-version` -export { version as appVersion } from './version.js'; +export { version as appVersion } from './version.ts'; diff --git a/src/events/clientReady.test.ts b/src/events/clientReady.test.ts index b2c077a2..634100dc 100644 --- a/src/events/clientReady.test.ts +++ b/src/events/clientReady.test.ts @@ -4,32 +4,32 @@ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import type { Client } from 'discord.js'; // Mock parseArgs so we can control what the args are -import type { parseArgs } from '../helpers/parseArgs.js'; +import type { parseArgs } from '../helpers/parseArgs.ts'; const mockParseArgs = vi.hoisted(() => vi.fn()); vi.mock('../helpers/parseArgs', () => ({ parseArgs: mockParseArgs })); // Mock deployCommands so we can track it -vi.mock('../helpers/actions/deployCommands.js'); -import { deployCommands } from '../helpers/actions/deployCommands.js'; +vi.mock('../helpers/actions/deployCommands.ts'); +import { deployCommands } from '../helpers/actions/deployCommands.ts'; const mockDeployCommands = deployCommands as Mock; // Mock revokeCommands so we can track it -vi.mock('../helpers/actions/revokeCommands.js'); -import { revokeCommands } from '../helpers/actions/revokeCommands.js'; +vi.mock('../helpers/actions/revokeCommands.ts'); +import { revokeCommands } from '../helpers/actions/revokeCommands.ts'; const mockRevokeCommands = revokeCommands as Mock; // Mock verifyCommandDeployments so we can track it -vi.mock('../helpers/actions/verifyCommandDeployments.js'); -import { verifyCommandDeployments } from '../helpers/actions/verifyCommandDeployments.js'; +vi.mock('../helpers/actions/verifyCommandDeployments.ts'); +import { verifyCommandDeployments } from '../helpers/actions/verifyCommandDeployments.ts'; const mockVerifyCommandDeployments = verifyCommandDeployments as Mock< typeof verifyCommandDeployments >; // Mock the logger so nothing is printed -vi.mock('../logger.js'); +vi.mock('../logger.ts'); // Import the code to test -import { clientReady } from './clientReady.js'; +import { clientReady } from './clientReady.ts'; describe('once(clientReady)', () => { const client = { diff --git a/src/events/clientReady.ts b/src/events/clientReady.ts index 3ce37013..5f7dd29b 100644 --- a/src/events/clientReady.ts +++ b/src/events/clientReady.ts @@ -1,13 +1,13 @@ import { Events } from 'discord.js'; import { Worker } from 'node:worker_threads'; -import { appVersion } from '../constants/meta.js'; -import { deployCommands } from '../helpers/actions/deployCommands.js'; -import { revokeCommands } from '../helpers/actions/revokeCommands.js'; -import { onEvent } from '../helpers/onEvent.js'; -import { parseArgs } from '../helpers/parseArgs.js'; -import { verifyCommandDeployments } from '../helpers/actions/verifyCommandDeployments.js'; -import { info } from '../logger.js'; +import { appVersion } from '../constants/meta.ts'; +import { deployCommands } from '../helpers/actions/deployCommands.ts'; +import { revokeCommands } from '../helpers/actions/revokeCommands.ts'; +import { onEvent } from '../helpers/onEvent.ts'; +import { parseArgs } from '../helpers/parseArgs.ts'; +import { verifyCommandDeployments } from '../helpers/actions/verifyCommandDeployments.ts'; +import { info } from '../logger.ts'; /** * The event handler for when the Discord Client is ready for action @@ -41,7 +41,7 @@ export const clientReady = onEvent(Events.ClientReady, { const UPTIME_URL = process.env['UPTIME_URL']; if (UPTIME_URL) { const UPTIME_INTERVAL_SECONDS = process.env['UPTIME_INTERVAL_SECONDS']; - new Worker(new URL('../workers/uptime.js', import.meta.url), { + new Worker(new URL('../workers/uptime.ts', import.meta.url), { name: 'uptime-ping', env: { UPTIME_URL, UPTIME_INTERVAL_SECONDS }, }); diff --git a/src/events/error.test.ts b/src/events/error.test.ts index cee9c8fa..7a9fa6c2 100644 --- a/src/events/error.test.ts +++ b/src/events/error.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test, vi } from 'vitest'; // Mock the logger to track output -vi.mock('../logger.js'); -import { error as mockLoggerError } from '../logger.js'; +vi.mock('../logger.ts'); +import { error as mockLoggerError } from '../logger.ts'; // Import the code to test -import { error } from './error.js'; +import { error } from './error.ts'; // A basic error to test with const mockClientError = new Error('This is a test error'); diff --git a/src/events/error.ts b/src/events/error.ts index 86426f24..de1cf70a 100644 --- a/src/events/error.ts +++ b/src/events/error.ts @@ -1,7 +1,7 @@ import { Events } from 'discord.js'; -import { onEvent } from '../helpers/onEvent.js'; -import { error as logErr } from '../logger.js'; +import { onEvent } from '../helpers/onEvent.ts'; +import { error as logErr } from '../logger.ts'; /** * The event handler for Discord Client errors diff --git a/src/events/index.test.ts b/src/events/index.test.ts index ac955e7a..aa65c292 100644 --- a/src/events/index.test.ts +++ b/src/events/index.test.ts @@ -24,10 +24,10 @@ import { Client, Events } from 'discord.js'; const client = new Client({ intents: [] }); // Mock the logger so nothing is printed -vi.mock('../logger.js'); +vi.mock('../logger.ts'); // Import the code to test -import { _add, allEventHandlers, registerEventHandlers } from './index.js'; +import { _add, allEventHandlers, registerEventHandlers } from './index.ts'; describe('allEvents', () => { test('index is not empty', () => { diff --git a/src/events/index.ts b/src/events/index.ts index 1339672b..80cf53ca 100644 --- a/src/events/index.ts +++ b/src/events/index.ts @@ -1,6 +1,6 @@ import type { Client } from 'discord.js'; -import { info } from '../logger.js'; +import { info } from '../logger.ts'; /** * The private list of all event handlers. You can use this to edit the list within this file. @@ -53,11 +53,11 @@ export function registerEventHandlers(client: Client): void { } // Install event handlers -import { clientReady } from './clientReady.js'; -import { error } from './error.js'; -import { interactionCreate } from './interactionCreate.js'; -import { messageReactionAdd } from './messageReactionAdd.js'; -import { messageReactionRemove } from './messageReactionRemove.js'; +import { clientReady } from './clientReady.ts'; +import { error } from './error.ts'; +import { interactionCreate } from './interactionCreate.ts'; +import { messageReactionAdd } from './messageReactionAdd.ts'; +import { messageReactionRemove } from './messageReactionRemove.ts'; _add(clientReady as EventHandler); _add(error as EventHandler); diff --git a/src/events/interactionCreate.test.ts b/src/events/interactionCreate.test.ts index 8160b77e..e46f4811 100644 --- a/src/events/interactionCreate.test.ts +++ b/src/events/interactionCreate.test.ts @@ -17,11 +17,11 @@ import { SlashCommandBuilder, } from 'discord.js'; -import { UserMessageError } from '../helpers/UserMessageError.js'; +import { UserMessageError } from '../helpers/UserMessageError.ts'; // Mock allCommands to isolate our test code const mockAllCommands = vi.hoisted(() => new Map()); -vi.mock('../commands/index.js', () => ({ +vi.mock('../commands/index.ts', () => ({ allCommands: mockAllCommands, })); @@ -140,7 +140,7 @@ mockAllCommands.set(mockUserMessageErrorGlobalCommand.info.name, mockUserMessage // Mock allButtons to isolate our test code const mockAllButtons = vi.hoisted(() => new Map()); -vi.mock('../buttons/index.js', () => ({ +vi.mock('../buttons/index.ts', () => ({ allButtons: mockAllButtons, })); @@ -161,11 +161,11 @@ const mockErrorButton: Button = { mockAllButtons.set(mockErrorButton.customId, mockErrorButton); // Mock the logger to track output -vi.mock('../logger.js'); -import { error as mockLoggerError } from '../logger.js'; +vi.mock('../logger.ts'); +import { error as mockLoggerError } from '../logger.ts'; // Import the code to test -import { interactionCreate } from './interactionCreate.js'; +import { interactionCreate } from './interactionCreate.ts'; // Constants for testing const interactionError = new Error('Failed to handle interaction. This is a test.'); diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts index ec155104..4cb7e19e 100644 --- a/src/events/interactionCreate.ts +++ b/src/events/interactionCreate.ts @@ -9,18 +9,18 @@ import { EmbedBuilder, Colors, ApplicationCommandType, ChannelType, Events } fro import path from 'node:path'; import { fileURLToPath } from 'node:url'; -import { allButtons } from '../buttons/index.js'; -import { allCommands } from '../commands/index.js'; -import { followUpFactory } from '../commandContext/followUp.js'; -import { prepareForLongRunningTasksFactory } from '../commandContext/prepareForLongRunningTasks.js'; -import { replyFactory } from '../commandContext/reply.js'; -import { replyPrivatelyFactory } from '../commandContext/replyPrivately.js'; -import { sendTypingFactory } from '../commandContext/sendTyping.js'; -import { DISCORD_API_MAX_CHOICES } from '../constants/apiLimitations.js'; -import { logUser } from '../helpers/logUser.js'; -import { onEvent } from '../helpers/onEvent.js'; -import { UserMessageError } from '../helpers/UserMessageError.js'; -import { debug, error, warn } from '../logger.js'; +import { allButtons } from '../buttons/index.ts'; +import { allCommands } from '../commands/index.ts'; +import { followUpFactory } from '../commandContext/followUp.ts'; +import { prepareForLongRunningTasksFactory } from '../commandContext/prepareForLongRunningTasks.ts'; +import { replyFactory } from '../commandContext/reply.ts'; +import { replyPrivatelyFactory } from '../commandContext/replyPrivately.ts'; +import { sendTypingFactory } from '../commandContext/sendTyping.ts'; +import { DISCORD_API_MAX_CHOICES } from '../constants/apiLimitations.ts'; +import { logUser } from '../helpers/logUser.ts'; +import { onEvent } from '../helpers/onEvent.ts'; +import { UserMessageError } from '../helpers/UserMessageError.ts'; +import { debug, error, warn } from '../logger.ts'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); diff --git a/src/events/messageReaction.test.ts b/src/events/messageReaction.test.ts index 178eaa0c..af9b8790 100644 --- a/src/events/messageReaction.test.ts +++ b/src/events/messageReaction.test.ts @@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import type { MessageReaction, User } from 'discord.js'; -import { buildExecute } from './messageReaction.js'; +import { buildExecute } from './messageReaction.ts'; const mockHandlerExecute = vi.fn(); const mockReactionHandler = { diff --git a/src/events/messageReactionAdd.ts b/src/events/messageReactionAdd.ts index 443b8e07..f770f035 100644 --- a/src/events/messageReactionAdd.ts +++ b/src/events/messageReactionAdd.ts @@ -1,8 +1,8 @@ import { Events } from 'discord.js'; -import { onEvent } from '../helpers/onEvent.js'; -import { addReactionHandlers } from '../reactionHandlers/add.js'; -import { buildExecute } from './messageReaction.js'; +import { onEvent } from '../helpers/onEvent.ts'; +import { addReactionHandlers } from '../reactionHandlers/add.ts'; +import { buildExecute } from './messageReaction.ts'; /** * The event handler for emoji reactions. diff --git a/src/events/messageReactionRemove.ts b/src/events/messageReactionRemove.ts index 2e34bead..f45ae8c1 100644 --- a/src/events/messageReactionRemove.ts +++ b/src/events/messageReactionRemove.ts @@ -1,8 +1,8 @@ import { Events } from 'discord.js'; -import { onEvent } from '../helpers/onEvent.js'; -import { removeReactionHandlers } from '../reactionHandlers/remove.js'; -import { buildExecute } from './messageReaction.js'; +import { onEvent } from '../helpers/onEvent.ts'; +import { removeReactionHandlers } from '../reactionHandlers/remove.ts'; +import { buildExecute } from './messageReaction.ts'; /** * The event handler for when reactions are removed from messages. diff --git a/src/evilHangman/evilHangmanAsciiArt.test.ts b/src/evilHangman/evilHangmanAsciiArt.test.ts index 1bf1435f..d80e9f64 100644 --- a/src/evilHangman/evilHangmanAsciiArt.test.ts +++ b/src/evilHangman/evilHangmanAsciiArt.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { getHangmanArt } from './evilHangmanAsciiArt.js'; +import { getHangmanArt } from './evilHangmanAsciiArt.ts'; describe('evilHangmanAsciiArt.ts', () => { const tests = [ diff --git a/src/evilHangman/evilHangmanGame.test.ts b/src/evilHangman/evilHangmanGame.test.ts index f4afbabd..cbf2549d 100644 --- a/src/evilHangman/evilHangmanGame.test.ts +++ b/src/evilHangman/evilHangmanGame.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, test } from 'vitest'; -import { EvilHangmanGame, EvilHangmanWinState } from './evilHangmanGame.js'; +import { EvilHangmanGame, EvilHangmanWinState } from './evilHangmanGame.ts'; describe('EvilHangmanGame', () => { let game: EvilHangmanGame; diff --git a/src/evilHangman/evilHangmanGame.ts b/src/evilHangman/evilHangmanGame.ts index d6de5ae9..9ec15955 100644 --- a/src/evilHangman/evilHangmanGame.ts +++ b/src/evilHangman/evilHangmanGame.ts @@ -1,6 +1,6 @@ -import { isNonEmptyArray } from '../helpers/guards/isNonEmptyArray.js'; -import { UserMessageError } from '../helpers/UserMessageError.js'; -import { allWords } from './evilHangmanDictionary.js'; +import { isNonEmptyArray } from '../helpers/guards/isNonEmptyArray.ts'; +import { UserMessageError } from '../helpers/UserMessageError.ts'; +import { allWords } from './evilHangmanDictionary.ts'; export class EvilHangmanGame { private possibleWords: Array; diff --git a/src/evilHangman/evilHangmanMessage.test.ts b/src/evilHangman/evilHangmanMessage.test.ts index 7e01567a..509914a3 100644 --- a/src/evilHangman/evilHangmanMessage.test.ts +++ b/src/evilHangman/evilHangmanMessage.test.ts @@ -2,8 +2,8 @@ import { describe, expect, test } from 'vitest'; import type { EmbedBuilder } from '@discordjs/builders'; -import { EvilHangmanWinState } from './evilHangmanGame.js'; -import { buildEvilHangmanMessage } from './evilHangmanMessage.js'; +import { EvilHangmanWinState } from './evilHangmanGame.ts'; +import { buildEvilHangmanMessage } from './evilHangmanMessage.ts'; describe('evilHangmanMessage', () => { describe('buildEvilHangmanMessage', () => { diff --git a/src/evilHangman/evilHangmanMessage.ts b/src/evilHangman/evilHangmanMessage.ts index 755be408..707a2f4a 100644 --- a/src/evilHangman/evilHangmanMessage.ts +++ b/src/evilHangman/evilHangmanMessage.ts @@ -1,15 +1,15 @@ import type { ButtonBuilder, MessageReplyOptions } from 'discord.js'; import { ActionRowBuilder, EmbedBuilder } from 'discord.js'; -import { hangmanLessButton } from '../buttons/hangmanLessButton.js'; -import { hangmanMoreButton } from '../buttons/hangmanMoreButton.js'; -import { appVersion } from '../constants/meta.js'; -import { format } from '../helpers/format.js'; -import { getHangmanArt } from './evilHangmanAsciiArt.js'; -import type { EvilHangmanDisplayInfo } from './evilHangmanGame.js'; -import { EvilHangmanWinState } from './evilHangmanGame.js'; -import { GAME_INFO_FORMAT } from './gameInfoParser.js'; -import { getButtonsForAllLettersExcept } from './hangmanLetterButtons.js'; +import { hangmanLessButton } from '../buttons/hangmanLessButton.ts'; +import { hangmanMoreButton } from '../buttons/hangmanMoreButton.ts'; +import { appVersion } from '../constants/meta.ts'; +import { format } from '../helpers/format.ts'; +import { getHangmanArt } from './evilHangmanAsciiArt.ts'; +import type { EvilHangmanDisplayInfo } from './evilHangmanGame.ts'; +import { EvilHangmanWinState } from './evilHangmanGame.ts'; +import { GAME_INFO_FORMAT } from './gameInfoParser.ts'; +import { getButtonsForAllLettersExcept } from './hangmanLetterButtons.ts'; type Page = 0 | 1; export async function buildEvilHangmanMessage( diff --git a/src/evilHangman/gameInfoParser.ts b/src/evilHangman/gameInfoParser.ts index c59bbff5..14ece61c 100644 --- a/src/evilHangman/gameInfoParser.ts +++ b/src/evilHangman/gameInfoParser.ts @@ -1,4 +1,4 @@ -import { format } from '../helpers/format.js'; +import { format } from '../helpers/format.ts'; export const GAME_INFO_FORMAT = 'Remaining Guesses: {0}\nWord: {1}\nLetters Guessed: {2}'; export const parser = new RegExp( diff --git a/src/evilHangman/hangmanLetterButtons.test.ts b/src/evilHangman/hangmanLetterButtons.test.ts index 76c58e4c..72aa527a 100644 --- a/src/evilHangman/hangmanLetterButtons.test.ts +++ b/src/evilHangman/hangmanLetterButtons.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { getButtonsForAllLettersExcept } from './hangmanLetterButtons.js'; +import { getButtonsForAllLettersExcept } from './hangmanLetterButtons.ts'; describe('getLetterOptions', () => { test('no guesses returns the full alphabet', () => { diff --git a/src/evilHangman/hangmanLetterButtons.ts b/src/evilHangman/hangmanLetterButtons.ts index e0e9818c..0a608bb0 100644 --- a/src/evilHangman/hangmanLetterButtons.ts +++ b/src/evilHangman/hangmanLetterButtons.ts @@ -1,5 +1,5 @@ -import type { Letter } from '../buttons/hangmanLetterButton.js'; -import { hangmanLetterButton } from '../buttons/hangmanLetterButton.js'; +import type { Letter } from '../buttons/hangmanLetterButton.ts'; +import { hangmanLetterButton } from '../buttons/hangmanLetterButton.ts'; const alphabet: ReadonlyArray = Array.from({ length: 26 }) .fill(null) diff --git a/src/evilHangman/parseEvilHangmanMessage.test.ts b/src/evilHangman/parseEvilHangmanMessage.test.ts index b8de229b..e5e02ff3 100644 --- a/src/evilHangman/parseEvilHangmanMessage.test.ts +++ b/src/evilHangman/parseEvilHangmanMessage.test.ts @@ -2,7 +2,7 @@ import { beforeEach, describe, expect, test } from 'vitest'; import type { Message } from 'discord.js'; -import { parseEvilHangmanMessage } from './parseEvilHangmanMessage.js'; +import { parseEvilHangmanMessage } from './parseEvilHangmanMessage.ts'; describe('parseEvilHangmanMessage', () => { const field: { value: string | undefined } = { diff --git a/src/evilHangman/parseEvilHangmanMessage.ts b/src/evilHangman/parseEvilHangmanMessage.ts index 858160dd..aadf3d82 100644 --- a/src/evilHangman/parseEvilHangmanMessage.ts +++ b/src/evilHangman/parseEvilHangmanMessage.ts @@ -1,7 +1,7 @@ import type { Message } from 'discord.js'; -import { EvilHangmanGame } from './evilHangmanGame.js'; -import { parser } from './gameInfoParser.js'; +import { EvilHangmanGame } from './evilHangmanGame.ts'; +import { parser } from './gameInfoParser.ts'; const FORMAT_ERROR_MESSAGE = 'Incorrect message format for Evil Hangman'; diff --git a/src/helpers/NetworkError.ts b/src/helpers/NetworkError.ts index c10122b6..f6024dd0 100644 --- a/src/helpers/NetworkError.ts +++ b/src/helpers/NetworkError.ts @@ -1,5 +1,5 @@ -import type { HttpStatusCode } from './HttpStatusCode.js'; -import { describeCode } from './HttpStatusCode.js'; +import type { HttpStatusCode } from './HttpStatusCode.ts'; +import { describeCode } from './HttpStatusCode.ts'; /** * An object that represents an HTTP status returned from an API request. diff --git a/src/helpers/actions/deployCommands.test.ts b/src/helpers/actions/deployCommands.test.ts index 193a4174..cad2f22a 100644 --- a/src/helpers/actions/deployCommands.test.ts +++ b/src/helpers/actions/deployCommands.test.ts @@ -5,18 +5,18 @@ import type { Client, Guild, OAuth2Guild } from 'discord.js'; import { Collection, InteractionContextType, SlashCommandBuilder } from 'discord.js'; // Mock the logger so nothing is printed -vi.mock('../../logger.js'); +vi.mock('../../logger.ts'); const mockAllCommands = vi.hoisted(() => new Map()); -vi.mock('../../commands/index.js', () => ({ +vi.mock('../../commands/index.ts', () => ({ allCommands: mockAllCommands, })); -vi.mock('./revokeCommands.js'); -import { revokeCommands } from './revokeCommands.js'; +vi.mock('./revokeCommands.ts'); +import { revokeCommands } from './revokeCommands.ts'; const mockRevokeCommands = revokeCommands as Mock; -import { deployCommands } from './deployCommands.js'; +import { deployCommands } from './deployCommands.ts'; describe('Command deployments', () => { const mockApplicationCommandsSet = vi.fn['commands']['set']>(); diff --git a/src/helpers/actions/deployCommands.ts b/src/helpers/actions/deployCommands.ts index 02aed729..8c046ba1 100644 --- a/src/helpers/actions/deployCommands.ts +++ b/src/helpers/actions/deployCommands.ts @@ -1,10 +1,10 @@ import type { Client, Guild, RESTPostAPIApplicationCommandsJSONBody } from 'discord.js'; import { ApplicationCommandType } from 'discord.js'; -import { allCommands } from '../../commands/index.js'; -import { debug, error, info } from '../../logger.js'; -import { isNonEmptyArray } from '../guards/isNonEmptyArray.js'; -import { revokeCommands } from './revokeCommands.js'; +import { allCommands } from '../../commands/index.ts'; +import { debug, error, info } from '../../logger.ts'; +import { isNonEmptyArray } from '../guards/isNonEmptyArray.ts'; +import { revokeCommands } from './revokeCommands.ts'; export async function deployCommands(client: Client): Promise { await revokeCommands(client); // fresh start! diff --git a/src/helpers/actions/messages/replyToMessage.test.ts b/src/helpers/actions/messages/replyToMessage.test.ts index e5ae5dd7..b3d75c8d 100644 --- a/src/helpers/actions/messages/replyToMessage.test.ts +++ b/src/helpers/actions/messages/replyToMessage.test.ts @@ -11,10 +11,10 @@ import type { import { ChannelType } from 'discord.js'; // Mock the logger to track output -vi.mock('../../../logger.js'); -import { error as mockLoggerError } from '../../../logger.js'; +vi.mock('../../../logger.ts'); +import { error as mockLoggerError } from '../../../logger.ts'; -import { replyWithPrivateMessage, sendMessageInChannel } from './replyToMessage.js'; +import { replyWithPrivateMessage, sendMessageInChannel } from './replyToMessage.ts'; describe('Replies', () => { const mockUserSend = vi.fn(); diff --git a/src/helpers/actions/messages/replyToMessage.ts b/src/helpers/actions/messages/replyToMessage.ts index 8cbd9b3b..ccf1c81e 100644 --- a/src/helpers/actions/messages/replyToMessage.ts +++ b/src/helpers/actions/messages/replyToMessage.ts @@ -9,8 +9,8 @@ import type { } from 'discord.js'; import { ChannelType, PartialGroupDMChannel, channelMention, userMention } from 'discord.js'; -import { error, info } from '../../../logger.js'; -import { logUser } from '../../logUser.js'; +import { error, info } from '../../../logger.ts'; +import { logUser } from '../../logUser.ts'; /** * Attempts to send a direct message to a user. diff --git a/src/helpers/actions/revokeCommands.test.ts b/src/helpers/actions/revokeCommands.test.ts index 1c16e585..18aa58a4 100644 --- a/src/helpers/actions/revokeCommands.test.ts +++ b/src/helpers/actions/revokeCommands.test.ts @@ -4,9 +4,9 @@ import type { Client, Guild, OAuth2Guild } from 'discord.js'; import { Collection } from 'discord.js'; // Mock the logger so nothing is printed -vi.mock('../../logger.js'); +vi.mock('../../logger.ts'); -import { revokeCommands } from './revokeCommands.js'; +import { revokeCommands } from './revokeCommands.ts'; describe('Command revocations', () => { const mockApplicationCommandsSet = vi.fn['commands']['set']>(); diff --git a/src/helpers/actions/revokeCommands.ts b/src/helpers/actions/revokeCommands.ts index e5e4184c..5b13e4ec 100644 --- a/src/helpers/actions/revokeCommands.ts +++ b/src/helpers/actions/revokeCommands.ts @@ -1,6 +1,6 @@ import type { Client } from 'discord.js'; -import { info } from '../../logger.js'; +import { info } from '../../logger.ts'; /** * Unregisters all command interactions globally and in each guild for this account. diff --git a/src/helpers/actions/verifyCommandDeployments.test.ts b/src/helpers/actions/verifyCommandDeployments.test.ts index 5765f681..46f71000 100644 --- a/src/helpers/actions/verifyCommandDeployments.test.ts +++ b/src/helpers/actions/verifyCommandDeployments.test.ts @@ -7,11 +7,11 @@ const mockAllCommands = vi.hoisted(() => new Map()); vi.mock('../../commands', () => ({ allCommands: mockAllCommands })); // Mock the logger to track output -vi.mock('../../logger.js'); -import { warn as mockLoggerWarn } from '../../logger.js'; +vi.mock('../../logger.ts'); +import { warn as mockLoggerWarn } from '../../logger.ts'; -import { deployableCommand } from './deployCommands.js'; -import { verifyCommandDeployments } from './verifyCommandDeployments.js'; +import { deployableCommand } from './deployCommands.ts'; +import { verifyCommandDeployments } from './verifyCommandDeployments.ts'; describe('Verify command deployments', () => { const commands: Array = [ diff --git a/src/helpers/actions/verifyCommandDeployments.ts b/src/helpers/actions/verifyCommandDeployments.ts index 1e301bca..3780f72e 100644 --- a/src/helpers/actions/verifyCommandDeployments.ts +++ b/src/helpers/actions/verifyCommandDeployments.ts @@ -1,7 +1,7 @@ import type { Client, Guild } from 'discord.js'; -import { allCommands } from '../../commands/index.js'; -import { warn } from '../../logger.js'; +import { allCommands } from '../../commands/index.ts'; +import { warn } from '../../logger.ts'; /** * Verify that the deployed command list is up-to-date, and yell in the console if it's not. diff --git a/src/helpers/fetch.test.ts b/src/helpers/fetch.test.ts index 3d15bc29..05307d33 100644 --- a/src/helpers/fetch.test.ts +++ b/src/helpers/fetch.test.ts @@ -3,9 +3,9 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import { URL } from 'node:url'; import { string, type as schema, StructError } from 'superstruct'; -import { fetchJson } from './fetch.js'; -import { HttpStatusCode } from './HttpStatusCode.js'; -import { NetworkError } from './NetworkError.js'; +import { fetchJson } from './fetch.ts'; +import { HttpStatusCode } from './HttpStatusCode.ts'; +import { NetworkError } from './NetworkError.ts'; const mockFetch = vi.spyOn(globalThis, 'fetch'); diff --git a/src/helpers/fetch.ts b/src/helpers/fetch.ts index 5f388550..f2fceab0 100644 --- a/src/helpers/fetch.ts +++ b/src/helpers/fetch.ts @@ -3,8 +3,8 @@ import type { URL } from 'node:url'; import type { Struct, StructError } from 'superstruct'; import { assert } from 'superstruct'; -import { HttpStatusCode } from './HttpStatusCode.js'; -import { NetworkError } from './NetworkError.js'; +import { HttpStatusCode } from './HttpStatusCode.ts'; +import { NetworkError } from './NetworkError.ts'; /** * Performs a network request. diff --git a/src/helpers/format.test.ts b/src/helpers/format.test.ts index 5b85fc02..05bfe65c 100644 --- a/src/helpers/format.test.ts +++ b/src/helpers/format.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { format } from './format.js'; +import { format } from './format.ts'; describe('format template strings', () => { test('creates "foo bar baz" as documented', () => { diff --git a/src/helpers/guards/isError.test.ts b/src/helpers/guards/isError.test.ts index d9e63a7a..e8e7f939 100644 --- a/src/helpers/guards/isError.test.ts +++ b/src/helpers/guards/isError.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { isError } from './isError.js'; +import { isError } from './isError.ts'; class TestError extends Error { public constructor() { diff --git a/src/helpers/guards/isNonEmptyArray.test.ts b/src/helpers/guards/isNonEmptyArray.test.ts index aed1b374..1e95db20 100644 --- a/src/helpers/guards/isNonEmptyArray.test.ts +++ b/src/helpers/guards/isNonEmptyArray.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { isNonEmptyArray } from './isNonEmptyArray.js'; +import { isNonEmptyArray } from './isNonEmptyArray.ts'; describe('Nonempty array', () => { test('returns false for an empty array', () => { diff --git a/src/helpers/logUser.test.ts b/src/helpers/logUser.test.ts index 5d870b84..beee388f 100644 --- a/src/helpers/logUser.test.ts +++ b/src/helpers/logUser.test.ts @@ -2,7 +2,7 @@ import { beforeEach, describe, expect, test } from 'vitest'; import type { User } from 'discord.js'; -import { logUser } from './logUser.js'; +import { logUser } from './logUser.ts'; describe('Log user ID', () => { const user = {} as unknown as User; diff --git a/src/helpers/onEvent.test.ts b/src/helpers/onEvent.test.ts index 3aab25a4..3a5ac2d7 100644 --- a/src/helpers/onEvent.test.ts +++ b/src/helpers/onEvent.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from 'vitest'; import { Events } from 'discord.js'; -import { onEvent } from './onEvent.js'; +import { onEvent } from './onEvent.ts'; const executeMock = (): void => undefined; diff --git a/src/helpers/parseArgs.test.ts b/src/helpers/parseArgs.test.ts index 8bd63e06..7b50bc15 100644 --- a/src/helpers/parseArgs.test.ts +++ b/src/helpers/parseArgs.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { parseArgs } from './parseArgs.js'; +import { parseArgs } from './parseArgs.ts'; describe('Args parser', () => { test('defaults both flags to `false`', () => { diff --git a/src/helpers/positionsOfUriInText.test.ts b/src/helpers/positionsOfUriInText.test.ts index 80db6a74..f1d9e636 100644 --- a/src/helpers/positionsOfUriInText.test.ts +++ b/src/helpers/positionsOfUriInText.test.ts @@ -6,8 +6,8 @@ import { URL } from 'node:url'; // return false for a specific string. For all other tests, we want to use the default implementation. const canParseMock = vi.spyOn(URL, 'canParse'); -import type { Range } from './positionsOfUriInText.js'; -import { positionsOfUriInText } from './positionsOfUriInText.js'; +import type { Range } from './positionsOfUriInText.ts'; +import { positionsOfUriInText } from './positionsOfUriInText.ts'; describe('Identifying URIs in strings', () => { test.each` diff --git a/src/logger.ts b/src/logger.ts index 9b01c920..b4ef0f30 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -4,7 +4,7 @@ import * as console from 'node:console'; * The default logger for this application. Set to the console for now. * Should not be accessed outside this logger file - instead, use the endpoint methods. * The goal is to define our own interface to separate usage from implementation. - * To import the entire logger with all endpoints, use `import * as logger from './logger.js';` + * To import the entire logger with all endpoints, use `import * as logger from './logger.ts';` * If you add any more endpoints to this file, remember to mock them in './\_\_mocks\_\_/logger.ts' * @private */ diff --git a/src/main.test.ts b/src/main.test.ts index 412b27df..c85d2ea8 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -31,16 +31,16 @@ const mockToken = 'TEST_TOKEN'; process.env['DISCORD_TOKEN'] = mockToken; // Mock the event handler index so we can track it -vi.mock('./events/index.js'); -import { registerEventHandlers } from './events/index.js'; +vi.mock('./events/index.ts'); +import { registerEventHandlers } from './events/index.ts'; const mockRegisterEventHandlers = registerEventHandlers as Mock; // Mock the logger to track output -vi.mock('./logger.js'); -import { error as mockLoggerError } from './logger.js'; +vi.mock('./logger.ts'); +import { error as mockLoggerError } from './logger.ts'; // Import the code to test -import { _main } from './main.js'; +import { _main } from './main.ts'; // A basic error to test with const loginError = new Error('Failed to log in. This is a test.'); diff --git a/src/main.ts b/src/main.ts index cb47a239..e1e76dc4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,8 +2,8 @@ import 'source-map-support/register.js'; import { ActivityType, Client, GatewayIntentBits, Partials } from 'discord.js'; -import { registerEventHandlers } from './events/index.js'; -import { error, info } from './logger.js'; +import { registerEventHandlers } from './events/index.ts'; +import { error, info } from './logger.ts'; // We *could* do all of this at the top level, but then // none of this setup would be testable :P diff --git a/src/reactionHandlers/add.test.ts b/src/reactionHandlers/add.test.ts index 8e3d0b4a..7c9e4738 100644 --- a/src/reactionHandlers/add.test.ts +++ b/src/reactionHandlers/add.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { _add, addReactionHandlers } from './add.js'; +import { _add, addReactionHandlers } from './add.ts'; describe('allReactionHandlers', () => { test('index is not empty', () => { diff --git a/src/reactionHandlers/add.ts b/src/reactionHandlers/add.ts index 34133c32..b464208d 100644 --- a/src/reactionHandlers/add.ts +++ b/src/reactionHandlers/add.ts @@ -25,8 +25,8 @@ export function _add(handler: ReactionHandler): void { } /** Install handlers here: **/ -import { duplicate } from './duplicate.js'; -import { buildUpdateReactboard } from './updateReactboard.js'; +import { duplicate } from './duplicate.ts'; +import { buildUpdateReactboard } from './updateReactboard.ts'; _add(duplicate); _add(buildUpdateReactboard('messageReactionAdd')); diff --git a/src/reactionHandlers/duplicate.test.ts b/src/reactionHandlers/duplicate.test.ts index 892e856c..d8488cb1 100644 --- a/src/reactionHandlers/duplicate.test.ts +++ b/src/reactionHandlers/duplicate.test.ts @@ -3,10 +3,10 @@ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import type { MessageReaction, User } from 'discord.js'; -import { duplicate } from './duplicate.js'; +import { duplicate } from './duplicate.ts'; // Mock the logger so nothing is printed -vi.mock('../logger.js'); +vi.mock('../logger.ts'); describe('Reaction duplication', () => { const mockResendReact = vi.fn(); diff --git a/src/reactionHandlers/duplicate.ts b/src/reactionHandlers/duplicate.ts index ff1db71b..27c4d946 100644 --- a/src/reactionHandlers/duplicate.ts +++ b/src/reactionHandlers/duplicate.ts @@ -1,5 +1,5 @@ -import { chances, DEFAULT_CHANCE } from '../constants/reactionDuplication.js'; -import { debug } from '../logger.js'; +import { chances, DEFAULT_CHANCE } from '../constants/reactionDuplication.ts'; +import { debug } from '../logger.ts'; export const duplicate: ReactionHandler = { async execute({ reaction }) { diff --git a/src/reactionHandlers/remove.test.ts b/src/reactionHandlers/remove.test.ts index da2819e6..3b5ebea0 100644 --- a/src/reactionHandlers/remove.test.ts +++ b/src/reactionHandlers/remove.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; -import { _add, removeReactionHandlers } from './remove.js'; +import { _add, removeReactionHandlers } from './remove.ts'; describe('allReactionHandlers', () => { test('index is not empty', () => { diff --git a/src/reactionHandlers/remove.ts b/src/reactionHandlers/remove.ts index 5c263e72..302dc8d1 100644 --- a/src/reactionHandlers/remove.ts +++ b/src/reactionHandlers/remove.ts @@ -25,6 +25,6 @@ export function _add(handler: ReactionHandler): void { } /** Install handlers here: **/ -import { buildUpdateReactboard } from './updateReactboard.js'; +import { buildUpdateReactboard } from './updateReactboard.ts'; _add(buildUpdateReactboard('messageReactionRemove')); diff --git a/src/reactionHandlers/updateReactboard.test.ts b/src/reactionHandlers/updateReactboard.test.ts index e2535cf1..922a5691 100644 --- a/src/reactionHandlers/updateReactboard.test.ts +++ b/src/reactionHandlers/updateReactboard.test.ts @@ -5,10 +5,10 @@ import type { DeepMockProxy } from 'vitest-mock-extended'; import type { PrismaClient, Reactboard, ReactboardPost } from '@prisma/client'; import { ChannelType, Client, Message, TextChannel, User } from 'discord.js'; -import { db } from '../database/index.js'; -import { buildUpdateReactboard } from './updateReactboard.js'; +import { db } from '../database/index.ts'; +import { buildUpdateReactboard } from './updateReactboard.ts'; -vi.mock('../database/index.js', () => ({ +vi.mock('../database/index.ts', () => ({ db: mockDeep(), })); diff --git a/src/reactionHandlers/updateReactboard.ts b/src/reactionHandlers/updateReactboard.ts index 18f6b5e3..a57a70d9 100644 --- a/src/reactionHandlers/updateReactboard.ts +++ b/src/reactionHandlers/updateReactboard.ts @@ -13,8 +13,8 @@ import { VoiceChannel, } from 'discord.js'; -import { db } from '../database/index.js'; -import { appVersion } from '../constants/meta.js'; +import { db } from '../database/index.ts'; +import { appVersion } from '../constants/meta.ts'; export function buildUpdateReactboard( eventType: 'messageReactionAdd' | 'messageReactionRemove' diff --git a/tsconfig.json b/tsconfig.json index ffa7765b..bc586254 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "noUnusedLocals": true, "noUnusedParameters": true, + "allowImportingTsExtensions": true, "module": "nodenext", "verbatimModuleSyntax": true, From b647c25be3c92727110bd6d98367c393bdeea70b Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Wed, 13 May 2026 04:42:03 -0600 Subject: [PATCH 03/12] Enforce erasable syntax --- src/commands/talk.test.ts | 5 +- src/commands/talk.ts | 29 ++- src/evilHangman/evilHangmanGame.ts | 14 +- src/helpers/DiscordErrorCode.ts | 364 ++++++++++++++--------------- src/helpers/HttpStatusCode.ts | 136 +++++------ src/helpers/fetch.ts | 2 +- tsconfig.json | 1 + 7 files changed, 277 insertions(+), 274 deletions(-) diff --git a/src/commands/talk.test.ts b/src/commands/talk.test.ts index fec77c2b..ef1e5dbd 100644 --- a/src/commands/talk.test.ts +++ b/src/commands/talk.test.ts @@ -11,7 +11,8 @@ vi.mock('dectalk-tts', () => ({ default: dectalkMock })); vi.mock('../logger.ts'); // Import the code to test -import { Speaker, talk } from './talk.ts'; +import { talk } from './talk.ts'; +import type { Speaker } from './talk.ts'; describe('Talk Slash Command', () => { const speakerMock = vi.fn<() => Speaker | null>(); @@ -61,7 +62,7 @@ describe('Talk Slash Command', () => { }); test('Prepends the speaker name to the message if provided', async () => { - const name = Speaker.Paul; + const name = 'PAUL'; speakerMock.mockReturnValueOnce(name); await talk.execute(context); diff --git a/src/commands/talk.ts b/src/commands/talk.ts index afd76829..0932d689 100644 --- a/src/commands/talk.ts +++ b/src/commands/talk.ts @@ -15,20 +15,21 @@ import dectalk from 'dectalk-tts'; import { writeFileSync, createReadStream } from 'node:fs'; import { fileSync } from 'tmp'; - -export enum Speaker { - Paul = 'PAUL', - Betty = 'BETTY', - Harry = 'HARRY', - Frank = 'FRANK', - Dennis = 'DENNIS', - Kit = 'KIT', - Ursula = 'URSULA', - Rita = 'RITA', - Wendy = 'WENDY', -} import { info } from '../logger.ts'; +const SPEAKERS = { + Paul: 'PAUL', + Betty: 'BETTY', + Harry: 'HARRY', + Frank: 'FRANK', + Dennis: 'DENNIS', + Kit: 'KIT', + Ursula: 'URSULA', + Rita: 'RITA', + Wendy: 'WENDY', +} as const; +export type Speaker = (typeof SPEAKERS)[keyof typeof SPEAKERS]; + const builder = new SlashCommandBuilder() .setName('talk') .setDescription('Uses Dectalk to speak the given message (via https://tts.cyzon.us/)') @@ -37,9 +38,7 @@ const builder = new SlashCommandBuilder() ) .addStringOption(option => { option.setRequired(false).setName('speaker').setDescription('Whose voice to use'); - for (const name of Object.keys(Speaker)) { - const value = (Speaker as Record)[name]; - if (value === undefined) continue; + for (const [name, value] of Object.entries(SPEAKERS)) { option = option.addChoices({ name, value }); } return option; diff --git a/src/evilHangman/evilHangmanGame.ts b/src/evilHangman/evilHangmanGame.ts index 9ec15955..299a8829 100644 --- a/src/evilHangman/evilHangmanGame.ts +++ b/src/evilHangman/evilHangmanGame.ts @@ -152,18 +152,18 @@ export type EvilHangmanDisplayInfo = { type DisplayInfoWinStateExtension = | { - winState: EvilHangmanWinState.LOST; + winState: typeof EvilHangmanWinState.LOST; correctWord: string; } | { - winState: EvilHangmanWinState.WON | EvilHangmanWinState.IN_PROGRESS; + winState: typeof EvilHangmanWinState.WON | typeof EvilHangmanWinState.IN_PROGRESS; }; -export enum EvilHangmanWinState { - WON = 'won', - IN_PROGRESS = 'in progress', - LOST = 'lost', -} +export const EvilHangmanWinState = { + WON: 'won', + IN_PROGRESS: 'in progress', + LOST: 'lost', +} as const; interface FormScore { form: RegExp; diff --git a/src/helpers/DiscordErrorCode.ts b/src/helpers/DiscordErrorCode.ts index aa8292ed..e75c7d09 100644 --- a/src/helpers/DiscordErrorCode.ts +++ b/src/helpers/DiscordErrorCode.ts @@ -3,901 +3,901 @@ * * See https://discord.com/developers/docs/topics/opcodes-and-status-codes#json */ -export enum DiscordErrorCode { +export const DiscordErrorCode = { /** General error (such as a malformed request body, amongst other things) */ - GENERAL = 0, + GENERAL: 0, /** Unknown account */ - UNKNOWN_ACCOUNT = 10_001, + UNKNOWN_ACCOUNT: 10_001, /** * Unknown application */ - UNKNOWN_APPLICATION = 10_002, + UNKNOWN_APPLICATION: 10_002, /** * Unknown channel */ - UNKNOWN_CHANNEL = 10_003, + UNKNOWN_CHANNEL: 10_003, /** * Unknown guild */ - UNKNOWN_GUILD = 10_004, + UNKNOWN_GUILD: 10_004, /** * Unknown integration */ - UNKNOWN_INTEGRATION = 10_005, + UNKNOWN_INTEGRATION: 10_005, /** * Unknown invite */ - UNKNOWN_INVITE = 10_006, + UNKNOWN_INVITE: 10_006, /** * Unknown member */ - UNKNOWN_MEMBER = 10_007, + UNKNOWN_MEMBER: 10_007, /** * Unknown message */ - UNKNOWN_MESSAGE = 10_008, + UNKNOWN_MESSAGE: 10_008, /** * Unknown permission overwrite */ - UNKNOWN_PERMISSION_OVERWRITE = 10_009, + UNKNOWN_PERMISSION_OVERWRITE: 10_009, /** * Unknown provider */ - UNKNOWN_PROVIDER = 10_010, + UNKNOWN_PROVIDER: 10_010, /** * Unknown role */ - UNKNOWN_ROLE = 10_011, + UNKNOWN_ROLE: 10_011, /** * Unknown token */ - UNKNOWN_TOKEN = 10_012, + UNKNOWN_TOKEN: 10_012, /** * Unknown user */ - UNKNOWN_USER = 10_013, + UNKNOWN_USER: 10_013, /** * Unknown emoji */ - UNKNOWN_EMOJI = 10_014, + UNKNOWN_EMOJI: 10_014, /** * Unknown webhook */ - UNKNOWN_WEBHOOK = 10_015, + UNKNOWN_WEBHOOK: 10_015, /** * Unknown webhook service */ - UNKNOWN_WEBHOOK_SERVICE = 10_016, + UNKNOWN_WEBHOOK_SERVICE: 10_016, /** * Unknown session */ - UNKNOWN_SESSION = 10_020, + UNKNOWN_SESSION: 10_020, /** * Unknown ban */ - UNKNOWN_BAN = 10_026, + UNKNOWN_BAN: 10_026, /** * Unknown SKU */ - UNKNOWN_SKU = 10_027, + UNKNOWN_SKU: 10_027, /** * Unknown Store Listing */ - UNKNOWN_STORE_LISTING = 10_028, + UNKNOWN_STORE_LISTING: 10_028, /** * Unknown entitlement */ - UNKNOWN_ENTITLEMENT = 10_029, + UNKNOWN_ENTITLEMENT: 10_029, /** * Unknown build */ - UNKNOWN_BUILD = 10_030, + UNKNOWN_BUILD: 10_030, /** * Unknown lobby */ - UNKNOWN_LOBBY = 10_031, + UNKNOWN_LOBBY: 10_031, /** * Unknown branch */ - UNKNOWN_BRANCH = 10_032, + UNKNOWN_BRANCH: 10_032, /** * Unknown store directory layout */ - UNKNOWN_STORE_DIRECTORY_LAYOUT = 10_033, + UNKNOWN_STORE_DIRECTORY_LAYOUT: 10_033, /** * Unknown redistributable */ - UNKNOWN_REDISTRIBUTABLE = 10_036, + UNKNOWN_REDISTRIBUTABLE: 10_036, /** * Unknown gift code */ - UNKNOWN_GIFT_CODE = 10_038, + UNKNOWN_GIFT_CODE: 10_038, /** * Unknown stream */ - UNKNOWN_STREAM = 10_049, + UNKNOWN_STREAM: 10_049, /** * Unknown premium server subscribe cooldown */ - UNKNOWN_PREMIUM_SERVER_SUBSCRIBE_COOLDOWN = 10_050, + UNKNOWN_PREMIUM_SERVER_SUBSCRIBE_COOLDOWN: 10_050, /** * Unknown guild template */ - UNKNOWN_GUILD_TEMPLATE = 10_057, + UNKNOWN_GUILD_TEMPLATE: 10_057, /** * Unknown discoverable server category */ - UNKNOWN_DISCOVERABLE_SERVER_CATEGORY = 10_059, + UNKNOWN_DISCOVERABLE_SERVER_CATEGORY: 10_059, /** * Unknown sticker */ - UNKNOWN_STICKER = 10_060, + UNKNOWN_STICKER: 10_060, /** * Unknown interaction */ - UNKNOWN_INTERACTION = 10_062, + UNKNOWN_INTERACTION: 10_062, /** * Unknown application command */ - UNKNOWN_APPLICATION_COMMAND = 10_063, + UNKNOWN_APPLICATION_COMMAND: 10_063, /** * Unknown voice state */ - UNKNOWN_VOICE_STATE = 10_065, + UNKNOWN_VOICE_STATE: 10_065, /** * Unknown application command permissions */ - UNKNOWN_APPLICATION_COMMAND_PERMISSIONS = 10_066, + UNKNOWN_APPLICATION_COMMAND_PERMISSIONS: 10_066, /** * Unknown Stage Instance */ - UNKNOWN_STAGE_INSTANCE = 10_067, + UNKNOWN_STAGE_INSTANCE: 10_067, /** * Unknown Guild Member Verification Form */ - UNKNOWN_GUILD_MEMBER_VERIFICATION_FORM = 10_068, + UNKNOWN_GUILD_MEMBER_VERIFICATION_FORM: 10_068, /** * Unknown Guild Welcome Screen */ - UNKNOWN_GUILD_WELCOME_SCREEN = 10_069, + UNKNOWN_GUILD_WELCOME_SCREEN: 10_069, /** * Unknown Guild Scheduled Event */ - UNKNOWN_GUILD_SCHEDULED_EVENT = 10_070, + UNKNOWN_GUILD_SCHEDULED_EVENT: 10_070, /** * Unknown Guild Event User */ - UNKNOWN_GUILD_SCHEDULED_EVENT_USER = 10_071, + UNKNOWN_GUILD_SCHEDULED_EVENT_USER: 10_071, /** * Unknown Tag */ - UNKNOWN_TAG = 10_087, + UNKNOWN_TAG: 10_087, /** * Bots cannot use this endpoint */ - ONLY_USERS = 20_001, + ONLY_USERS: 20_001, /** * Only bots can use this endpoint */ - ONLY_BOTS = 20_002, + ONLY_BOTS: 20_002, /** * Explicit content cannot be sent to the desired recipient(s) */ - EXPLICIT_CONTENT = 20_009, + EXPLICIT_CONTENT: 20_009, /** * You are not authorized to perform this action on this application */ - NOT_APPLICATION_AUTHORIZED = 20_012, + NOT_APPLICATION_AUTHORIZED: 20_012, /** * This action cannot be performed due to slowmode rate limit */ - SLOWMODE_RATE_LIMIT = 20_016, + SLOWMODE_RATE_LIMIT: 20_016, /** * Only the owner of this account can perform this action */ - NOT_ACCOUNT_OWNER = 20_018, + NOT_ACCOUNT_OWNER: 20_018, /** * This message cannot be edited due to announcement rate limits */ - ANNOUNCEMENT_EDIT_RATE_LIMIT = 20_022, + ANNOUNCEMENT_EDIT_RATE_LIMIT: 20_022, /** * Under minimum age */ - AGE_RESTRICTED = 20_024, + AGE_RESTRICTED: 20_024, /** * The channel you are writing has hit the write rate limit */ - CHANNEL_WRITE_RATE_LIMIT = 20_028, + CHANNEL_WRITE_RATE_LIMIT: 20_028, /** * The write action you are performing on the server has hit the write rate limit */ - SERVER_WRITE_RATE_LIMIT = 20_029, + SERVER_WRITE_RATE_LIMIT: 20_029, /** * Your Stage topic, server name, server description, or channel names contain * words that are not allowed */ - PROFANITY = 20_031, + PROFANITY: 20_031, /** * Guild premium subscription level too low */ - GUILD_PREMIUM_SUBSCRIPTION_LEVEL_TOO_LOW = 20_035, + GUILD_PREMIUM_SUBSCRIPTION_LEVEL_TOO_LOW: 20_035, /** * Maximum number of guilds reached (100) */ - TOO_MANY_GUILDS = 30_001, + TOO_MANY_GUILDS: 30_001, /** * Maximum number of friends reached (1000) */ - TOO_MANY_FRIENDS = 30_002, + TOO_MANY_FRIENDS: 30_002, /** * Maximum number of pins reached for the channel (50) */ - TOO_MANY_PINS = 30_003, + TOO_MANY_PINS: 30_003, /** * Maximum number of recipients reached (10) */ - TOO_MANY_RECIPIENTS = 30_004, + TOO_MANY_RECIPIENTS: 30_004, /** * Maximum number of guild roles reached (250) */ - TOO_MANY_ROLES = 30_005, + TOO_MANY_ROLES: 30_005, /** * Maximum number of webhooks reached (10) */ - TOO_MANY_WEBHOOKS = 30_007, + TOO_MANY_WEBHOOKS: 30_007, /** * Maximum number of emojis reached */ - TOO_MANY_EMOJIS = 30_008, + TOO_MANY_EMOJIS: 30_008, /** * Maximum number of reactions reached (20) */ - TOO_MANY_REACTIONS = 30_010, + TOO_MANY_REACTIONS: 30_010, /** * Maximum number of guild channels reached (500) */ - TOO_MANY_GUILD_CHANNELS = 30_013, + TOO_MANY_GUILD_CHANNELS: 30_013, /** * Maximum number of attachments in a message reached (10) */ - TOO_MANY_ATTACHMENTS = 30_015, + TOO_MANY_ATTACHMENTS: 30_015, /** * Maximum number of invites reached (1000) */ - TOO_MANY_INVITES = 30_016, + TOO_MANY_INVITES: 30_016, /** * Maximum number of animated emojis reached */ - TOO_MANY_ANIMATED_EMOJIS = 30_018, + TOO_MANY_ANIMATED_EMOJIS: 30_018, /** * Maximum number of server members reached */ - TOO_MANY_GUILD_MEMBERS = 30_019, + TOO_MANY_GUILD_MEMBERS: 30_019, /** * Maximum number of server categories has been reached (5) */ - TOO_MANY_SERVER_CATEGORIES = 30_030, + TOO_MANY_SERVER_CATEGORIES: 30_030, /** * Guild already has a template */ - ALREADY_HAS_TEMPLATE = 30_031, + ALREADY_HAS_TEMPLATE: 30_031, /** * Maximum number of application commands reached */ - TOO_MANY_APPLICATION_COMMANDS = 30_032, + TOO_MANY_APPLICATION_COMMANDS: 30_032, /** * Max number of thread participants has been reached (1000) */ - TOO_MANY_THREAD_PARTICIPANTS = 30_033, + TOO_MANY_THREAD_PARTICIPANTS: 30_033, /** * Max number of daily application command creates has been reached (200) */ - APPLICATION_COMMAND_CREATION_RATE_LIMIT = 30_034, + APPLICATION_COMMAND_CREATION_RATE_LIMIT: 30_034, /** * Maximum number of bans for non-guild members have been exceeded */ - TOO_MANY_EXTERNAL_APPLICATION_BANS = 30_035, + TOO_MANY_EXTERNAL_APPLICATION_BANS: 30_035, /** * Maximum number of bans fetches has been reached */ - BAN_FETCH_RATE_LIMIT = 30_037, + BAN_FETCH_RATE_LIMIT: 30_037, /** * Maximum number of uncompleted guild scheduled events reached (100) */ - TOO_MANY_SCHEDULED_EVENTS = 30_038, + TOO_MANY_SCHEDULED_EVENTS: 30_038, /** * Maximum number of stickers reached */ - TOO_MANY_STICKERS = 30_039, + TOO_MANY_STICKERS: 30_039, /** * Maximum number of prune requests has been reached. Try again later */ - PRUNE_REQUEST_RATE_LIMIT = 30_040, + PRUNE_REQUEST_RATE_LIMIT: 30_040, /** * Maximum number of guild widget settings updates has been reached. Try again later */ - GUILD_WIDGET_SETTINGS_UPDATE_RATE_LIMIT = 30_042, + GUILD_WIDGET_SETTINGS_UPDATE_RATE_LIMIT: 30_042, /** * Maximum number of edits to messages older than 1 hour reached. Try again later */ - OLD_MESSAGE_EDIT_RATE_LIMIT = 30_046, + OLD_MESSAGE_EDIT_RATE_LIMIT: 30_046, /** * Maximum number of pinned threads in a forum channel has been reached */ - TOO_MANY_PINNED_FORUM_THREADS = 30_047, + TOO_MANY_PINNED_FORUM_THREADS: 30_047, /** * Maximum number of tags in a forum channel has been reached */ - TOO_MANY_FORUM_CHANNEL_TAGS = 30_048, + TOO_MANY_FORUM_CHANNEL_TAGS: 30_048, /** * Bitrate is too high for channel of this type */ - BITRATE_TOO_HIGH = 30_052, + BITRATE_TOO_HIGH: 30_052, /** * Unauthorized. Provide a valid token and try again */ - UNAUTHORIZED = 40_001, + UNAUTHORIZED: 40_001, /** * You need to verify your account in order to perform this action */ - UNVERIFIED_ACCOUNT = 40_002, + UNVERIFIED_ACCOUNT: 40_002, /** * You are opening direct messages too fast */ - DM_OPEN_RATE_LIMIT = 40_003, + DM_OPEN_RATE_LIMIT: 40_003, /** * Send messages has been temporarily disabled */ - CANNOT_SEND_MESSAGES = 40_004, + CANNOT_SEND_MESSAGES: 40_004, /** * Request entity too large. Try sending something smaller in size */ - REQUEST_ENTITY_TOO_LARGE = 40_005, + REQUEST_ENTITY_TOO_LARGE: 40_005, /** * This feature has been temporarily disabled server-side */ - CANNOT_USE_FEATURE = 40_006, + CANNOT_USE_FEATURE: 40_006, /** * The user is banned from this guild */ - USER_IS_BANNED_FROM_GUILD = 40_007, + USER_IS_BANNED_FROM_GUILD: 40_007, /** * Connection has been revoked */ - CONNECTION_REVOKED = 40_012, + CONNECTION_REVOKED: 40_012, /** * Target user is not connected to voice */ - MUST_BE_CONNECTED_TO_VOICE = 40_032, + MUST_BE_CONNECTED_TO_VOICE: 40_032, /** * This message has already been crossposted */ - ALREADY_CROSSPOSTED = 40_033, + ALREADY_CROSSPOSTED: 40_033, /** * An application command with that name already exists */ - DUPLICATE_APPLICATION_COMMAND_NAME = 40_041, + DUPLICATE_APPLICATION_COMMAND_NAME: 40_041, /** * Application interaction failed to send */ - INTERACTION_DID_NOT_SEND = 40_043, + INTERACTION_DID_NOT_SEND: 40_043, /** * Cannot send a message in a forum channel */ - CANNOT_SEND_MESSAGE_IN_FORUM = 40_058, + CANNOT_SEND_MESSAGE_IN_FORUM: 40_058, /** * Interaction has already been acknowledged */ - INTERACTION_ALREADY_ACKNOWLEDGED = 40_060, + INTERACTION_ALREADY_ACKNOWLEDGED: 40_060, /** * Tag names must be unique */ - DUPLICATE_TAG_NAME = 40_061, + DUPLICATE_TAG_NAME: 40_061, /** * There are no tags available that can be set by non-moderators */ - NO_NORMIE_TAGS = 40_066, + NO_NORMIE_TAGS: 40_066, /** * A tag is required to create a forum post in this channel */ - TAG_REQUIRED = 40_067, + TAG_REQUIRED: 40_067, /** * Missing access */ - MISSING_ACCESS = 50_001, + MISSING_ACCESS: 50_001, /** * Invalid account type */ - INVALID_ACCOUNT_TYPE = 50_002, + INVALID_ACCOUNT_TYPE: 50_002, /** * Cannot execute action on a DM channel */ - NOT_ALLOWED_IN_DM = 50_003, + NOT_ALLOWED_IN_DM: 50_003, /** * Guild widget disabled */ - GUILD_WIDGET_DISABLED = 50_004, + GUILD_WIDGET_DISABLED: 50_004, /** * Cannot edit a message authored by another user */ - NOT_YOUR_MESSAGE = 50_005, + NOT_YOUR_MESSAGE: 50_005, /** * Cannot send an empty message */ - MESSAGE_EMPTY = 50_006, + MESSAGE_EMPTY: 50_006, /** * Cannot send messages to this user */ - USER_NOT_REACHABLE = 50_007, + USER_NOT_REACHABLE: 50_007, /** * Cannot send messages in a non-text channel */ - NOT_A_TEXT_CHANNEL = 50_008, + NOT_A_TEXT_CHANNEL: 50_008, /** * Channel verification level is too high for you to gain access */ - INSUFFICIENT_VERIFICATION_LEVEL = 50_009, + INSUFFICIENT_VERIFICATION_LEVEL: 50_009, /** * OAuth2 application does not have a bot */ - OAUTH_APPLICATION_HAS_NO_BOT = 50_010, + OAUTH_APPLICATION_HAS_NO_BOT: 50_010, /** * OAuth2 application limit reached */ - OAUTH_APPLICATION_LIMIT_REACHED = 50_011, + OAUTH_APPLICATION_LIMIT_REACHED: 50_011, /** * Invalid OAuth2 state */ - INVALID_OAUTH_STATE = 50_012, + INVALID_OAUTH_STATE: 50_012, /** * You lack permissions to perform that action */ - INSUFFICIENT_PERMISSIONS = 50_013, + INSUFFICIENT_PERMISSIONS: 50_013, /** * Invalid authentication token provided */ - INVALID_AUTH_TOKEN = 50_014, + INVALID_AUTH_TOKEN: 50_014, /** * Note was too long */ - NOTE_TOO_LONG = 50_015, + NOTE_TOO_LONG: 50_015, /** * Provided too few or too many messages to delete. Must provide at least 2 and fewer than 100 messages to delete */ - DELETE_BATCH_OUT_OF_RANGE = 50_016, + DELETE_BATCH_OUT_OF_RANGE: 50_016, /** * Invalid MFA Level */ - INVALID_MFA_LEVEL = 50_017, + INVALID_MFA_LEVEL: 50_017, /** * A message can only be pinned to the channel it was sent in */ - WRONG_CHANNEL_TO_PIN = 50_019, + WRONG_CHANNEL_TO_PIN: 50_019, /** * Invite code was either invalid or taken */ - BAD_INVITE = 50_020, + BAD_INVITE: 50_020, /** * Cannot execute action on a system message */ - SYSTEM_MESSAGE = 50_021, + SYSTEM_MESSAGE: 50_021, /** * Cannot execute action on this channel type */ - WRONG_CHANNEL_TYPE = 50_024, + WRONG_CHANNEL_TYPE: 50_024, /** * Invalid OAuth2 access token provided */ - INVALID_OAUTH_ACCESS_TOKEN = 50_025, + INVALID_OAUTH_ACCESS_TOKEN: 50_025, /** * Missing required OAuth2 scope */ - MISSING_OAUTH_SCOPE = 50_026, + MISSING_OAUTH_SCOPE: 50_026, /** * Invalid webhook token provided */ - INVALID_WEBHOOK_TOKEN = 50_027, + INVALID_WEBHOOK_TOKEN: 50_027, /** * Invalid role */ - INVALID_ROLE = 50_028, + INVALID_ROLE: 50_028, /** * Invalid Recipient(s) */ - INVALID_RECIPIENTS = 50_033, + INVALID_RECIPIENTS: 50_033, /** * A message provided was too old to bulk delete */ - MESSAGE_TOO_OLD_TO_BATCH_DELETE = 50_034, + MESSAGE_TOO_OLD_TO_BATCH_DELETE: 50_034, /** * Invalid form body (returned for both application/json and multipart/form-data bodies), or invalid Content-Type provided */ - INVALID_FORM_BODY = 50_035, + INVALID_FORM_BODY: 50_035, /** * An invite was accepted to a guild the application's bot is not in */ - INVITE_ACCEPTED_BUT_NOT_IN_GUILD = 50_036, + INVITE_ACCEPTED_BUT_NOT_IN_GUILD: 50_036, /** * Invalid Activity Action */ - INVALID_ACTIVITY_ACTION = 50_039, + INVALID_ACTIVITY_ACTION: 50_039, /** * Invalid API version provided */ - INVALID_API_VERSION = 50_041, + INVALID_API_VERSION: 50_041, /** * File uploaded exceeds the maximum size */ - FILE_TOO_LARGE = 50_045, + FILE_TOO_LARGE: 50_045, /** * Invalid file uploaded */ - INVALID_FILE = 50_046, + INVALID_FILE: 50_046, /** * Cannot self-redeem this gift */ - CANNOT_SAVE_SELF_FROM_SIN = 50_054, + CANNOT_SAVE_SELF_FROM_SIN: 50_054, /** * Invalid Guild */ - INVALID_GUILD = 50_055, + INVALID_GUILD: 50_055, /** * Invalid message type */ - INVALID_MESSAGE_TYPE = 50_068, + INVALID_MESSAGE_TYPE: 50_068, /** * Payment source required to redeem gift */ - REQUIRES_PAYMENT_SOURCE = 50_070, + REQUIRES_PAYMENT_SOURCE: 50_070, /** * Cannot modify a system webhook */ - CANNOT_MODIFY_SYSTEM_WEBHOOK = 50_073, + CANNOT_MODIFY_SYSTEM_WEBHOOK: 50_073, /** * Cannot delete a channel required for Community guilds */ - CANNOT_DELETE_REQUIRED_CHANNEL = 50_074, + CANNOT_DELETE_REQUIRED_CHANNEL: 50_074, /** * Cannot edit stickers within a message */ - CANNOT_EDIT_MESSAGE_STICKERS = 50_080, + CANNOT_EDIT_MESSAGE_STICKERS: 50_080, /** * Invalid sticker sent */ - INVALID_STICKER = 50_081, + INVALID_STICKER: 50_081, /** * Tried to perform an operation on an archived thread, such as editing a message or adding a user to the thread */ - THREAD_IS_ARCHIVED = 50_083, + THREAD_IS_ARCHIVED: 50_083, /** * Invalid thread notification settings */ - INVALID_THREAD_NOTIFICATION_SETTINGS = 50_084, + INVALID_THREAD_NOTIFICATION_SETTINGS: 50_084, /** * `before` value is earlier than the thread creation date */ - TIME_OUT_OF_RANGE = 50_085, + TIME_OUT_OF_RANGE: 50_085, /** * Community server channels must be text channels */ - CHANNEL_MUST_BE_TEXT = 50_086, + CHANNEL_MUST_BE_TEXT: 50_086, /** * This server is not available in your location */ - REGION_LOCKED = 50_095, + REGION_LOCKED: 50_095, /** * This server needs monetization enabled in order to perform this action */ - GUILD_MONETIZATION_REQUIRED = 50_097, + GUILD_MONETIZATION_REQUIRED: 50_097, /** * This server needs more boosts to perform this action */ - INSUFFICIENT_GUILD_BOOST_LEVEL = 50_101, + INSUFFICIENT_GUILD_BOOST_LEVEL: 50_101, /** * The request body contains invalid JSON. */ - INVALID_JSON = 50_109, + INVALID_JSON: 50_109, /** * Ownership cannot be transferred to a bot user */ - BOT_CANNOT_BE_OWNER = 50_132, + BOT_CANNOT_BE_OWNER: 50_132, /** * Failed to resize asset below the maximum size: 262144 */ - ASSET_TOO_SMALL = 50_138, + ASSET_TOO_SMALL: 50_138, /** * Uploaded file not found. */ - FILE_LOST = 50_146, + FILE_LOST: 50_146, /** * You do not have permission to send this sticker. */ - CANNOT_SEND_THIS_STICKER = 50_600, + CANNOT_SEND_THIS_STICKER: 50_600, /** * Two factor is required for this operation */ - MFA_REQUIRED = 60_003, + MFA_REQUIRED: 60_003, /** * No users with DiscordTag exist */ - NO_DISCORDTAG_USERS = 80_004, + NO_DISCORDTAG_USERS: 80_004, /** * Reaction was blocked */ - REACTION_BLOCKED = 90_001, + REACTION_BLOCKED: 90_001, /** * Application not yet available. Try again later */ - APPLICATION_NOT_AVAILABLE = 110_001, + APPLICATION_NOT_AVAILABLE: 110_001, /** * API resource is currently overloaded. Try again a little later */ - RESOURCE_OVERLOADED = 130_000, + RESOURCE_OVERLOADED: 130_000, /** * The Stage is already open */ - STAGE_ALREADY_OPEN = 150_006, + STAGE_ALREADY_OPEN: 150_006, /** * Cannot reply without permission to read message history */ - MUST_READ_MESSAGE_HISTORY_TO_REPLY_BUT_I_HAVE_NO_EYES = 160_002, + MUST_READ_MESSAGE_HISTORY_TO_REPLY_BUT_I_HAVE_NO_EYES: 160_002, /** * A thread has already been created for this message */ - MESSAGE_ALREADY_HAS_THREAD = 160_004, + MESSAGE_ALREADY_HAS_THREAD: 160_004, /** * Thread is locked */ - THREAD_IS_LOCKED = 160_005, + THREAD_IS_LOCKED: 160_005, /** * Maximum number of active threads reached */ - TOO_MANY_ACTIVE_THREADS = 160_006, + TOO_MANY_ACTIVE_THREADS: 160_006, /** * Maximum number of active announcement threads reached */ - TOO_MANY_ACTIVE_ANNOUNCEMENT_THREADS = 160_007, + TOO_MANY_ACTIVE_ANNOUNCEMENT_THREADS: 160_007, /** * Invalid JSON for uploaded Lottie file */ - INVALID_LOTTIE_JSON = 170_001, + INVALID_LOTTIE_JSON: 170_001, /** * Uploaded Lotties cannot contain rasterized images such as PNG or JPEG */ - CANNOT_RASTER_LOTTIE = 170_002, + CANNOT_RASTER_LOTTIE: 170_002, /** * Sticker maximum framerate exceeded */ - STICKER_HAS_TOO_MANY_HERTZ = 170_003, + STICKER_HAS_TOO_MANY_HERTZ: 170_003, /** * Sticker frame count exceeds maximum of 1000 frames */ - STICKER_HAS_TOO_MANY_FRAMES = 170_004, + STICKER_HAS_TOO_MANY_FRAMES: 170_004, /** * Lottie animation maximum dimensions exceeded */ - LOTTIE_IS_NOT_TARDIS = 170_005, + LOTTIE_IS_NOT_TARDIS: 170_005, /** * Sticker frame rate is either too small or too large */ - STICKER_HERTZ_OUT_OF_BOUNDS = 170_006, + STICKER_HERTZ_OUT_OF_BOUNDS: 170_006, /** * Sticker animation duration exceeds maximum of 5 seconds */ - STICKER_LASTS_TOO_LONG = 170_007, + STICKER_LASTS_TOO_LONG: 170_007, /** * Cannot update a finished event */ - EVENT_IS_OVER = 180_000, + EVENT_IS_OVER: 180_000, /** * Failed to create stage needed for stage event */ - FAILED_TO_BUILD_STAGE = 180_002, + FAILED_TO_BUILD_STAGE: 180_002, /** * Message was blocked by automatic moderation */ - AUTOMOD_BLOCKED_MESSAGE = 200_000, + AUTOMOD_BLOCKED_MESSAGE: 200_000, /** * Title was blocked by automatic moderation */ - AUTOMOD_BLOCKED_TITLE = 200_001, + AUTOMOD_BLOCKED_TITLE: 200_001, /** * Webhooks posted to forum channels must have a thread_name or thread_id */ - MISSING_NAME_OR_ID = 220_001, + MISSING_NAME_OR_ID: 220_001, /** * Webhooks posted to forum channels cannot have both a thread_name and thread_id */ - CANNOT_HAVE_BOTH_NAME_AND_ID = 220_002, + CANNOT_HAVE_BOTH_NAME_AND_ID: 220_002, /** * Webhooks can only create threads in forum channels */ - CANNOT_CREATE_THREAD_OUTSIDE_OF_FORUM = 220_003, + CANNOT_CREATE_THREAD_OUTSIDE_OF_FORUM: 220_003, /** * Webhook services cannot be used in forum channels */ - CANNOT_USE_IN_FORUM = 220_004, + CANNOT_USE_IN_FORUM: 220_004, /** * Message blocked by harmful links filter */ - AUTOMOD_BLOCKED_LINK = 240_000, -} + AUTOMOD_BLOCKED_LINK: 240_000, +} as const; diff --git a/src/helpers/HttpStatusCode.ts b/src/helpers/HttpStatusCode.ts index ed8eb841..dd95d6d1 100644 --- a/src/helpers/HttpStatusCode.ts +++ b/src/helpers/HttpStatusCode.ts @@ -6,7 +6,7 @@ * Hypertext Transfer Protocol (HTTP) response status codes. * @see https://en.wikipedia.org/wiki/List_of_HTTP_status_codes */ -export enum HttpStatusCode { +export const HttpStatusCode = { /** * The server has received the request headers and the client should proceed to send the request body * (in the case of a request for which a body needs to be sent; for example, a POST request). @@ -14,19 +14,19 @@ export enum HttpStatusCode { * To have a server check the request's headers, a client must send Expect: 100-continue as a header in its initial request * and receive a 100 Continue status code in response before sending the body. The response 417 Expectation Failed indicates the request should not be continued. */ - CONTINUE = 100, + CONTINUE: 100, /** * The requester has asked the server to switch protocols and the server has agreed to do so. */ - SWITCHING_PROTOCOLS = 101, + SWITCHING_PROTOCOLS: 101, /** * A WebDAV request may contain many sub-requests involving file operations, requiring a long time to complete the request. * This code indicates that the server has received and is processing the request, but no response is available yet. * This prevents the client from timing out and assuming the request was lost. */ - PROCESSING = 102, + PROCESSING: 102, /** * Standard response for successful HTTP requests. @@ -34,73 +34,73 @@ export enum HttpStatusCode { * In a GET request, the response will contain an entity corresponding to the requested resource. * In a POST request, the response will contain an entity describing or containing the result of the action. */ - OK = 200, + OK: 200, /** * The request has been fulfilled, resulting in the creation of a new resource. */ - CREATED = 201, + CREATED: 201, /** * The request has been accepted for processing, but the processing has not been completed. * The request might or might not be eventually acted upon, and may be disallowed when processing occurs. */ - ACCEPTED = 202, + ACCEPTED: 202, /** * SINCE HTTP/1.1 * The server is a transforming proxy that received a 200 OK from its origin, * but is returning a modified version of the origin's response. */ - NON_AUTHORITATIVE_INFORMATION = 203, + NON_AUTHORITATIVE_INFORMATION: 203, /** * The server successfully processed the request and is not returning any content. */ - NO_CONTENT = 204, + NO_CONTENT: 204, /** * The server successfully processed the request, but is not returning any content. * Unlike a 204 response, this response requires that the requester reset the document view. */ - RESET_CONTENT = 205, + RESET_CONTENT: 205, /** * The server is delivering only part of the resource (byte serving) due to a range header sent by the client. * The range header is used by HTTP clients to enable resuming of interrupted downloads, * or split a download into multiple simultaneous streams. */ - PARTIAL_CONTENT = 206, + PARTIAL_CONTENT: 206, /** * The message body that follows is an XML message and can contain a number of separate response codes, * depending on how many sub-requests were made. */ - MULTI_STATUS = 207, + MULTI_STATUS: 207, /** * The members of a DAV binding have already been enumerated in a preceding part of the (multistatus) response, * and are not being included again. */ - ALREADY_REPORTED = 208, + ALREADY_REPORTED: 208, /** * The server has fulfilled a request for the resource, * and the response is a representation of the result of one or more instance-manipulations applied to the current instance. */ - IM_USED = 226, + IM_USED: 226, /** * Indicates multiple options for the resource from which the client may choose (via agent-driven content negotiation). * For example, this code could be used to present multiple video format options, * to list files with different filename extensions, or to suggest word-sense disambiguation. */ - MULTIPLE_CHOICES = 300, + MULTIPLE_CHOICES: 300, /** * This and all future requests should be directed to the given URI. */ - MOVED_PERMANENTLY = 301, + MOVED_PERMANENTLY: 301, /** * This is an example of industry practice contradicting the standard. @@ -110,7 +110,7 @@ export enum HttpStatusCode { * to distinguish between the two behaviours. However, some Web applications and frameworks * use the 302 status code as if it were the 303. */ - FOUND = 302, + FOUND: 302, /** * SINCE HTTP/1.1 @@ -118,25 +118,25 @@ export enum HttpStatusCode { * When received in response to a POST (or PUT/DELETE), the client should presume that * the server has received the data and should issue a redirect with a separate GET message. */ - SEE_OTHER = 303, + SEE_OTHER: 303, /** * Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-None-Match. * In such case, there is no need to retransmit the resource since the client still has a previously-downloaded copy. */ - NOT_MODIFIED = 304, + NOT_MODIFIED: 304, /** * SINCE HTTP/1.1 * The requested resource is available only through a proxy, the address for which is provided in the response. * Many HTTP clients (such as Mozilla and Internet Explorer) do not correctly handle responses with this status code, primarily for security reasons. */ - USE_PROXY = 305, + USE_PROXY: 305, /** * No longer used. Originally meant "Subsequent requests should use the specified proxy." */ - SWITCH_PROXY = 306, + SWITCH_PROXY: 306, /** * SINCE HTTP/1.1 @@ -144,20 +144,20 @@ export enum HttpStatusCode { * In contrast to how 302 was historically implemented, the request method is not allowed to be changed when reissuing the original request. * For example, a POST request should be repeated using another POST request. */ - TEMPORARY_REDIRECT = 307, + TEMPORARY_REDIRECT: 307, /** * The request and all future requests should be repeated using another URI. * 307 and 308 parallel the behaviors of 302 and 301, but do not allow the HTTP method to change. * So, for example, submitting a form to a permanently redirected resource may continue smoothly. */ - PERMANENT_REDIRECT = 308, + PERMANENT_REDIRECT: 308, /** * The server cannot or will not process the request due to an apparent client error * (e.g., malformed request syntax, too large size, invalid request message framing, or deceptive request routing). */ - BAD_REQUEST = 400, + BAD_REQUEST: 400, /** * Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet @@ -165,55 +165,55 @@ export enum HttpStatusCode { * requested resource. See Basic access authentication and Digest access authentication. 401 semantically means * "unauthenticated",i.e. the user does not have the necessary credentials. */ - UNAUTHORIZED = 401, + UNAUTHORIZED: 401, /** * Reserved for future use. The original intention was that this code might be used as part of some form of digital * cash or micro payment scheme, but that has not happened, and this code is not usually used. * Google Developers API uses this status if a particular developer has exceeded the daily limit on requests. */ - PAYMENT_REQUIRED = 402, + PAYMENT_REQUIRED: 402, /** * The request was valid, but the server is refusing action. * The user might not have the necessary permissions for a resource. */ - FORBIDDEN = 403, + FORBIDDEN: 403, /** * The requested resource could not be found but may be available in the future. * Subsequent requests by the client are permissible. */ - NOT_FOUND = 404, + NOT_FOUND: 404, /** * A request method is not supported for the requested resource; * for example, a GET request on a form that requires data to be presented via POST, or a PUT request on a read-only resource. */ - METHOD_NOT_ALLOWED = 405, + METHOD_NOT_ALLOWED: 405, /** * The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request. */ - NOT_ACCEPTABLE = 406, + NOT_ACCEPTABLE: 406, /** * The client must first authenticate itself with the proxy. */ - PROXY_AUTHENTICATION_REQUIRED = 407, + PROXY_AUTHENTICATION_REQUIRED: 407, /** * The server timed out waiting for the request. * According to HTTP specifications: * "The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time." */ - REQUEST_TIMEOUT = 408, + REQUEST_TIMEOUT: 408, /** * Indicates that the request could not be processed because of conflict in the request, * such as an edit conflict between multiple simultaneous updates. */ - CONFLICT = 409, + CONFLICT: 409, /** * Indicates that the resource requested is no longer available and will not be available again. @@ -222,85 +222,85 @@ export enum HttpStatusCode { * Clients such as search engines should remove the resource from their indices. * Most use cases do not require clients and search engines to purge the resource, and a "404 Not Found" may be used instead. */ - GONE = 410, + GONE: 410, /** * The request did not specify the length of its content, which is required by the requested resource. */ - LENGTH_REQUIRED = 411, + LENGTH_REQUIRED: 411, /** * The server does not meet one of the preconditions that the requester put on the request. */ - PRECONDITION_FAILED = 412, + PRECONDITION_FAILED: 412, /** * The request is larger than the server is willing or able to process. Previously called "Request Entity Too Large". */ - PAYLOAD_TOO_LARGE = 413, + PAYLOAD_TOO_LARGE: 413, /** * The URI provided was too long for the server to process. Often the result of too much data being encoded as a query-string of a GET request, * in which case it should be converted to a POST request. * Called "Request-URI Too Long" previously. */ - URI_TOO_LONG = 414, + URI_TOO_LONG: 414, /** * The request entity has a media type which the server or resource does not support. * For example, the client uploads an image as image/svg+xml, but the server requires that images use a different format. */ - UNSUPPORTED_MEDIA_TYPE = 415, + UNSUPPORTED_MEDIA_TYPE: 415, /** * The client has asked for a portion of the file (byte serving), but the server cannot supply that portion. * For example, if the client asked for a part of the file that lies beyond the end of the file. * Called "Requested Range Not Satisfiable" previously. */ - RANGE_NOT_SATISFIABLE = 416, + RANGE_NOT_SATISFIABLE: 416, /** * The server cannot meet the requirements of the Expect request-header field. */ - EXPECTATION_FAILED = 417, + EXPECTATION_FAILED: 417, /** * This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol, * and is not expected to be implemented by actual HTTP servers. The RFC specifies this code should be returned by * teapots requested to brew coffee. This HTTP status is used as an Easter egg in some websites, including Google.com. */ - I_AM_A_TEAPOT = 418, + I_AM_A_TEAPOT: 418, /** * The request was directed at a server that is not able to produce a response (for example because a connection reuse). */ - MISDIRECTED_REQUEST = 421, + MISDIRECTED_REQUEST: 421, /** * The request was well-formed but was unable to be followed due to semantic errors. */ - UNPROCESSABLE_ENTITY = 422, + UNPROCESSABLE_ENTITY: 422, /** * The resource that is being accessed is locked. */ - LOCKED = 423, + LOCKED: 423, /** * The request failed due to failure of a previous request (e.g., a PROPPATCH). */ - FAILED_DEPENDENCY = 424, + FAILED_DEPENDENCY: 424, /** * The server is unwilling to risk processing a request that might be replayed, * which creates the potential for a replay attack. */ - TOO_EARLY = 425, + TOO_EARLY: 425, /** * The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header field. */ - UPGRADE_REQUIRED = 426, + UPGRADE_REQUIRED: 426, /** * The origin server requires the request to be conditional. @@ -308,83 +308,83 @@ export enum HttpStatusCode { * GETs a resource's state, modifies it, and PUTs it back to the server, * when meanwhile a third party has modified the state on the server, leading to a conflict." */ - PRECONDITION_REQUIRED = 428, + PRECONDITION_REQUIRED: 428, /** * The user has sent too many requests in a given amount of time. Intended for use with rate-limiting schemes. */ - TOO_MANY_REQUESTS = 429, + TOO_MANY_REQUESTS: 429, /** * The server is unwilling to process the request because either an individual header field, * or all the header fields collectively, are too large. */ - REQUEST_HEADER_FIELDS_TOO_LARGE = 431, + REQUEST_HEADER_FIELDS_TOO_LARGE: 431, /** * A server operator has received a legal demand to deny access to a resource or to a set of resources * that includes the requested resource. The code 451 was chosen as a reference to the novel Fahrenheit 451. */ - UNAVAILABLE_FOR_LEGAL_REASONS = 451, + UNAVAILABLE_FOR_LEGAL_REASONS: 451, /** * A generic error message, given when an unexpected condition was encountered and no more specific message is suitable. */ - INTERNAL_SERVER_ERROR = 500, + INTERNAL_SERVER_ERROR: 500, /** * The server either does not recognize the request method, or it lacks the ability to fulfill the request. * Usually this implies future availability (e.g., a new feature of a web-service API). */ - NOT_IMPLEMENTED = 501, + NOT_IMPLEMENTED: 501, /** * The server was acting as a gateway or proxy and received an invalid response from the upstream server. */ - BAD_GATEWAY = 502, + BAD_GATEWAY: 502, /** * The server is currently unavailable (because it is overloaded or down for maintenance). * Generally, this is a temporary state. */ - SERVICE_UNAVAILABLE = 503, + SERVICE_UNAVAILABLE: 503, /** * The server was acting as a gateway or proxy and did not receive a timely response from the upstream server. */ - GATEWAY_TIMEOUT = 504, + GATEWAY_TIMEOUT: 504, /** * The server does not support the HTTP protocol version used in the request */ - HTTP_VERSION_NOT_SUPPORTED = 505, + HTTP_VERSION_NOT_SUPPORTED: 505, /** * Transparent content negotiation for the request results in a circular reference. */ - VARIANT_ALSO_NEGOTIATES = 506, + VARIANT_ALSO_NEGOTIATES: 506, /** * The server is unable to store the representation needed to complete the request. */ - INSUFFICIENT_STORAGE = 507, + INSUFFICIENT_STORAGE: 507, /** * The server detected an infinite loop while processing the request. */ - LOOP_DETECTED = 508, + LOOP_DETECTED: 508, /** * Further extensions to the request are required for the server to fulfill it. */ - NOT_EXTENDED = 510, + NOT_EXTENDED: 510, /** * The client needs to authenticate to gain network access. * Intended for use by intercepting proxies used to control access to the network (e.g., "captive portals" used * to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot). */ - NETWORK_AUTHENTICATION_REQUIRED = 511, + NETWORK_AUTHENTICATION_REQUIRED: 511, /** * An unofficial server error specific to Cloudflare and Pantheon. @@ -396,14 +396,16 @@ export enum HttpStatusCode { * * @see https://http.dev/530 */ - SITE_FROZEN = 530, -} + SITE_FROZEN: 530, +} as const; +export type HttpStatusCode = (typeof HttpStatusCode)[keyof typeof HttpStatusCode]; /** * Returns a brief textual description of the status code. */ -export function describeCode(code: HttpStatusCode | number): string { +export function describeCode(code: number): string { // Since HTTP clients no longer populate the `statusText` field, we must provide our own. // It is taking me every ounce of willpower not to paste in my switch of pony puns here. - return HttpStatusCode[code] ?? `HTTP_${code}`; + const label = Object.entries(HttpStatusCode).find(([, v]) => v === code)?.[0]; + return label ?? `HTTP_${code}`; } diff --git a/src/helpers/fetch.ts b/src/helpers/fetch.ts index f2fceab0..87bd62d9 100644 --- a/src/helpers/fetch.ts +++ b/src/helpers/fetch.ts @@ -25,7 +25,7 @@ export async function fetchJson( ): Promise { const res = await fetch(input, init); - const status: HttpStatusCode = res.status; + const status = res.status as HttpStatusCode; if (status !== HttpStatusCode.OK) { throw new NetworkError(status); } diff --git a/tsconfig.json b/tsconfig.json index bc586254..99fcc7bc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,7 @@ "allowImportingTsExtensions": true, "module": "nodenext", + "erasableSyntaxOnly": true, "verbatimModuleSyntax": true, } } From e74a598094bb5a81d0de45a827d39a8d874d1ed8 Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Wed, 13 May 2026 04:44:13 -0600 Subject: [PATCH 04/12] Run main.ts directly --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index e6ab33f1..d4b67ba1 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "license": "0BSD", "author": "BYU CS", "type": "module", - "main": "./dist/main.js", + "main": "src/main.ts", "scripts": { "build": "npm run db:generate && rm -rf dist && ./node_modules/.bin/tsc -p tsconfig.build.json", "commands:deploy": "node --env-file=.env . --deploy # TODO: Replace these with automatic command deployment", @@ -30,7 +30,7 @@ "db:introspect": "./node_modules/.bin/prisma db pull", "db:migrate": "./node_modules/.bin/prisma migrate deploy", "db:migrations:generate": "./node_modules/.bin/prisma migrate dev --create-only", - "dev": "NODE_ENV=development node --watch --env-file=.env ./dist/main.js", + "dev": "NODE_ENV=development node --watch --env-file=.env .", "docker": "npm run docker:image && npm run docker:cleanup && npm run docker:container", "docker:cleanup": "docker system prune --force --filter='label=cs-bot'", "docker:container": "docker run --tty --interactive --rm --mount type=bind,source=$PWD,destination=/cs-bot cs-bot-image", @@ -40,8 +40,8 @@ "lint:fix": "npm run lint -- --fix", "release": "node ./scripts/release.ts", "setup": "npm ci && npm run export-version && npm run db:migrate && npm run build --omit=dev && npm run commands:deploy", - "start": "node --env-file=.env ./dist/main.js", "test": "./node_modules/.bin/vitest" + "start": "node --env-file=.env .", }, "dependencies": { "@discordjs/voice": "0.19.2", From 53f39b2f01bed5fce00757c5a8dfbc46a32013b0 Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Wed, 13 May 2026 04:45:37 -0600 Subject: [PATCH 05/12] Replace build step with type-checking only --- .github/workflows/ci.yml | 10 +++++----- README.md | 4 +--- package.json | 6 +++--- tsconfig.build.json | 11 ----------- tsconfig.json | 2 ++ 5 files changed, 11 insertions(+), 22 deletions(-) delete mode 100644 tsconfig.build.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7ac0cb8..c5ce5efb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,5 @@ name: CI -# Lints, builds, tests, and checks versions of the project when a pull request is opened or merged +# Lints, type-checks, tests, and checks versions of the project when a pull request is opened or merged on: pull_request: @@ -41,8 +41,8 @@ jobs: - name: Lint run: npm run lint - build: - name: Build + type-check: + name: Type check runs-on: ubuntu-latest @@ -68,8 +68,8 @@ jobs: - name: Generate version run: npm run export-version - - name: Build - run: npm run build + - name: Type check + run: npm run type-check test: name: Test diff --git a/README.md b/README.md index 6e7c5be0..587ba51e 100644 --- a/README.md +++ b/README.md @@ -215,7 +215,7 @@ The docker script will take care of every part of the docker development process ### Build the bot -Be sure to install dependencies, run a quick lint to generate needed files, compile the source, and deploy commands. Here's a handy command to do all of that: +Be sure to install dependencies, generate necessary files, initialize the database, and deploy commands. Here's a handy command to do all of that: ```sh $ npm run setup @@ -270,8 +270,6 @@ If you have added new code, you should write new unit tests to cover all the cod For development purposes: ```sh -$ node --env-file=.env . -# or $ npm run dev ``` diff --git a/package.json b/package.json index d4b67ba1..bad0ecab 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "type": "module", "main": "src/main.ts", "scripts": { - "build": "npm run db:generate && rm -rf dist && ./node_modules/.bin/tsc -p tsconfig.build.json", "commands:deploy": "node --env-file=.env . --deploy # TODO: Replace these with automatic command deployment", "commands:revoke": "node --env-file=.env . --revoke", "db:generate": "./node_modules/.bin/prisma generate --no-hints --schema ./prisma/schema.prisma", @@ -39,9 +38,10 @@ "lint": "./node_modules/.bin/eslint --flag unstable_native_nodejs_ts_config", "lint:fix": "npm run lint -- --fix", "release": "node ./scripts/release.ts", - "setup": "npm ci && npm run export-version && npm run db:migrate && npm run build --omit=dev && npm run commands:deploy", - "test": "./node_modules/.bin/vitest" + "setup": "npm ci && npm run export-version && npm run db:migrate && npm run db:generate && npm run commands:deploy", "start": "node --env-file=.env .", + "test": "./node_modules/.bin/vitest", + "type-check": "./node_modules/.bin/tsc --noEmit" }, "dependencies": { "@discordjs/voice": "0.19.2", diff --git a/tsconfig.build.json b/tsconfig.build.json deleted file mode 100644 index 45c7cfa5..00000000 --- a/tsconfig.build.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "./tsconfig.json", - "include": ["src"], - "exclude": ["**/*.test.*", "**/__mocks__/**"], - "compilerOptions": { - "rootDir": "src", - - "outDir": "dist", - "sourceMap": true, - } -} diff --git a/tsconfig.json b/tsconfig.json index 99fcc7bc..1d366225 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,8 @@ "allowImportingTsExtensions": true, "module": "nodenext", + "noEmit": true, + "erasableSyntaxOnly": true, "verbatimModuleSyntax": true, } From 2f4143faa299b0d2c23eedd80b70d4a341136ab6 Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Wed, 13 May 2026 04:46:24 -0600 Subject: [PATCH 06/12] Remove references to dist --- .gitignore | 1 - .vscode/settings.json | 5 ++--- eslint.config.ts | 2 +- src/events/interactionCreate.ts | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index e5133124..aac7b5ed 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ logs # Generated files node_modules db -dist coverage src/constants/version.ts tmp diff --git a/.vscode/settings.json b/.vscode/settings.json index 09c47f21..dc02a2b1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,13 +1,12 @@ { - "typescript.tsdk": "node_modules/typescript/lib", + "js/ts.tsdk.path": "node_modules/typescript/lib", "editor.detectIndentation": false, "editor.insertSpaces": false, "git.branchProtection": ["main"], - "todo-tree.filtering.excludeGlobs": ["**/dist/**", "**/node_modules/**", "coverage/**"], + "todo-tree.filtering.excludeGlobs": ["**/node_modules/**", "coverage/**"], "files.eol": "auto", "terminal.integrated.defaultProfile.windows": "Git Bash", "editor.formatOnSave": true, - "eslint.useFlatConfig": true, "yaml.schemas": { "https://json.schemastore.org/github-workflow.json": "**/workflows/*.yml" } diff --git a/eslint.config.ts b/eslint.config.ts index f4075a54..9df05515 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -13,7 +13,7 @@ import unicorn from 'eslint-plugin-unicorn'; export default defineConfig( { files: ['**/*.{m,c,}{js,ts}{x,}'] }, - globalIgnores(['dist', 'coverage', 'src/constants/version.ts']), + globalIgnores(['coverage', 'src/constants/version.ts']), { linterOptions: { reportUnusedDisableDirectives: 'error', diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts index 4cb7e19e..84586972 100644 --- a/src/events/interactionCreate.ts +++ b/src/events/interactionCreate.ts @@ -267,7 +267,7 @@ export async function sendErrorMessage( ): Promise { const errorMessage = error_ instanceof Error ? error_.message : JSON.stringify(error_); // for privacy, strip out any mention of the internal directory - const privateDir = __dirname.slice(0, __dirname.lastIndexOf('dist')); + const privateDir = __dirname.slice(0, __dirname.lastIndexOf('src')); const safeErrorMessage = errorMessage.replace(privateDir, '...'); const embed = new EmbedBuilder().setTitle('Error'); From d021ac5f72f9d69826c4533d8bf332882a34313b Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Wed, 13 May 2026 04:47:19 -0600 Subject: [PATCH 07/12] Update Dockerfile --- Dockerfile | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Dockerfile b/Dockerfile index 991b8928..ff243176 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,4 @@ -FROM node:24-slim as builder - -RUN apt-get update -y -RUN apt-get install -y openssl +FROM node:24-slim AS builder WORKDIR /app @@ -9,20 +6,21 @@ COPY . . RUN npm ci RUN npm run export-version -RUN npm run build --omit=dev -FROM node:24-slim as runner +FROM node:24-slim AS runner + +ENV NODE_ENV=production -RUN apt-get update -y RUN apt-get install -y openssl WORKDIR /app -COPY --from=builder /app/dist/ ./dist/ -COPY --from=builder /app/res/ ./res/ +COPY --exclude=**/*.test.* --exclude=**/__mocks__/** src ./src/ +COPY --from=builder /app/src/constants/version.ts ./src/constants/ +COPY res ./res/ COPY package*.json ./ COPY prisma prisma/ -COPY scripts/launch_in_docker.sh . +COPY scripts/launch_in_docker.sh ./scripts/ RUN npm ci --omit=dev @@ -30,4 +28,4 @@ RUN npm ci --omit=dev ENV DATABASE_URL="file:/db/db.sqlite" # Using bash here to get consistent behavior and configurations -CMD ["bash", "/app/launch_in_docker.sh"] +CMD ["bash", "/app/scripts/launch_in_docker.sh"] From 63669f532fd95a4fc63f7330bcdef97046c96aee Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Wed, 13 May 2026 04:49:08 -0600 Subject: [PATCH 08/12] Address new type errors --- eslint.config.ts | 14 ++++++++++++++ tsconfig.json | 3 +++ 2 files changed, 17 insertions(+) diff --git a/eslint.config.ts b/eslint.config.ts index 9df05515..21fc4855 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -53,6 +53,20 @@ export default defineConfig( }, }, + // FIXME Test files cannot be type-checked (see tsconfig.json) + { + files: ['**/*.test.ts'], + linterOptions: { + reportUnusedDisableDirectives: 'off', + }, + languageOptions: { + parserOptions: { + projectService: false, + }, + }, + extends: [typescriptConfigs.disableTypeChecked], + }, + stylistic.configs['disable-legacy'], stylistic.configs.customize({ braceStyle: '1tbs', diff --git a/tsconfig.json b/tsconfig.json index 1d366225..2ed146b5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,5 @@ { + "exclude": ["**/*.test.*"], // FIXME Test files are riddled with type errors "compilerOptions": { // "exactOptionalPropertyTypes": true, // Correct but annoying "noFallthroughCasesInSwitch": true, @@ -16,5 +17,7 @@ "erasableSyntaxOnly": true, "verbatimModuleSyntax": true, + + "skipLibCheck": true, // https://github.com/oscarotero/keep-a-changelog/issues/67 } } From 4285336a14bbe80d226b40112dad769b88462e73 Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Wed, 13 May 2026 04:59:27 -0600 Subject: [PATCH 09/12] Delete nodemon.json --- nodemon.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 nodemon.json diff --git a/nodemon.json b/nodemon.json deleted file mode 100644 index 2213924f..00000000 --- a/nodemon.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "delay": "1000" -} From 2b8dc3165f966368782cb944c82fb87e54029fae Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Wed, 13 May 2026 05:11:23 -0600 Subject: [PATCH 10/12] Update CHANGELOG.md --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bfcf58a..d965f768 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,11 +14,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Refactor GitHub workflows - **Breaking:** set minimum Node version to `^22.18.0 || >=24.0.0` - **Breaking:** upgrade to Node 24 -- Replace `nodemon` with `node --watch` for the `npm run dev` script - Use `clientReady` event instead of `ready` to fix deprecation warning - Use `Events` enum for event handler names -- Replace `tsx` with native Node for `release.ts` script -- Replace `jiti` with native Node for loading `eslint.config.ts` +- Replace `nodemon` with `node --watch` for the `npm run dev` script +- Replace `tsx` with native Node.js for `release.ts` script +- Replace `jiti` with native Node.js for loading `eslint.config.ts` +- Replace build step with native Node.js for running the bot ### Removed From 1b6fee870fd449f08737cae825426ea80740c6e6 Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Fri, 22 May 2026 02:16:42 -0600 Subject: [PATCH 11/12] Revert "Build(deps-dev): Bump keep-a-changelog from 3.0.2 to 3.0.3 (#563)" This reverts commit 296a91e13757fe1a9503c476b320ed6f4632faf7. --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index ea006aee..5d960219 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,7 @@ "eslint-plugin-promise": "7.3.0", "eslint-plugin-unicorn": "64.0.0", "genversion": "3.2.0", - "keep-a-changelog": "3.0.3", + "keep-a-changelog": "3.0.2", "prettier": "3.8.3", "prettier-plugin-prisma": "5.0.0", "prisma": "6.9.0", @@ -4930,9 +4930,9 @@ } }, "node_modules/keep-a-changelog": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/keep-a-changelog/-/keep-a-changelog-3.0.3.tgz", - "integrity": "sha512-eLTf1egh0t+RSe8JTVZwebsDQczPnzcNcslnCjFrcvjcZFgkYygEPWUjVMFwizh55+WKE+UP/dTtpPgrCUYT0w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/keep-a-changelog/-/keep-a-changelog-3.0.2.tgz", + "integrity": "sha512-MKk4RWduGopP7MoA8bkzdXQk9CV6cbqNjMzpClM/mA2kT+jsbvO6co2h3UuYPe6/bX/UITemzLBNEanplrIOmQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index bad0ecab..9d4303b7 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "eslint-plugin-promise": "7.3.0", "eslint-plugin-unicorn": "64.0.0", "genversion": "3.2.0", - "keep-a-changelog": "3.0.3", + "keep-a-changelog": "3.0.2", "prettier": "3.8.3", "prettier-plugin-prisma": "5.0.0", "prisma": "6.9.0", From 8b953e43aa8613ce5eb8eb41979305316cdf0a00 Mon Sep 17 00:00:00 2001 From: Justin McBride Date: Fri, 22 May 2026 02:18:02 -0600 Subject: [PATCH 12/12] Remove source-map-support --- package-lock.json | 28 ---------------------------- package.json | 2 -- src/main.ts | 2 -- 3 files changed, 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5d960219..26b3ba95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "dectalk-tts": "1.0.1", "discord.js": "14.26.4", "ffmpeg-static": "5.3.0", - "source-map-support": "0.5.21", "superstruct": "2.0.2", "tmp": "0.2.5" }, @@ -22,7 +21,6 @@ "@stylistic/eslint-plugin": "5.10.0", "@types/node": "24.10.9", "@types/semver": "7.7.1", - "@types/source-map-support": "0.5.10", "@types/tmp": "0.2.6", "@vitest/coverage-istanbul": "4.1.6", "eslint": "9.39.2", @@ -1631,15 +1629,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/source-map-support": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@types/source-map-support/-/source-map-support-0.5.10.tgz", - "integrity": "sha512-tgVP2H469x9zq34Z0m/fgPewGhg/MLClalNOiPIzQlXrSS2YrKu/xCdSCKnEDwkFha51VKEKB6A9wW26/ZNwzA==", - "dev": true, - "dependencies": { - "source-map": "^0.6.0" - } - }, "node_modules/@types/tmp": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz", @@ -6234,14 +6223,6 @@ "dev": true, "license": "ISC" }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -6251,15 +6232,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/stable-hash-x": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.1.1.tgz", diff --git a/package.json b/package.json index 9d4303b7..0b46e5e9 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,6 @@ "dectalk-tts": "1.0.1", "discord.js": "14.26.4", "ffmpeg-static": "5.3.0", - "source-map-support": "0.5.21", "superstruct": "2.0.2", "tmp": "0.2.5" }, @@ -57,7 +56,6 @@ "@stylistic/eslint-plugin": "5.10.0", "@types/node": "24.10.9", "@types/semver": "7.7.1", - "@types/source-map-support": "0.5.10", "@types/tmp": "0.2.6", "@vitest/coverage-istanbul": "4.1.6", "eslint": "9.39.2", diff --git a/src/main.ts b/src/main.ts index e1e76dc4..7d252e45 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,3 @@ -import 'source-map-support/register.js'; - import { ActivityType, Client, GatewayIntentBits, Partials } from 'discord.js'; import { registerEventHandlers } from './events/index.ts';