Skip to content

dontWatchMeCode/discord-archiver

Repository files navigation

discord-archiver

Messages-only Go Discord archiver.

Current scope:

  • MITM Discord HTTPS traffic with goproxy
  • capture GET /api/v*/channels/{channel_id}/messages
  • capture Gateway READY events from Discord websocket traffic
  • store messages, users, channels, guild ids, revisions, and attachment URLs in SQLite
  • use sqlc for 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 READY payloads
  • arbitrary REST JSON payloads are not treated as guild metadata sources

Not implemented yet:

  • websocket gateway capture
  • media/blob downloading
  • HTML or DCE exporters

Run

go run ./cmd/discord-archiver serve --listen :8080 --db ~/.local/share/discord-archiver/archive.db

This 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 :8888

On first startup, the proxy also generates a local MITM root CA next to the database:

  • ca.crt
  • ca.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.crt

certutil is usually provided by libnss3-tools.

Regenerate sqlc code

sqlc generate

Developer Workflow

Running the API and Frontend Together

The 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 :8888

The 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 dev

The 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

Regenerating the API Client

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:client

This 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 Build

Production builds embed the frontend assets directly into the Go binary for single-binary deployment:

1. Build the complete application:

make build

This runs:

  1. cd web && bun run build - Generate OpenAPI/client, typecheck, and Vite build (outputs to web/dist/)
  2. 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 :8888

The binary serves the embedded frontend for all non-API routes, with SPA fallback to index.html.

How embedding works:

  • embed.go uses //go:embed web/dist to embed the Vite build output
  • The webembed package provides Assets() and HasAssets() 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)

Make Targets

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) into bin/discord-archiver
  • make nilaway - Run NilAway static analysis

Frontend Targets

  • make frontend-build - Build the Vue frontend (typecheck + Vite build)
  • make frontend-typecheck - Run TypeScript type checking on the frontend
  • make frontend-generate - Generate the OpenAPI file and TypeScript API client
  • make frontend-dev - Start the Vite development server

Run NilAway

NilAway is tracked as a module tool dependency, so you can run it through go tool:

make nilaway

Equivalent command:

go tool nilaway -pretty-print=false -include-pkgs=github.com/dontWatchMeCode/discord-archiver -exclude-test-files ./...

About

Messages-only Go Discord archiver.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages