Messages-only Go Discord archiver.
Current scope:
- MITM Discord HTTPS traffic with
goproxy - capture
GET /api/v*/channels/{channel_id}/messages - capture Gateway
READYevents from Discord websocket traffic - store messages, users, channels, guild ids, revisions, and attachment URLs in SQLite
- use
sqlcfor all database queries
Current guild metadata behavior intentionally follows the original Python project more closely:
- guild names come from
GET /api/v*/guilds/{guild_id}/profile - guild icons and authoritative guild/channel metadata come from Gateway
READYpayloads - arbitrary REST JSON payloads are not treated as guild metadata sources
Not implemented yet:
- websocket gateway capture
- media/blob downloading
- HTML or DCE exporters
go run ./cmd/discord-archiver serve --listen :8080 --db ~/.local/share/discord-archiver/archive.dbThis starts:
- the Discord MITM proxy on
:8080 - the archive API and embedded web UI on
:8888 - the background media watcher
Then point Discord at the proxy and browse channels. Message history responses will be stored in SQLite.
You can override the API/web listener with --api-listen, for example:
go run ./cmd/discord-archiver serve --listen :8080 --api-listen :8888On first startup, the proxy also generates a local MITM root CA next to the database:
ca.crtca.key
If those files already exist, they are reused. If only one exists, startup fails so trust does not silently break.
You must trust ca.crt in the relevant client trust stores before Discord will accept the proxy certificate.
On Linux, that often means both the system trust store and the NSS database used by Chromium/Electron apps:
sudo cp ~/.local/share/discord-archiver/ca.crt /usr/local/share/ca-certificates/discord-archiver.crt
sudo update-ca-certificates
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n discord-archiver -i ~/.local/share/discord-archiver/ca.crtcertutil is usually provided by libnss3-tools.
sqlc generateThe application consists of a Go API server and a Vue frontend. During development, you run them separately:
If you want the backend stack in one process, serve now starts the proxy, API server, embedded web UI, and media watcher together. For frontend development with Vite hot reload, keep using the separate API + Vite workflow below.
1. Start the Go API server:
go run ./cmd/discord-archiver api --listen :8888The API server runs on port 8888 by default and serves:
- REST API endpoints at
/api/* - OpenAPI spec at
/api/openapi.json - API documentation UI at
/api/docs
2. In a separate terminal, start the frontend dev server:
make frontend-dev
# or: cd web && bun run devThe Vite dev server runs on port 5173 and proxies /api/* requests to the Go API at localhost:8888.
Access the development frontend at http://localhost:5173
The frontend uses Orval to generate a typed TypeScript client from a locally generated OpenAPI file.
Generate the client:
make frontend-generate
# or: cd web && bun run generate:clientThis runs go run ./cmd/discord-archiver swagger --output web/openapi.json before Orval.
Generated code is output to web/src/shared/api/generated/ and should be committed to the repository.
Production builds embed the frontend assets directly into the Go binary for single-binary deployment:
1. Build the complete application:
make buildThis runs:
cd web && bun run build- Generate OpenAPI/client, typecheck, and Vite build (outputs toweb/dist/)go build -o bin/discord-archiver ./cmd/discord-archiver- Compile Go binary with embedded assets
2. Run the production binary:
./bin/discord-archiver api --listen :8888The binary serves the embedded frontend for all non-API routes, with SPA fallback to index.html.
How embedding works:
embed.gouses//go:embed web/distto embed the Vite build output- The
webembedpackage providesAssets()andHasAssets()functions - The API server serves embedded assets for non-API routes when available
- This allows graceful fallback when assets aren't embedded (dev without frontend build)
The following make targets are available:
make check- Run all quality checks (Go tests, NilAway, frontend typecheck, frontend build)make build- Build the complete application (frontend + Go binary) intobin/discord-archivermake nilaway- Run NilAway static analysis
make frontend-build- Build the Vue frontend (typecheck + Vite build)make frontend-typecheck- Run TypeScript type checking on the frontendmake frontend-generate- Generate the OpenAPI file and TypeScript API clientmake frontend-dev- Start the Vite development server
NilAway is tracked as a module tool dependency, so you can run it through go tool:
make nilawayEquivalent command:
go tool nilaway -pretty-print=false -include-pkgs=github.com/dontWatchMeCode/discord-archiver -exclude-test-files ./...