Files
abdulive/docs/projects/discord-community.md
T
ZeasyAlexandClaude Opus 5 994ce4faf0 Discord: Knopf fuer die Live-Ping-Rolle statt Onboarding
Live-Ping nuetzt nur, wenn man sie sich selbst geben kann. Discords
Onboarding waere der vorgesehene Weg, laesst sich hier aber nicht
einschalten - gemessen, nicht vermutet:

  HTTP 400  Cannot enable onboarding, requirements are not met  (350000)
  sichtbar fuer @everyone: 5   davon beschreibbar: 3
  Discord verlangt:        7   davon beschreibbar: 5

Zwei Kanaele anzulegen, damit eine Schwelle passt, macht den Server leerer
statt besser. Stattdessen ein Knopf unter dem Willkommenstext: ein Druck
holt die Rolle, der naechste gibt sie ab, die Antwort sieht nur, wer
geklickt hat.

Der Knopf braucht eine dauerhafte Verbindung, weil Discord Klicks ans
Gateway oder an eine oeffentliche HTTPS-Adresse liefert und der Stream-PC
keine hat:

- gateway.ts   WebSocket mit Herzschlag, Fortsetzen und Wiederverbinden.
               Bei 4004 und Verwandten wird aufgegeben statt im Kreis zu
               laufen - dagegen hilft nur eine Aenderung an der App.
               intents: 0, der Bot sieht weder Nachrichten noch Mitglieder.
- selfroles.ts Knopfleiste und Rollenwechsel.
- bot.ts       beides zusammen, laeuft im Ingest-Daemon mit. Ohne
               hinterlegtes Token entfaellt er wortlos.

Neuer Befehl `abdulive discord:bot` zum Ausprobieren; im Normalbetrieb
haengt der Bot im Daemon und meldet sich als discordConnected auf der
Statusseite.

Die Knopfleiste gehoert zum Soll-Zustand des Willkommenstextes: fehlt sie,
wird sie nachgereicht, ohne die Nachricht neu zu posten.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 21:59:08 +02:00

13 KiB

Discord-Community

Wirkrichtung: Bindung. Twitch ist der Ort, an dem Leute zuschauen. Discord ist der Ort, an dem sie zwischen den Streams noch da sind. Ohne den zweiten Ort faengt jeder Stream bei null an.

Der Server ist kein Tool aus der Neunerliste, aber drei davon posten dorthin: Go-Live-Broadcaster, Stream-Recap und Clip-to-Shorts. Deshalb steht die Struktur hier im Repo und nicht nur in einer Oberflaeche.

Leitgedanke: klein anfangen

Der Kanal hat 5 bis 30 gleichzeitige Zuschauer. Daraus werden realistisch 20 bis 100 Discord-Mitglieder, von denen eine Handvoll schreibt.

Ein Server mit zwanzig Kanaelen sieht bei dieser Groesse nicht nach einer grossen Community aus, sondern nach einer verlassenen. Zwanzig leere Kanaele sagen jedem Neuankoemmling: hier ist nichts los. Fuenf Kanaele, in denen etwas steht, sagen das Gegenteil.

Also: fuenf sichtbare Kanaele. Wachstum kommt spaeter, und nur dann, wenn ein bestehender Kanal wirklich zu voll wird. Wann das so weit ist, steht weiter unten unter Wann ein Kanal dazukommt.

Die Struktur

Der Bauplan liegt in packages/discord/src/plan.ts und ist die massgebliche Fassung. Was hier steht, ist die Begruendung dazu.

Kanaele

Kategorie Kanal Wer schreibt Wofuer
📌 Info 👋│willkommen niemand Die drei Regeln, einmal gepostet
📌 Info 📢│ankündigungen nur Webhooks Stream-Start und Recap; Diskussion in Threads
🎮 Community 💬│allgemein alle Der Hauptkanal. Im Zweifel hier
🎮 Community 🎬│clips alle + Clip-Knopf Gute Momente
🎮 Community 🔊 Zusammen zocken — Sprachkanal
🔒 Intern 🔨│mod-chat Mods Fuer alle anderen unsichtbar
🔒 Intern 🤖│technik-log Toolkit Probelaeufe, Fehler, AutoMod-Treffer

