Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
888ba83
Normalise formatting to 2-space indentation
BrentOates Oct 5, 2026
8d8b0ee
Add tests, typed lint, strictNullChecks and env validation
BrentOates Oct 5, 2026
908ffaf
Add command/event framework, loader and dispatcher; port commands and…
BrentOates Oct 5, 2026
3b7b95d
Add framework, dispatcher and loader tests
BrentOates Oct 5, 2026
27189f0
Add audit, member, birthday, scheduler and retention services
BrentOates Oct 5, 2026
1405404
Fix post-merge audit return type and ignore .claude in lint
BrentOates Oct 5, 2026
ea486f7
Add umzug migrations: baseline, UserProfile unique index, access trac…
BrentOates Oct 5, 2026
402a0cb
Add transactional guild purge, trim services, drop underscore
BrentOates Oct 5, 2026
88b9f42
Rework moderation commands and message events
BrentOates Oct 5, 2026
594a27c
Add BirthdayService and DataCheckService, rework birthday commands, p…
BrentOates Oct 5, 2026
9847a00
Add OnboardingService and WelcomeImage; rework welcome, newroles, deb…
BrentOates Oct 5, 2026
7a28666
Improve /about output
BrentOates Oct 5, 2026
c876fcf
Remove legacy files; move domain services to src/services and Command…
BrentOates Oct 5, 2026
3a987a8
Normalise wording and style, fix about embed, drop redundant @types/v…
BrentOates Oct 5, 2026
04b7689
Rewrite README for v3
BrentOates Oct 5, 2026
9a00cfb
Replace Sequelize schema and umzug with Drizzle schema and a sync SQL…
BrentOates Oct 5, 2026
24d7263
Update tests, service seam and README for Drizzle; prune stale overrides
BrentOates Oct 5, 2026
ab9c918
Switch to ESM and native TypeScript execution; static registry; croner
BrentOates Oct 5, 2026
cc070b0
Run node directly in Docker and gate publish on tests
BrentOates Oct 5, 2026
b4f9d70
Rename NovaClient to DingirClient and reorganise commands and db dire…
BrentOates Oct 5, 2026
0cc6f43
Introduce App composition root and pass dependencies explicitly
BrentOates Oct 5, 2026
9bc7be7
Add UserError and throw it for command validation failures
BrentOates Oct 5, 2026
bd2136e
Consolidate test fakes into typed factories
BrentOates Oct 5, 2026
2d80583
Defer command replies before loading server config
BrentOates Oct 5, 2026
c7fa062
Cache server configs per app and invalidate on writes
BrentOates Oct 5, 2026
dd2e7ad
Register slash commands only when their hash changes and add a deploy…
BrentOates Oct 5, 2026
6565550
Install process-level crash and signal handlers with bounded shutdown
BrentOates Oct 5, 2026
f1ad314
Replace console logger with pino structured logging and add LOG_LEVEL
BrentOates Oct 5, 2026
dbd18ae
Enable strict TypeScript options and disallow explicit any
BrentOates Oct 5, 2026
9ae0697
Add coverage thresholds and run them in CI
BrentOates Oct 5, 2026
e99794c
Upgrade to TypeScript 7
BrentOates Oct 5, 2026
ccc4f7d
Replace ESLint with oxlint (type-aware via oxlint-tsgolint)
BrentOates Oct 5, 2026
6f71571
Add oxfmt config and format/check scripts
BrentOates Oct 5, 2026
e2c8d46
Format with oxfmt
BrentOates Oct 5, 2026
6c6dcd9
Update dependency overrides for audit
BrentOates Oct 5, 2026
433cd53
Run format, lint, typecheck and coverage in CI; update README tooling…
BrentOates Oct 5, 2026
e45d2a3
Refresh README for the v3 toolchain
BrentOates Oct 5, 2026
7fefd8d
Disable install scripts so native deps use prebuilt binaries
BrentOates Oct 5, 2026
d7e278e
Draw a thin avatar ring with a translucent backdrop on welcome cards
BrentOates Oct 5, 2026
6436af6
Skip onboarding for bots while still auditing their join
BrentOates Oct 6, 2026
cff4834
Only report birthday cleared when one was actually set
BrentOates Oct 6, 2026
1d3fc37
Force-fetch partial cached members and show unknown join time
BrentOates Oct 6, 2026
1a5fd2d
Avoid a duplicate audit when onboarding immediately on join
BrentOates Oct 6, 2026
e26ba60
Fix README boolean setting tables to match the real subcommands
BrentOates Oct 6, 2026
155d371
Restore CI job name required by branch protection
BrentOates Oct 6, 2026
c117cbc
Validate and bound welcome message length after {member} expansion
BrentOates Oct 6, 2026
5442f25
Onboard members completing screening when the old state is unknown
BrentOates Oct 6, 2026
e4406f8
Scope the command registration hash by application id
BrentOates Oct 6, 2026
b7bb39d
Backfill NULL activity scores and drop unusable UserProfiles rows
BrentOates Oct 6, 2026
07d880a
Correct README and add 2.x upgrade notes
BrentOates Oct 6, 2026
8a2d9a6
Persist onboarding completion and gate unknown-state onboarding on it
BrentOates Oct 6, 2026
624ebe8
Create the new birthday calendar before removing the old one
BrentOates Oct 6, 2026
37028bc
Defer routes that call Discord before replying
BrentOates Oct 6, 2026
77f669d
Clear stale commands when the registration scope changes
BrentOates Oct 6, 2026
f22f275
Snapshot profiles before fetching members in the data check
BrentOates Oct 6, 2026
01e6d44
Document onboarding tracking, scope cleanup and calendar recreation
BrentOates Oct 6, 2026
fcdf9e1
Add screeningPendingAt column and service functions
BrentOates Oct 6, 2026
8660f34
Require recorded pending state before onboarding from unknown member …
BrentOates Oct 6, 2026
27639d1
Document recorded screening state for onboarding
BrentOates Oct 6, 2026
676d317
Only remove the old birthday calendar once the new one is populated
BrentOates Oct 6, 2026
8c8fa2f
Keep the calendar path when deleting the message fails
BrentOates Oct 6, 2026
b5eda77
Stop the data check recreating purged server configs
BrentOates Oct 6, 2026
210f9ae
Update supported versions in SECURITY.md
BrentOates Oct 6, 2026
2949364
Validate JOB_SCHEDULE by parsing it with croner
BrentOates Oct 6, 2026
d06e501
Require Read Message History to create the birthday calendar
BrentOates Oct 6, 2026
38572ad
Treat a member join as a new screening cycle
BrentOates Oct 6, 2026
466ddf0
Specify and consolidate onboarding state handling
BrentOates Oct 6, 2026
20e3bc9
Specify birthday calendar lifecycle and harden its failure handling
BrentOates Oct 6, 2026
adecc28
Specify command registration and make scope switching robust
BrentOates Oct 6, 2026
525c1e8
Specify data retention and close its races
BrentOates Oct 6, 2026
639645a
Keep welcome previews within Discord's message limit
BrentOates Oct 6, 2026
95237e4
Report member-list gateway rate limits to the admin
BrentOates Oct 6, 2026
2036557
Cap the welcome image download while reading it
BrentOates Oct 6, 2026
59d7834
Split large birthday announcements across messages
BrentOates Oct 6, 2026
cee635a
Fix README upgrade notes and examples
BrentOates Oct 6, 2026
0b04df2
Fix welcome preview truncation edge cases
BrentOates Oct 6, 2026
5ca9732
Correct unchanged command list in upgrade notes
BrentOates Oct 6, 2026
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
8 changes: 6 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
node_modules
npm-debug.log
dist
data
tests
coverage
.env
.git
.github
docs
.claude
docs
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
22 changes: 21 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
# Required: bot token and application (client) ID from the Discord developer portal
TOKEN=
CLIENT_ID=
JOB_SCHEDULE=0 9 * * *

