Skip to content

jynx-labs/suppit

Repository files navigation

suppit

Two-way sync between a Discord bug-report forum and GitHub issues.

Note

Although you can just deploy to any VPS after filling the config, I encourage forking and making any modifications you need to tailor it your server.

What it does

Trigger Effect
New forum post in Discord Opens a GitHub issue (title = post title, body includes the poster's username + content + mapped labels) and replies in-thread with the issue link
Comment in a synced thread Cross-posted to the GitHub issue, attributed to the Discord author
GitHub issue comment starting with !dc The text after !dc is posted back into the Discord thread
Forum tags changed GitHub labels reconciled to match (mapped tags only)
GitHub labels changed Discord forum tags reconciled to match (mapped tags only)
GitHub issue closed Adds the Resolved tag to the thread + a notice (thread stays open)
GitHub issue reopened Removes the Resolved tag

Architecture

Discord Gateway ──► discord.js client ──► Sync ──► GitHub (App auth)
                       (src/discord.ts)   (src/sync.ts)        ▲
                                          │                    │ webhook
GitHub  ──────────────────────────────────┴────────────── h3 ◄─┘  (src/webhook.ts)
                                          │
                                  db0/SQLite map (src/store.ts, thread ↔ issue)
  • src/discord.ts — Gateway client; discord.js owns heartbeats, RESUME, reconnection.
  • src/webhook.ts — h3 + listhen server; @octokit/webhooks verifies signatures and routes events.
  • src/sync.ts — all bidirectional logic.
  • src/tags.ts — pure tag↔label translation (unit-tested).
  • src/store.tsdb0 (better-sqlite3 connector) thread↔issue map (suppit.db).
  • src/github.ts — Octokit App client (handles installation-token refresh).
  • src/config.ts — c12 + defu: env > suppit.config.ts > defaults. src/logger.ts — consola.

Tooling: tsdown (rolldown) builds src/index.tsdist/index.mjs; deps stay external.

Setup

1. Discord application

  1. Create an app at https://discord.com/developers/applications, add a Bot.
  2. Enable the Message Content Intent (Bot → Privileged Gateway Intents).
  3. Invite with scope bot and permissions: View Channels, Send Messages, Send Messages in Threads, Manage Threads, Read Message History. (274877983744)
  4. Note the bot token, guild id, and the forum channel id. Create the forum tags you want (including a Resolved tag).

2. GitHub App

  1. Create a GitHub App (Settings → Developer settings → GitHub Apps).
  2. Permissions: Issues: Read & write. Subscribe to events: Issues, Issue comment.
  3. Webhook URL: https://<your-host>/github/webhook, with a webhook secret.
  4. Install it on the target repo; note the App ID and Installation ID.
  5. Generate a private key (.pem). Octokit accepts the PKCS#1 key as-is.

3. Configure

Copy .env.example.env and fill in every value (TAG_MAP maps Discord tag name → GitHub label). For GITHUB_APP_PRIVATE_KEY, paste the PEM with literal \n between lines, wrapped in quotes.

Non-secret values (IDs, tagMap, port) may instead live in a suppit.config.ts file — copy suppit.config.example.ts. Resolution order is env > suppit.config.ts > defaults, so env always wins. Secrets must only come from env / .env.

4. Run

pnpm install
pnpm run lint
pnpm run build && pnpm run start      # production -> dist/index.mjs

The GitHub webhook needs to reach this host. In dev, expose :3000 with a tunnel (cloudflared tunnel --url http://localhost:3000) and point the App's webhook URL at it.

Deploy

Any always-on Node host works (Railway, Fly.io, Render, a VPS, systemd, Dokploy + Railpack). It needs: outbound network for the Discord Gateway, an inbound HTTPS route to /github/webhook, and a persistent disk for the SQLite database.

Container filesystems (Railpack/Dokploy etc.) are ephemeral — anything written during a run is lost on the next deploy or restart. Mount a persistent volume and point DB_PATH at a file inside it, e.g. set DB_PATH=/data/suppit.db and mount a volume at /data in Dokploy.

Notes & limits

  • Discord forum posts allow at most 5 tags; reconciliation truncates to 5.
  • Reading ongoing comment text requires the Message Content privileged intent.
  • Only TAG_MAP-listed tags/labels are synced; anything else on either side is preserved.

About

Two-way sync between a Discord bug-report forum and GitHub issues.

Resources

Stars

Watchers

Forks

Releases

No releases published

Contributors