Zu den Namen: Discord schreibt Textkanaele klein und macht aus Leerzeichen Bindestriche. Emoji, Umlaute und das Trennzeichen │ (U+2502) bleiben stehen - am echten Server nachgemessen, nicht angenommen. normalizeName() bildet das ab, damit nicht bei jedem Lauf dieselbe Umbenennung erneut rausgeht.

Und zur Schreibweise: im Quelltext bleibt es bei ae/oe/ue wie im uebrigen Repo, aber alles, was ein Mitglied auf Discord liest, steht in richtigem Deutsch. „Sei anstaendig" liest sich wie ein Tippfehler, und der Text im Server ist der erste Eindruck, den jemand davon bekommt.

📢│ankündigungen ist schreibgeschuetzt, erlaubt aber Reaktionen und Threads. So bleibt die Kanalansicht eine saubere Liste von Streams, und die Diskussion ueber das Recap haengt trotzdem direkt daran.

Der Sprachkanal ist bewusst dabei, obwohl er anfangs leer sein wird. Ein Sprachkanal, den zwei Leute nutzen, ist der Anfang; einer, den es nicht gibt, wird nie einer.

Rollen

Die Reihenfolge ist zugleich die Rangfolge auf dem Server.

Rolle Sichtbar Wofuer
Abdu ja Der Kanal selbst. Administrator
Mod ja Loeschen, stummschalten, rauswerfen
Stammgast ja Auszeichnung fuer Leute, die regelmaessig da sind
Live-Ping nein Wird bei Stream-Start angepingt, selbst vergeben

Abdu traegt Administrator. Das Recht schliesst alle anderen ein und setzt jede Kanal-Ausnahme ausser Kraft, auch kuenftige. Es gehoert deshalb an genau ein Konto und an kein zweites. Ein Test im Repo haelt fest, dass keine andere Rolle es bekommt.

Live-Ping ist die wichtigste der vier. Ein Rundruf an alle bei jedem Stream ist der schnellste Weg, dass die Leute den Server stummschalten - und ein stummgeschalteter Server ist ein toter Server. Angepingt wird nur, wer sich die Rolle selbst geholt hat. Das sind weniger Leute, aber es sind die, die kommen.

Der Knopf fuer Live-Ping

Live-Ping nuetzt nur, wenn man sie sich selbst geben kann. Discord bietet dafuer Onboarding an, aber das laesst sich hier nicht einschalten:

HTTP 400  Cannot enable onboarding, requirements are not met  (350000)

sichtbar fuer @everyone: 5   davon beschreibbar: 3
Discord verlangt:        7   davon beschreibbar: 5

Zwei Kanaele anzulegen, damit eine Schwelle passt, macht den Server leerer statt besser - genau das, wogegen der ganze Entwurf gebaut ist. Also stattdessen ein Knopf unter dem Willkommenstext. Ein Druck holt die Rolle, der naechste gibt sie wieder ab, und die Antwort sieht nur, wer geklickt hat.

Der Knopf braucht einen laufenden Bot: Discord liefert Klicks entweder ans Gateway oder an eine oeffentlich erreichbare HTTPS-Adresse, und der Stream-PC hat keine. Die Gateway-Verbindung haengt deshalb im Ingest-Daemon mit drin (gateway.ts) und meldet sich als discordConnected auf der Statusseite. Zum Ausprobieren einzeln:

abdulive discord:bot

Die Verbindung fordert keine Absichten an (intents: 0). Interaktionen kommen trotzdem an, aber Nachrichteninhalte und Mitgliederlisten sieht der Bot nicht - was man nicht anfordert, kann man auch nicht versehentlich mitlesen.

Welche Knoepfe es gibt, steht in SELF_ROLES in plan.ts. Die custom_id steht dauerhaft in der Nachricht und darf sich nie aendern, sonst tun alte Knoepfe nichts mehr.

Stammgast hat fast keine zusaetzlichen Rechte, und das ist Absicht. Der Wert liegt darin, dass der Name farbig ist und in der Mitgliederliste oben steht. Bei dieser Kanalgroesse ist sichtbare Zugehoerigkeit der wirksamste Hebel, den es gibt, und er kostet nichts.

Mod bekommt kein Server verwalten, kein Rollen verwalten und kein Kanaele verwalten. Moderation heisst aufraeumen, nicht umbauen. Wer umbauen soll, bekommt das Recht einzeln.