# Cron schedule (5 or 6 fields) for cleanup, birthday notifications and calendars
JOB_SCHEDULE=0 9 * * *

# IANA time zone used for scheduling and birthday calculations
BOT_TIMEZONE=Europe/London

# SQLite database file (directory is created if missing); use :memory: for throwaway runs
DB_PATH=data/dingir.sqlite

# Data for unreachable guilds is only purged after at least this many failed checks...
PURGE_MIN_FAILURES=3
# ...spanning at least this many days
PURGE_GRACE_DAYS=7

# Log verbosity: fatal, error, warn, info, debug or trace
LOG_LEVEL=info

# Optional: register slash commands to this guild only (instant updates during development)
# DEV_GUILD_ID=
26 changes: 13 additions & 13 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@

version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: "daily"
interval: 'daily'
labels:
- "dependencies"
- 'dependencies'
groups:
all-dependencies:
patterns:
- "*"
- '*'

- package-ecosystem: "github-actions"
directory: "/"
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: "daily"
interval: 'daily'
labels:
- "dependencies"
- 'dependencies'

- package-ecosystem: "docker"
directory: "/"
- package-ecosystem: 'docker'
directory: '/'
schedule:
interval: "daily"
interval: 'daily'
labels:
- "dependencies"
- 'dependencies'
27 changes: 18 additions & 9 deletions .github/workflows/build-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ name: Build on Tag
on:
push:
tags:
- '*'
- '*'

