Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -41,8 +41,8 @@ jobs:
- name: Lint
run: npm run lint

build:
name: Build
type-check:
name: Type check

runs-on: ubuntu-latest

Expand All @@ -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
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ logs
# Generated files
node_modules
db
dist
coverage
src/constants/version.ts
tmp
Expand Down
5 changes: 2 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -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"
}
Expand Down
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ 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
- 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

Expand Down
20 changes: 9 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
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

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
Copy link
Copy Markdown
Contributor

@AverageHelper AverageHelper May 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about removing this line. Shouldn't we update the package lists before trying to install packages?

Copy link
Copy Markdown
Contributor Author

@JstnMcBrd JstnMcBrd May 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only when you want the most recent package versions, which is unnecessary for our use case (simply installing any version of openssl). Relying on auto-updates from node:24-slim is sufficient.

Each line of a Dockerfile is an additional layer, so I figure it's better to cut it.

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

# Path internal to container; use `volumes` config to specify real system path of `/db/`
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"]
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
```

Expand Down
16 changes: 15 additions & 1 deletion eslint.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down
3 changes: 0 additions & 3 deletions nodemon.json

This file was deleted.

38 changes: 5 additions & 33 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 8 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
"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",
"commands:revoke": "node --env-file=.env . --revoke",
"db:generate": "./node_modules/.bin/prisma generate --no-hints --schema ./prisma/schema.prisma",
Expand All @@ -30,7 +29,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",
Expand All @@ -39,25 +38,24 @@
"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",
"start": "node --env-file=.env ./dist/main.js",
"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",
"@prisma/client": "6.13.0",
"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"
},
"devDependencies": {
"@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",
Expand All @@ -69,7 +67,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",
Expand All @@ -80,12 +78,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"
}
}
2 changes: 1 addition & 1 deletion src/__mocks__/logger.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/buttons/hangmanLessButton.test.ts
Original file line number Diff line number Diff line change
@@ -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<ButtonContext['interaction']['update']>();
Expand Down
2 changes: 1 addition & 1 deletion src/buttons/hangmanLessButton.ts
Original file line number Diff line number Diff line change
@@ -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 = {
Expand Down
4 changes: 2 additions & 2 deletions src/buttons/hangmanLetterButton.test.ts
Original file line number Diff line number Diff line change
@@ -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<ButtonContext['interaction']['update']>();
Expand Down
6 changes: 3 additions & 3 deletions src/buttons/hangmanLetterButton.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -36,7 +36,7 @@ export function hangmanLetterButton(letter: Letter): Button {
return {
customId,
async execute({ interaction, message }): Promise<void> {
const { buildEvilHangmanMessage } = await import('../evilHangman/evilHangmanMessage.js');
const { buildEvilHangmanMessage } = await import('../evilHangman/evilHangmanMessage.ts');
const game = parseEvilHangmanMessage(message);

const guessErrorMessage = game.checkGuess(letter);
Expand Down
Loading