Moderation & Kontakt + Game-Server-Monitor

- Modmail: DMs an den Bot landen als Threads im privaten Staff-Kanal,
  Thread-Antworten gehen als DM zurück (Zustell-Feedback per Reaktion)
- Willkommens-Embed für neue Member (GuildMemberAdd; Server-Members-Intent nötig)
- Mod-Log: gelöschte/bearbeitete User-Nachrichten in privaten Log-Kanal
- Server-Monitor: FiveM-kompatible Endpoints (/dynamic.json) alle 2 min,
  persistentes Status-Embed (edit in place) + Spielerzahl als Bot-Presence
- Neue Intents: DirectMessages, GuildMembers; Partials.Channel
- Setup-Seite: Sektionen // Moderation & Kontakt und // Game-Server

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 13:14:18 +02:00
co-authored by Claude Opus 4.8
parent a3c47656c5
commit 075ea36bd2
9 changed files with 402 additions and 5 deletions
+59
View File
@@ -357,6 +357,65 @@ export default function Settings({ me }) {
</div>
</div>
{/* Moderation & Kontakt */}
<div className="settings-section">
<h2 className="settings-title">// Moderation &amp; Kontakt</h2>
<div className="field">
<label>Modmail-Kanal <span className="field-hint">PRIVATER Staff-Kanal DMs an den Bot landen hier als Threads</span></label>
<select
value={form.modmail_channel_id ?? ''}
onChange={(e) => setForm({ ...form, modmail_channel_id: e.target.value })}
>
<option value=""> deaktiviert </option>
{channelOptions}
</select>
</div>
<div className="field">
<label>Willkommens-Kanal <span className="field-hint">Begrüßungs-Embed für neue Member (braucht Server-Members-Intent im Dev-Portal!)</span></label>
<select
value={form.welcome_channel_id ?? ''}
onChange={(e) => setForm({ ...form, welcome_channel_id: e.target.value })}
>
<option value=""> deaktiviert </option>
{channelOptions}
</select>
</div>
<div className="field">
<label>Mod-Log-Kanal <span className="field-hint">PRIVAT gelöschte/bearbeitete Nachrichten</span></label>
<select
value={form.modlog_channel_id ?? ''}
onChange={(e) => setForm({ ...form, modlog_channel_id: e.target.value })}
>
<option value=""> deaktiviert </option>
{channelOptions}
</select>
</div>
</div>
{/* Game-Server */}
<div className="settings-section">
<h2 className="settings-title">// Game-Server</h2>
<div className="field">
<label>Status-Kanal <span className="field-hint">persistentes Status-Embed, alle 2 min aktualisiert</span></label>
<select
value={form.status_channel_id ?? ''}
onChange={(e) => setForm({ ...form, status_channel_id: e.target.value })}
>
<option value=""> deaktiviert </option>
{channelOptions}
</select>
</div>
<div className="field">
<label>Server <span className="field-hint">kommagetrennt Name=URL FiveM-kompatibel (/dynamic.json)</span></label>
<input
type="text"
placeholder="z. B. FiveM=http://1.2.3.4:30120, EcoGame=http://…"
value={form.gameservers}
onChange={(e) => setForm({ ...form, gameservers: e.target.value })}
/>
</div>
</div>
{/* Backups */}
<div className="settings-section">
<h2 className="settings-title">// Backups</h2>