Feature 2: Commit-Feed — Gitea-Webhook, Discord-Embeds, SQLite-Archiv

- Fastify-Webserver mit /health und /webhooks/gitea (HMAC-SHA256-Signaturprüfung, timing-safe)
- Push-Commits werden in SQLite gespeichert (Dedupe per SHA) und als Embed gepostet
- Dockerfile auf node:22-slim (glibc-Prebuilds für better-sqlite3), Port 3080 published
- README: Anleitung für Cloudflare-DNS, Nginx Proxy Manager (bot.d4rkst3r.de) und Gitea-Webhook

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 23:27:33 +02:00
co-authored by Claude Opus 4.8
parent 2b3fa3eb69
commit 46d6a3f927
11 changed files with 1357 additions and 17 deletions
+60 -8
View File
@@ -4,11 +4,11 @@ Discord-Bot + Webinterface für die EcoGame-Community.
**Features (Roadmap):**
1. ✅ Bot online + `/ping` Slash-Command
2. Commit-Feed: Gitea-Push-Webhooks → Discord-Embeds + SQLite-Archiv
2. Commit-Feed: Gitea-Push-Webhooks → Discord-Embeds + SQLite-Archiv
3. ⬜ Devlog-Archiv: tägliche Devlogs archivieren
4. ⬜ Webinterface: Discord-Login, Devlog- & Commit-Seiten
**Stack:** Node.js 20+, discord.js v14, Fastify (ab Feature 2), React (ab Feature 4), SQLite, Docker
**Stack:** Node.js 20+, discord.js v14, Fastify, React (ab Feature 4), SQLite (better-sqlite3), Docker
---
@@ -45,7 +45,55 @@ Discord-Bot + Webinterface für die EcoGame-Community.
```
cp .env.example .env
```
Dann die drei Werte eintragen. Die `.env` ist in `.gitignore` und landet nie im Repo.
Dann die Werte eintragen. Die `.env` ist in `.gitignore` und landet nie im Repo.
---
## Setup: Commit-Feed (Gitea → Discord)
### 1. Neue .env-Werte
| Variable | Woher |
|---|---|
| `COMMIT_CHANNEL_ID` | Rechtsklick auf den Ziel-Kanal in Discord → **Kanal-ID kopieren** |
| `GITEA_WEBHOOK_SECRET` | Generieren: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"` |
### 2. Öffentlicher Host im Nginx Proxy Manager (`bot.d4rkst3r.de`)
**Cloudflare (DNS):**
1. Cloudflare-Dashboard → Zone `d4rkst3r.de`**DNS**
2. Neuen Record anlegen: Typ **CNAME**, Name `bot`, Ziel wie bei den bestehenden
Hosts (z. B. `d4rkst3r.de`), Proxy-Status **Proxied** (orange Wolke)
**Nginx Proxy Manager:**
1. NPM öffnen → **Hosts****Proxy Hosts****Add Proxy Host**
2. Tab **Details:**
- Domain Names: `bot.d4rkst3r.de`
- Scheme: `http`
- Forward Hostname / IP: `host.docker.internal`
(NPM läuft im Container, der Bot published Port 3080 auf dem Windows-Host)
- Forward Port: `3080`
- ✅ Block Common Exploits
3. Tab **SSL:**
- SSL Certificate: **Request a new SSL Certificate** (Let's Encrypt)
— oder das vorhandene Wildcard-Zertifikat auswählen
- ✅ Force SSL
4. **Save**
Test: `https://bot.d4rkst3r.de/health` im Browser → `{"status":"ok"}`
### 3. Webhook in Gitea eintragen
1. Gitea → EcoGame-Repo → **Einstellungen****Webhooks****Webhook hinzufügen****Gitea**
2. Ziel-URL: `https://bot.d4rkst3r.de/webhooks/gitea`
3. HTTP-Methode: `POST`, POST Content Type: `application/json`
4. **Geheimnis:** exakt der Wert aus `GITEA_WEBHOOK_SECRET`
5. Trigger: **Push-Events**, Branch-Filter leer (= alle)
6. Speichern → auf den Webhook klicken → **Testzustellung** senden
→ im Discord-Kanal erscheint ein Embed 🎉
> Den alten direkten Discord-Webhook im Repo danach löschen, sonst gibt's Doppel-Posts.
Bereits gepostete Commits werden per SHA dedupliziert — ein erneuter Push
derselben Commits erzeugt keine doppelten DB-Einträge.
---
@@ -98,12 +146,16 @@ docker logs -f ecobot
```
ecobot/
├── src/
│ ├── index.js # Einstiegspunkt
│ ├── index.js # Einstiegspunkt (Bot + Webserver)
│ ├── config.js # Env-Konfiguration mit Validierung
── bot/
├── client.js # Discord-Client, Command-Registry, Interactions
── commands/
└── ping.js # /ping — Lebenszeichen
── db.js # SQLite (better-sqlite3), Schema + Queries
├── bot/
── client.js # Discord-Client, Command-Registry, Interactions
│ ├── commit-feed.js # Push → Discord-Embed
│ │ └── commands/
│ │ └── ping.js # /ping — Lebenszeichen
│ └── web/
│ └── server.js # Fastify: /health, /webhooks/gitea (HMAC-geprüft)
├── .env.example # Vorlage für Secrets (nach .env kopieren)
├── Dockerfile
├── docker-compose.yml