diff --git a/README.md b/README.md index 38dbea9..a2ccd7d 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ SQLite (better-sqlite3, FTS5), Docker Multi-Stage — deploybar als Portainer-St | ⭐ **Starboard** | Nachrichten mit genug ⭐-Reaktionen landen automatisch im Best-of-Kanal | | 📸 **Screenshot-Galerie** | Bilder aus dem Screenshot-Kanal → öffentliche `/galerie` (lokal gespeichert); Historie via `/galerie-backfill` | | 📬 **Modmail** | DM an den Bot → Thread im privaten Staff-Kanal; Antworten im Thread gehen als DM zurück | +| 🎫 **Tickets** | `/ticket-setup` postet den Button; Klick öffnet einen privaten Thread (ein offenes Ticket pro User, Schließen-Button) | | 👋 **Willkommens-Embed** | Begrüßung neuer Member im Brand-Look (braucht Server-Members-Intent) | | 📋 **Mod-Log** | Gelöschte/bearbeitete Nachrichten in einen privaten Log-Kanal | | 🎮 **Server-Monitor** | FiveM-kompatible Game-Server (/dynamic.json): Live-Status-Embed + Spielerzahl in der Bot-Presence | @@ -202,6 +203,7 @@ Authorization: Bearer d4rk_ | Endpoint | Scope | Body / Antwort | |---|---|---| | `POST /api/v1/message` | `message` | `{ channel_id, content?, embed? }` → postet als Bot (Embed: title, description, color, url, image, thumbnail, footer, fields) | +| `PATCH /api/v1/message` | `message` | `{ channel_id, message_id, content?, embed? }` → eigenen Bot-Post bearbeiten | | `POST /api/v1/dm` | `dm` | `{ user_id, content }` → Direktnachricht | | `POST /api/v1/roles` | `roles` | `{ user_id, role_id, action: "add"\|"remove" }` → Rolle vergeben (z. B. Shop-Kauf → Kunden-Rolle) | | `GET /api/v1/member/:id` | `read` | Member-Info: Name, Rollen, Beitritt — für Login-/Berechtigungs-Checks | diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx index 54893f8..b80a618 100644 --- a/frontend/src/pages/Settings.jsx +++ b/frontend/src/pages/Settings.jsx @@ -28,6 +28,8 @@ export default function Settings({ me }) { const [feedback, setFeedback] = useState(null); // Community const [playtesters, setPlaytesters] = useState([]); + // Composer + const [composer, setComposer] = useState({ channel: '', title: '', text: '', messageId: '' }); // API-Keys const [keys, setKeys] = useState([]); const [newKeyName, setNewKeyName] = useState(''); @@ -80,6 +82,25 @@ export default function Settings({ me }) { } } + async function sendCompose() { + if (!composer.channel || !composer.text.trim()) { + flash('✗ Kanal und Text nötig'); + return; + } + try { + const res = await apiPost('/api/compose', { + channel_id: composer.channel, + message_id: composer.messageId.trim() || undefined, + embed_title: composer.title.trim() || undefined, + content: composer.text, + }); + flash(res.edited ? '✓ Aktualisiert' : `✓ Gesendet (ID ${res.message_id})`); + if (!res.edited) setComposer({ ...composer, messageId: res.message_id }); + } catch { + flash('✗ Senden fehlgeschlagen'); + } + } + async function sendTest(target) { try { await apiPost(`/api/settings/test/${target}`); @@ -400,6 +421,59 @@ export default function Settings({ me }) { {channelOptions} +
+ + +
+ + + {/* Composer */} +
+

// Post verfassen

+
+ + +
+
+ + setComposer({ ...composer, title: e.target.value })} + /> +
+
+ +