Files
d4rkbot/README.md
T
D4rkst3randClaude Opus 4.8 eb51be4ebc README komplett überarbeitet: aktueller Funktionsumfang, Setup, Endpoints, Struktur
- Feature-Tabellen (Discord + Webinterface + Setup-Seite)
- Ersteinrichtung gestrafft: Discord-App inkl. aller nötigen Permissions,
  Env-Tabelle mit Pflicht/Optional, Gitea-Webhook mit allen drei Trigger-Events
- Deployment (Portainer inkl. Re-pull-Hinweis), lokale Entwicklung
- HTTP-Endpoint-Referenz und aktualisierte Projektstruktur

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 11:43:21 +02:00

229 lines
11 KiB
Markdown

# EcoBot — D4RKST3R // DEVLOG
Discord-Bot + Webinterface: Devlog-Tagebuch, Commit-Feed, Changelog und
Community-Tools für die EcoGame-Entwicklung — alles gebrandet, alles über
die Setup-Seite steuerbar.
**Stack:** Node.js 20+ (ESM), discord.js v14, Fastify 5, React 19 + Vite,
SQLite (better-sqlite3, FTS5), Docker Multi-Stage — deploybar als Portainer-Stack.
---
## Features
### Discord
| Feature | Beschreibung |
|---|---|
| 📔 **Devlog-Posts** | `tools/devlog.py` (EcoGame-Repo) schickt Prosa + Bilder an den Bot-Endpoint → gebrandetes Embed (Datum-Titel, Author-Zeile, Commit-Zähler im Footer, Bilder-Grid, Link-Buttons) |
| 💬 **Auto-Threads** | Diskussions-Thread unter jedem Devlog-Post („💬 Devlog 23.07.") |
| 🔔 **Rollen-Ping** | Ping-Rolle beim Devlog-Post; Member abonnieren sie selbst über den 🔔-Button |
| 📦 **Commit-Feed** | Gitea-Push-Webhooks → Embeds in den (privaten) Commit-Kanal |
| 🚀 **Release-Ankündigungen** | Neues Gitea-Release → oranges Ankündigungs-Embed |
| 📊 **Wochen-Rückblick** | Sonntags 20:00 automatisch: Commits pro Tag als Balken, Devlogs, Top-Projekte |
| 🐛 **`/bug`** | Member melden Bugs → Gitea-Issue (inkl. Screenshot-Upload); Issue geschlossen → DM an den Reporter |
| 🚨 **Watchdog** | Prüft eigene Dienste alle 2 min, DM-Alarm bei Ausfall + Entwarnung |
| 🏓 `/ping`, 🗄 `/devlog-backfill` | Lebenszeichen · Kanal-Historie nacharchivieren (Admin) |
### Webinterface (`bot.d4rkst3r.de`)
| Seite | Zugriff | Inhalt |
|---|---|---|
| `/devlogs` | öffentlich | Devlog-Archiv: Timeline, Bildergalerien, Projekt-Chips, **Volltextsuche** |
| `/changelog` | öffentlich | Alle Releases mit Notes, Tag- und Pre-Release-Chips |
| `/feed.xml` | öffentlich | RSS-Feed der Devlogs |
| `/commits` | nur Admin | Archivierte Commits aller Repos (SHA → Gitea-Link) |
| `/settings` | nur Admin | **Setup-Seite** — siehe unten |
Login via Discord-OAuth2 (identify-Scope, signierte Session-Cookies, keine Token-Speicherung).
Design: D4RKST3R-Brand (Neon-Gelb/Orange auf Schwarz, Bebas Neue + Barlow Condensed +
Share Tech Mono, selbst gehostet).
### Setup-Seite (`/settings`)
Alles zur Laufzeit änderbar — gespeichert in SQLite, Env-Variablen sind nur Fallback,
kein Redeploy nötig:
- **Kanäle** (Devlog / Commit / Release) als Dropdown + „Test senden"-Button je Kanal
- **Devlog:** Ping-Rolle, Auto-Threads an/aus, Wochen-Rückblick an/aus (+ Sofort-Test)
- **Commit-Feed:** an/aus, Branch-Filter, ignorierte Repos
(gefiltert wird nur das Posten — archiviert wird immer; ignorierte Repos komplett übersprungen)
- **Bug-Reports:** Ziel-Repo für `/bug`
- **Watchdog:** überwachte URLs
- **Status-Panel:** Bot-Account, Uptime, Devlog-/Commit-Zahlen, DB-Größe
---
## Ersteinrichtung
### 1. Discord-App ([Developer Portal](https://discord.com/developers/applications))
1. **New Application** → Name vergeben
2. **General Information** → Application ID = `DISCORD_CLIENT_ID`
3. **Bot** → Reset Token = `DISCORD_TOKEN` (wird nur einmal angezeigt!)
und **Message Content Intent** aktivieren (Devlog-Listener)
4. **OAuth2** → Client Secret = `DISCORD_CLIENT_SECRET`;
unter **Redirects** eintragen:
- `https://bot.d4rkst3r.de/auth/callback`
- `http://localhost:3080/auth/callback` (lokale Entwicklung)
5. **OAuth2 → URL Generator:** Scopes `bot` + `applications.commands`;
Permissions: Send Messages, Embed Links, Attach Files, Read Message History,
**Create Public Threads**, **Manage Roles** (für den 🔔-Abo-Button)
→ URL öffnen, Bot einladen
6. In Discord: Entwicklermodus an → Server-ID = `DISCORD_GUILD_ID`,
eigene User-ID = `ADMIN_DISCORD_ID`
⚠️ **Kanal-Overrides:** In Kanälen, in denen `@everyone` nicht schreiben darf,
braucht der Bot eigene Overrides (Kanal ansehen, Nachrichten senden, Links einbetten,
Dateien anhängen, Threads erstellen). Die Bot-Rolle muss **über** der Ping-Rolle stehen.
### 2. Environment-Variablen
Vorlage: [.env.example](.env.example) — lokal als `.env` (gitignored),
in Portainer als Stack-Environment-Variables.
| Variable | Pflicht | Zweck |
|---|---|---|
| `DISCORD_TOKEN` | ✅ | Bot-Token |
| `DISCORD_CLIENT_ID` | ✅ | Application ID |
| `DISCORD_CLIENT_SECRET` | ✅ | OAuth2-Login |
| `SESSION_SECRET` | ✅ | Session-Cookies signieren¹ |
| `ADMIN_DISCORD_ID` | ✅ | Deine User-ID (Admin-Zugriff + Watchdog-DMs) |
| `GITEA_WEBHOOK_SECRET` | ✅ | HMAC-Prüfung der Gitea-Webhooks¹ |
| `DEVLOG_POST_SECRET` | ✅ | Secret im Devlog-Endpoint-Pfad¹ |
| `DISCORD_GUILD_ID` | optional | Guild-Commands sofort statt global (bis 1h) |
| `GITEA_API_TOKEN` | optional | Für `/bug` → Issues (Scope `write:issue`); ohne Token ist `/bug` aus |
| `GITEA_URL` | optional | Default `https://git.d4rkst3r.de` |
| `PUBLIC_URL` | optional | Default `https://bot.d4rkst3r.de` |
| `COMMIT_CHANNEL_ID` / `DEVLOG_CHANNEL_ID` | optional | Fallbacks — Kanäle kommen normal von der Setup-Seite |
| `TZ` | optional | Default `Europe/Berlin` (Wochen-Rückblick, Datumsformate) |
¹ Generieren: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`
### 3. Routing (einmalig eingerichtet)
Cloudflare: CNAME `bot` → Zone, Proxied. Nginx Proxy Manager: `bot.d4rkst3r.de`
`host.docker.internal:3080`, Block Common Exploits, Force SSL.
Test: `https://bot.d4rkst3r.de/health``{"status":"ok"}`
### 4. Gitea-Webhook (systemweit oder pro Repo)
- Typ **Gitea**, URL `https://bot.d4rkst3r.de/webhooks/gitea`,
Content Type `application/json`, Geheimnis = `GITEA_WEBHOOK_SECRET`
- Trigger-Events: **Push**, **Release**, **Issues**
(Push = Commit-Feed · Release = Ankündigungen/Changelog · Issues = Bug-Rückkanal-DMs)
### 5. devlog.py (EcoGame-Repo)
In `tools/.devlog_webhook` steht die Bot-Endpoint-URL:
```
https://bot.d4rkst3r.de/webhooks/devlog/<DEVLOG_POST_SECRET>
```
Workflow: Prosa nach `tools/devlog_today.txt` (+ Bilder in `devlog_images/`, max 4)
`python tools/devlog.py` (oder Task täglich 21:00) → Bot postet + archiviert,
Prosa-Datei und Bilder werden danach gelöscht (gepostet = erledigt).
Ohne Prosa postet das Skript **nichts** (Schutz des öffentlichen Kanals).
Der Endpoint versteht das Discord-Webhook-Format (JSON + Multipart) —
`devlog.py` kennt den Bot also gar nicht.
---
## Deployment (Portainer)
1. **Stacks → Add stack** → Name `ecobot` → Build method **Repository**
- URL `https://git.d4rkst3r.de/D4rkst3r/ecobot`, Reference `refs/heads/main`,
Compose path `docker-compose.yml`
- Privates Repo: Authentication mit Gitea-Token (Scope `read:repository`)
2. Environment-Variablen eintragen (Tabelle oben)
3. **Deploy the stack**
**Updates:** Stack öffnen → **Pull and redeploy**
(„Re-pull image" **aus** lassen — das Image wird lokal gebaut, nicht aus einer Registry gezogen).
Daten liegen im Volume `ecobot_data` (`/app/data`): SQLite (`ecobot.db`, WAL)
+ Devlog-Bilder (`devlog_images/` — lokal gespeichert, weil Discord-CDN-Links ablaufen).
Manuell statt Portainer:
```
git clone git@gitea:D4rkst3r/ecobot.git && cd ecobot
cp .env.example .env # Werte eintragen
docker compose up -d --build
docker logs -f ecobot
```
---
## Lokale Entwicklung
```
npm install
npm run dev # Bot + API auf :3080 (Werte aus .env)
```
Frontend mit Hot-Reload:
```
cd frontend
npm install
npm run dev # Vite auf :5173, proxied /api + /auth → :3080
```
Alternativ `npm run build` im frontend/ — der Bot liefert `frontend/dist`
dann selbst unter :3080 aus (so läuft es auch im Container, Multi-Stage-Build).
Commit-Feed ohne Gitea testen (signierte Fake-Testzustellung):
```
node tools/test-webhook.mjs
```
---
## HTTP-Endpoints
| Route | Auth | Zweck |
|---|---|---|
| `GET /health` | — | Healthcheck |
| `POST /webhooks/gitea` | HMAC-Signatur | Push / Release / Issues von Gitea |
| `POST /webhooks/devlog/:secret` | Secret im Pfad | Devlog von devlog.py (JSON/Multipart) |
| `GET /api/devlogs?page=&q=` | — | Archiv + FTS5-Volltextsuche |
| `GET /api/releases?page=` | — | Changelog |
| `GET /feed.xml` | — | RSS |
| `GET /devlog-assets/*` | — | Lokal gespeicherte Devlog-Bilder |
| `GET/PUT /api/settings`, `POST /api/settings/test/:target` | Admin | Setup-Seite |
| `GET /api/commits?page=` · `DELETE /api/devlogs/:id` | Admin | Commit-Archiv · Devlog löschen |
| `GET /auth/login` · `/auth/callback` · `/auth/logout` | — | Discord-OAuth2 |
Devlogs, die in Discord gelöscht werden, verschwinden automatisch auch aus dem
Archiv (MessageDelete-Sync) — zusätzlich gibt es den ✕-Button für Admins auf der Webseite.
---
## Projektstruktur
```
ecobot/
├── src/
│ ├── index.js # Start: Bot, Webserver, Wochen-Rückblick, Watchdog
│ ├── config.js # Env-Konfiguration mit Validierung
│ ├── db.js # SQLite: Schema, Migrationen, FTS5, alle Queries
│ ├── runtime-settings.js # Effektive Settings (DB vor Env)
│ ├── gitea-api.js # Gitea-REST (Issues + Assets für /bug)
│ ├── bot/
│ │ ├── client.js # Discord-Client, Commands, Listener (Devlog, Delete, Buttons)
│ │ ├── commit-feed.js # Push → Embed
│ │ ├── release-feed.js # Release → Ankündigungs-Embed
│ │ ├── devlog-archive.js # Nachricht → SQLite (+ Bild-Download)
│ │ ├── weekly-recap.js # Sonntags-Zusammenfassung + Scheduler
│ │ ├── watchdog.js # URL-Checks + DM-Alarm
│ │ └── commands/ # ping, devlog-backfill, bug
│ └── web/
│ ├── server.js # Fastify: Webhooks, Static, SPA-Fallback
│ ├── auth.js # Discord-OAuth2 + Session-Cookies
│ ├── api.js # REST-API + Settings + RSS
│ └── devlog-endpoint.js# Devlog-Post: Embed, Bilder, Ping, Thread, Archiv
├── frontend/ # React + Vite (D4RKST3R-Design)
│ └── src/
│ ├── App.jsx # Layout, Router, Nav, Login-Status
│ ├── markdown.jsx # Mini-Markdown (fett/kursiv/Code/Links/Listen/---/##)
│ └── pages/ # Devlogs, Changelog, Commits, Settings
├── tools/test-webhook.mjs # Lokaler Commit-Feed-Test
├── .env.example # Vorlage für alle Env-Variablen
├── Dockerfile # Multi-Stage: Frontend-Build + node:22-slim Runtime
└── docker-compose.yml # Portainer-ready, Volume ecobot_data, TZ
```
**Neue Slash-Commands:** Datei in `src/bot/commands/` (exportiert `data` + `execute`)
und in `client.js` bei `commandModules` eintragen.
**Neue Settings:** Key in `db.js`-Settings nutzen, Zugriff über `runtime-settings.js`,
UI in `frontend/src/pages/Settings.jsx`, GET/PUT in `src/web/api.js`.