Was @everyone darf

Gesetzt wird eine vollstaendige Liste statt Discords Vorgabe - die aendert sich mit der Zeit, und dann steht irgendwann ein Recht drin, das niemand vergeben hat. Ausdruecklich nicht enthalten: @everyone erwaehnen, TTS-Nachrichten, private Threads, saemtliche Verwaltungsrechte.

Ausdruecklich enthalten: Einladungen erstellen. Ein Server, in den Mitglieder niemanden einladen koennen, waechst nur so schnell, wie Abdu selbst Links verteilt.

Serverweit

  • Sicherheitsstufe „mittel" - das Konto muss aelter als fuenf Minuten sein. Kostet echte Leute nichts und haelt Wegwerf-Konten draussen. Ein oeffentlich von Twitch aus verlinkter Server bekommt die.
  • Benachrichtigungen nur bei Erwaehnung. Sonst klingelt jede Nachricht bei jedem. Siehe oben, stummgeschalteter Server.
  • Zwei AutoMod-Regeln: Erwaehnungs-Spam (mehr als fuenf auf einmal) und Discords eigene Spam-Erkennung. Beide blocken die Nachricht und melden sie in 🤖│technik-log. Kein Wortfilter - der kostet bei dieser Groesse mehr Aerger durch Fehlalarme, als er an Spam verhindert.

Einrichten

1. Von Hand: Server und Bot

Beides geht nur ueber die Oberflaeche, ein Skript darf das nicht.

  1. Server anlegen. In Discord links unten auf +, „Eigenen erstellen", Name und Bild setzen.

  2. Entwicklermodus einschalten (Einstellungen > Erweitert), dann Rechtsklick auf den Server > „Server-ID kopieren".

  3. App anlegen unter https://discord.com/developers/applications: „New Application", dann links „Bot". Dort „Reset Token", Token kopieren. Er wird genau einmal angezeigt.

  4. Bot einladen. Client-ID aus „General Information" einsetzen:

    https://discord.com/oauth2/authorize?client_id=DEINE_CLIENT_ID&permissions=805375024&scope=bot
    

    Die Zahl sind genau die sieben Rechte, die das Skript braucht: Kanaele, Rollen, Webhooks und Server verwalten, lesen, schreiben, Verlauf lesen. Kein Administrator.

2. Der Befehl

abdulive discord:setup --server <SERVER-ID> --vorschau

Die Vorschau liest den Server aus und zeigt Zeile fuer Zeile, was passieren wuerde. Sie schreibt nichts. Sieht das gut aus, dasselbe ohne --vorschau:

abdulive discord:setup --server <SERVER-ID>

Der Bot-Token wird beim ersten Lauf abgefragt (die Eingabe wird nicht angezeigt) und danach zusammen mit der Server-ID verschluesselt abgelegt - siehe ADR-0005. Ab dem zweiten Lauf genuegt abdulive discord:setup.

Die drei Webhook-URLs landet das Skript direkt im selben Speicher, unter goLiveWebhook, recapWebhook und clipsWebhook. Sie werden nie ausgegeben und nie geloggt - Broadcaster, Recap und Clipper lesen sie von dort.

3. Von Hand: der Rest

Drei Dinge kann die API nicht oder nicht sinnvoll:

  1. Dir selbst Abdu geben und die Bot-Rolle in den Servereinstellungen ueber Abdu ziehen. Eine Rolle kann nur Rollen unterhalb der eigenen verschieben - auch mit Administrator. Discord haengt die Bot-Rolle beim Einladen ganz unten ein, dort ist also kein Platz fuer vier Rollen darunter. Bis das erledigt ist, meldet das Skript die Rangfolge als uebersprungen und nennt den Grund.
  2. Einladungslink erzeugen, ohne Ablaufdatum, und ins Twitch-Panel, in die Kanalinfo und in einen Chat-Befehl eintragen. Ein Server, den im Stream niemand erwaehnt, bleibt leer.
  3. Twitch-Konto verbinden (Servereinstellungen > Integrationen). Danach bekommen Subs automatisch eine Rolle.

Onboarding steht bewusst nicht in der Liste - warum, steht oben unter Der Knopf fuer Live-Ping.