permissions:
checks: write
packages: write

jobs:
run-linters:
name: Run ESLint
verify:
name: Format, Lint, Typecheck and Test
runs-on: ubuntu-latest

steps:
Expand All @@ -24,18 +24,27 @@ jobs:
node-version: 24
cache: npm

# ESLint and Prettier must be in `package.json`
- name: Install Node.js dependencies
run: npm ci

- name: Audit dependencies
run: npm audit --audit-level=low

- name: Run linters
- name: Check formatting
run: npm run format:check

- name: Run linter
run: npm run lint

- name: Type check
run: npm run typecheck

- name: Run tests
run: npm run test:coverage

docker:
name: Build Docker Image
needs: verify
runs-on: ubuntu-latest

steps:
Expand All @@ -58,6 +67,6 @@ jobs:
with:
push: true
platforms: linux/amd64,linux/arm64
tags: |
ghcr.io/brentoates/dingir:${{ github.ref_name }}
ghcr.io/brentoates/dingir:latest
tags: |
ghcr.io/brentoates/dingir:${{ github.ref_name }}
ghcr.io/brentoates/dingir:latest
16 changes: 11 additions & 5 deletions .github/workflows/lint-and-build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Lint and Build
name: Format, Lint, Typecheck and Test

on:
# Trigger the workflow on push or pull request,
Expand All @@ -15,7 +15,7 @@ permissions:
checks: write

jobs:
lint-and-build:
verify:
name: Lint and Build
runs-on: ubuntu-latest

Expand All @@ -35,8 +35,14 @@ jobs:
- name: Audit dependencies
run: npm audit --audit-level=low

- name: Run linters
- name: Check formatting
run: npm run format:check

- name: Run linter
run: npm run lint

- name: Build TypeScript
run: npm run build
- name: Type check
run: npm run typecheck

- name: Run tests
run: npm run test:coverage
3 changes: 2 additions & 1 deletion .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
registry=https://registry.npmjs.org/
registry=https://registry.npmjs.org/
ignore-scripts=true
Comment thread
BrentOates marked this conversation as resolved.
11 changes: 11 additions & 0 deletions .oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"endOfLine": "lf",
"ignorePatterns": ["package-lock.json", "coverage", "data", "src/resources/**", ".claude"]
}
26 changes: 26 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["typescript", "unicorn", "import", "node", "oxc"],
"categories": { "correctness": "error" },
"env": { "node": true, "es2024": true },
"rules": {
"typescript/no-floating-promises": "error",
"typescript/no-misused-promises": "error",
"typescript/no-explicit-any": "error",
"typescript/consistent-type-imports": "error",
"eqeqeq": ["error", "always", { "null": "ignore" }],
"curly": ["error", "all"],
"no-console": "error"
},
"overrides": [
{
"files": ["tests/**/*.ts"],
"rules": { "typescript/no-floating-promises": "off" }
},
{
"files": ["src/scripts/**/*.ts"],
"rules": { "no-console": "off" }
}
],
"ignorePatterns": ["node_modules", "coverage", "data", ".claude"]
}
22 changes: 7 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
# Stage 1 - Build

FROM node:24-trixie-slim AS build
FROM node:24-trixie-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2 - Dist Only

FROM node:24-trixie-slim AS dist
WORKDIR /usr/src/app
COPY package*.json ./
COPY package*.json .npmrc ./
RUN npm ci --omit=dev
COPY --from=build /usr/src/app/dist dist
ENTRYPOINT ["npm", "start"]
COPY src ./src
RUN mkdir -p data && chown node:node data
USER node
VOLUME /usr/src/app/data
CMD ["node", "src/index.ts"]
Loading
Loading