Files
sftrading/README.md
jbergner 720708f9d3
All checks were successful
release-tag / release-image (push) Successful in 2m8s
Deutsch und Cleanup der Kanäle
2026-05-29 21:48:19 +02:00

230 lines
7.2 KiB
Markdown

# Starauftrag Discord Bot (Go + SQLite)
Produktionsnaher Discord-Bot für Lieferaufträge mit SQLite-Persistenz, Slash Commands, internen Team-Buttons, Audit-Log und privater Lagerverwaltung.
## Kernidee
- Endnutzer erstellen mit `/auftrag` einen Lieferauftrag.
- Der öffentliche Auftragspost enthält nur auftragsbezogene Basisdaten.
- Das Team erhält in einem privaten internen Channel denselben Auftrag plus Lagerprüfung.
- Annahme/Ablehnung erfolgt ausschließlich im internen Channel per Button.
- Lagerdaten werden nie an den Einreicher oder in öffentliche Posts ausgegeben.
- Alle relevanten Änderungen werden in `order_events` auditiert.
Discord Buttons sind Message Components mit `custom_id`; beim Klick erhält der Bot eine Component Interaction und ordnet sie damit wieder dem Auftrag zu.
## Setup
1. Discord Developer Portal: Bot erstellen, Token kopieren, Bot in deinen Server einladen.
2. Bot-Berechtigungen:
- `Send Messages`
- `Use Slash Commands`
- `Read Message History`
- `Embed Links`
- `Create Public Threads` oder `Create Private Threads` je nach Channel-Einstellung
- `Send Messages in Threads`
3. `.env.example` nach `.env` kopieren oder Umgebungsvariablen setzen.
4. Starten:
```bash
go mod tidy
go run .
```
Für schnelle Command-Updates in Entwicklung `DISCORD_GUILD_ID` setzen. Ohne Guild-ID werden Slash Commands global registriert, was länger dauern kann.
## Wichtige Umgebungsvariablen
```env
DISCORD_TOKEN=...
DISCORD_APP_ID=...
DISCORD_GUILD_ID=...
DISCORD_PUBLIC_ORDER_CHANNEL_ID=...
DISCORD_INTERNAL_ORDER_CHANNEL_ID=...
DISCORD_AUDIT_CHANNEL_ID=...
DISCORD_ADMIN_ROLE_IDS=roleId1,roleId2
DISCORD_TEAM_ROLE_IDS=roleId3,roleId4
DATABASE_PATH=orders.db
THREAD_DELETE_AFTER_HOURS=72
```
`DISCORD_INTERNAL_ORDER_CHANNEL_ID` sollte ein privater Team-Channel sein. Nur dort erscheinen Lagerprüfung und Annahme-/Ablehnen-Buttons.
## User Commands
### `/auftrag`
Erstellt einen Auftrag mit:
- `ware`
- `qualitaet` 0-1000
- `menge` als Zahl
- `einheit` `SCU`, `cSCU` oder `Stück`
- `frist` im Format `YYYY-MM-DD`
- `lieferort`
- `budget` in aUEC
### `/auftrag_status id:<id>`
Zeigt den Auftrag. Team/Admin sieht die interne Ansicht inklusive Lagerprüfung, normale Nutzer nur eigene Aufträge ohne Lagerdaten.
### `/auftrag_liste status:<optional> limit:<optional>`
Listet nur aktive Aufträge. Standardmäßig werden `offen`, `angenommen`, `in Lieferung` und `geliefert` angezeigt. Abgeschlossene, abgelehnte und abgebrochene Aufträge erscheinen hier nicht mehr.
### `/auftrag_archiv status:<optional> limit:<optional>`
Listet archivierte Aufträge mit den deutschen Statuswerten `abgeschlossen`, `abgelehnt` und `abgebrochen`. Intern werden die stabilen Werte `completed`, `declined` und `cancelled` gespeichert.
### `/auftrag_abschliessen id:<id>`
Einreicher, Annehmer oder Team/Admin können abschließen.
### `/auftrag_abbrechen id:<id> grund:<optional>`
Einreicher oder Team/Admin können abbrechen.
### `/auftrag_nachricht id:<id> text:<text>`
Leitet eine Nachricht per DM an Einreicher und Annehmer weiter und schreibt sie zusätzlich in den internen Auftragsthread.
## Team/Admin Commands
### `/auftrag_status_setzen`
Team/Admin kann den Status manuell setzen:
- `offen`
- `angenommen`
- `in Lieferung`
- `geliefert`
- `abgeschlossen`
- `abgelehnt`
- `abgebrochen`
## Lager Commands
Nur Admins können Lagerbestände verändern. Team/Admin kann Lager prüfen und anzeigen.
### `/lager_add`
Fügt Bestand hinzu oder setzt ihn absolut.
```text
/lager_add ware:Gold qualitaet:900 menge:64 einheit:SCU ort:Orison modus:addieren
/lager_add ware:Gold qualitaet:900 menge:100 einheit:SCU ort:Orison modus:setzen
```
`ort` ist der interne Lagerort. Er wird nur in Team-/Admin-Ausgaben, der internen Lagerprüfung und im Auditlog angezeigt. Öffentliche Auftragsposts und Endnutzer-DMs enthalten keine Lagerorte.
Das Auditlog zeigt Bestandsänderungen mit altem und neuem Wert, z. B.:
```text
Lager geändert durch b1tk1ll3r: P4-AR Q725 Stück @ Baijini Point: 0 → 2
```
### `/lager_remove`
Reduziert Bestand. Der Bot verhindert negative Bestände.
```text
/lager_remove ware:Gold qualitaet:900 menge:10 einheit:SCU ort:Orison
```
Auch hier bezieht sich `ort` auf genau diese Lagerposition. Wird kein Ort angegeben, wird der Bestand ohne Lagerort geführt.
### `/lager_liste`
Zeigt interne Lagerbestände ephemeral an.
```text
/lager_liste suche:Gold limit:20
```
### `/lager_check`
Prüft intern, ob eine Menge verfügbar ist.
```text
/lager_check ware:Gold qualitaet:900 menge:64 einheit:SCU
/lager_check ware:P4-AR qualitaet:725 menge:2 einheit:cSCU
```
## Statusmodell
```text
offen -> angenommen -> in Lieferung -> geliefert -> abgeschlossen
\-> abgebrochen
offen -> abgelehnt
Intern speichert der Bot weiterhin stabile technische Statuswerte wie `open`, `accepted`, `completed` usw. In Discord werden sie deutsch angezeigt.
```
## Datenbanktabellen
- `orders`: Aufträge und Discord-Message-Referenzen
- `inventory`: interne Lagerpositionen
- `order_events`: Audit-Log für Aufträge und Lageränderungen
SQLite wird mit WAL-Modus und `busy_timeout` betrieben, damit kleine produktive Deployments robuster laufen.
## Produktionshinweise
- Setze `DISCORD_INTERNAL_ORDER_CHANNEL_ID` auf einen strikt privaten Channel.
- Gib Lager-Commands nur einer kleinen Admin-Rolle.
- Sichere `orders.db` regelmäßig.
- Führe den Bot als systemd-Service oder Container aus.
- Aktiviere Monitoring für Logs und Neustarts.
- Teste DMs: Manche Nutzer blockieren DMs von Servermitgliedern; der Bot loggt solche Fehler, kann sie aber nicht erzwingen.
## Lagerbestand bei 0
Wenn ein Lagerbestand durch `/lager_remove` oder `/lager_add` mit `modus:setzen` auf `0` fällt, wird der Lagerdatensatz automatisch gelöscht. Das Auditlog zeigt weiterhin die Änderung als `alter Wert → neuer Wert`, z. B. `2 → 0`.
Zusätzlich verhindert die Lagerlogik negative Bestände. Wenn mehr entfernt wird als vorhanden ist, antwortet der Bot mit einem Fehler und ändert den Bestand nicht.
`/lager_liste` und die interne Lagerprüfung berücksichtigen nur Bestände größer als `0`, sodass alte Nullbestände nicht mehr angezeigt werden.
## Automatische Thread-Bereinigung
Interne Auftragsthreads werden nach einer konfigurierbaren Zeit automatisch gelöscht, sobald der Auftrag archiviert ist. Archiviert bedeutet:
- `abgeschlossen`
- `abgelehnt`
- `abgebrochen`
Die Zeit steuerst du über:
```env
THREAD_DELETE_AFTER_HOURS=72
```
`72` bedeutet: Der Thread wird frühestens 72 Stunden nach der letzten Statusänderung gelöscht. `0` deaktiviert die automatische Thread-Bereinigung.
Für das Löschen benötigt der Bot im internen Channel zusätzlich `Manage Threads`. Wenn diese Berechtigung fehlt, bleibt der Thread bestehen und der Fehler erscheint im Bot-Log.
## Deutsche Statusbegriffe
Discord zeigt Statuswerte jetzt deutsch an:
| Anzeige | interner Wert |
| --- | --- |
| offen | `open` |
| angenommen | `accepted` |
| in Lieferung | `in_delivery` |
| geliefert | `delivered` |
| abgeschlossen | `completed` |
| abgelehnt | `declined` |
| abgebrochen | `cancelled` |
Die internen Werte bleiben absichtlich englisch, damit bestehende Datenbanken und Integrationen stabil bleiben.
## Einheiten
Bei Aufträgen und Lagerbeständen sind jetzt diese Einheiten auswählbar:
- `SCU`
- `cSCU`
- `Stück`