Was das Skript nicht tut

Es loescht nichts. Keine Kanaele, keine Rollen, keine Nachrichten. Ein Einrichtungsskript, das aufraeumt, raeumt irgendwann das Falsche weg. Was von Hand dazugekommen ist, bleibt stehen - auch eigene Rechte-Ausnahmen in einem Kanal, den das Skript anfasst.

Es ueberschreibt den Willkommenstext nicht. Gepostet wird nur, wenn #willkommen leer ist. Danach gehoert der Text der Hand, die ihn zuletzt angefasst hat.

Es laesst von Discord verwaltete Rollen in Ruhe. Rollen, die zu einer App oder zur Twitch-Anbindung gehoeren, meldet es als uebersprungen.

Wiederholtes Ausfuehren ist der Normalfall: gefunden wird ueber den Namen, danach wird angeglichen statt neu angelegt. Der zweite Lauf aendert nichts.

Wann ein Kanal dazukommt

Nicht auf Verdacht. Jeweils erst, wenn die Bedingung wirklich eintritt:

Neuer Kanal Erst wenn
#vorschlaege In #allgemein gehen Vorschlaege zwischen anderem unter
#fotos oder #offtopic #allgemein besteht ueberwiegend aus einem Thema, das nicht der Stream ist
Spiel-eigener Kanal Zu einem Spiel gibt es ueber Wochen taeglich Gespraech
Zweiter Sprachkanal Der erste ist regelmaessig belegt, wenn jemand dazu will
Forum statt #clips Mehr als etwa zehn Clips pro Woche

Umgekehrt gilt genauso: ein Kanal, in dem vier Wochen nichts steht, kommt weg.

Fallstricke

  • Die Bot-Rolle steht anfangs unten. Discord haengt sie beim Einladen unterhalb bestehender Rollen ein. Dann schlaegt das Setzen der Rangfolge fehl. Das Skript bricht deswegen nicht ab, sondern meldet es - nachziehen und noch einmal laufen lassen.
  • Von Hand angelegte Webhooks geben ihren Token nicht heraus. Wer einen Webhook in der Oberflaeche neu anlegt, bekommt eine URL, die das Skript nicht auslesen kann. Es meldet ihn als uebersprungen; loeschen und noch einmal laufen lassen loest es.
  • Kanalnamen lassen sich nur zweimal in zehn Minuten aendern. Discord verlangt danach bis zu neun Minuten Pause. Der Lauf wartet hoechstens eine Minute, meldet den Kanal als uebersprungen und macht weiter - spaeter noch einmal ausfuehren holt es nach.
  • Umbenennen statt verdoppeln. Aendert sich ein Name im Bauplan, gehoert der alte in aliases. Sonst findet das Skript den Kanal nicht wieder und legt einen zweiten daneben an. Ein Test besteht darauf, dass jeder Eintrag einen frueheren Namen hinterlegt hat.
  • Ankuendigungskanaele im Discord-Sinn (die, denen andere Server folgen koennen) brauchen einen Community-Server, und der braucht Regelkanal, Update-Kanal und einige Einstellungen. Fuer diese Groesse bringt das nichts, deshalb ist #ankuendigungen ein normaler Textkanal mit Schreibschutz.
  • Ein Ping ist keine Reichweite. Wer Live-Ping nicht anbietet und stattdessen @everyone benutzt, hat beim dritten Mal einen stummen Server.

Abnahmekriterien

  • abdulive discord:setup --vorschau laeuft auf einem frischen Server durch und meldet keinen uebersprungenen Punkt.
  • Nach dem echten Lauf existieren drei Kategorien, sieben Kanaele, vier Rollen und drei Webhooks; 👋│willkommen enthaelt genau eine Nachricht.
  • Ein zweiter Lauf meldet ausschliesslich „steht" und legt nichts doppelt an.
  • Ein Konto ohne Rolle sieht Intern nicht und kann in #ankuendigungen nicht schreiben, aber einen Thread eroeffnen.
  • Die Webhook-URLs stehen im verschluesselten Speicher und tauchen in keiner Ausgabe und keinem Log auf.
  • Der Knopf unter dem Willkommenstext vergibt Live-Ping und nimmt sie beim zweiten Druck wieder weg; die Antwort sieht nur, wer geklickt hat.