Kapitel 10/Free Rhohtext.md aktualisiert
This commit is contained in:
@@ -270,3 +270,543 @@ Nach wenigen Sekunden ist n8n über die gewählte Subdomain erreichbar, z. B.:
|
||||
[!TIP]
|
||||
Falls der Zugriff auch von außen möglich sein soll, muss im Router Port 443 auf den NPM-Host weitergeleitet werden.
|
||||
|
||||
## Schritt 5 – Vorbereitung: X-App und Credentials anlegen
|
||||
|
||||
In diesem Schritt richten wir die Verbindung zwischen **n8n** und **X (ehemals Twitter)** ein, damit später automatisch Beiträge gepostet werden können.
|
||||
|
||||
### 5.1 – X-Entwicklerkonto erstellen und Free-Plan aktivieren
|
||||
1) Gehe zu [https://developer.x.com/](https://developer.x.com/) und melde dich mit deinem normalen X-Account an.
|
||||
2) Öffne im linken Menü **Products → X API**.
|
||||
3) Scrolle zu **API Tiers & Pricing** und wähle **Free**.
|
||||
4) Klicke auf **„Sign Up for Free Account“** (der Button ist etwas unscheinbar).
|
||||
5) Im Formular die **Use Cases** eintragen – mindestens 250 Zeichen.
|
||||
Beispiel (englisch, ausreichend allgemein):
|
||||
> We use the API to read and write posts programmatically in order to build community engagement and automate simple posting flows for our streams.
|
||||
6) Alle Häkchen für die Bedingungen setzen und die Anmeldung abschließen.
|
||||
|
||||
👉 Screenshot geeignet: Developer-Portal mit ausgewähltem Free-Plan
|
||||
|
||||
[!NOTE]
|
||||
Mit dem Free-Plan steht genau **eine App** zur Verfügung.
|
||||
Dieser Plan erlaubt bis zu **500 Posts (Write) und 100 gelesene Posts (Read) pro Monat** – für Streaming-Ankündigungen reicht das in der Regel völlig aus.
|
||||
|
||||
### 5.2 – Überblick im Developer-Dashboard
|
||||
Nach der Anmeldung erscheint im **Dashboard → Projects & Apps** automatisch ein erstes Projekt mit einer App.
|
||||
|
||||
👉 Screenshot geeignet: Dashboard mit Projekt-Kachel und Post-Limit-Anzeige
|
||||
|
||||
### 5.3 – Keys und Tokens vorbereiten
|
||||
1) Klicke in der App-Kachel auf das **Zahnrad-Symbol → Keys and Tokens**.
|
||||
2) Hier später **API Key & Secret** sowie **Bearer Token** generieren – diese brauchen wir gleich in n8n.
|
||||
|
||||
👉 Screenshot geeignet: Bereich „Keys and Tokens“ vor dem Generieren der Keys
|
||||
|
||||
[!WARNING]
|
||||
Diese Schlüssel sind vertraulich und dürfen nicht öffentlich geteilt oder im Code abgelegt werden.
|
||||
Speichere sie sicher ab.
|
||||
|
||||
### 5.4 – n8n-Credentials anlegen
|
||||
1) Öffne in **n8n** das linke Menü **Credentials → + Neu**.
|
||||
2) Wähle **„X OAuth 2.0 API“** als Typ.
|
||||
3) Kopiere im geöffneten Fenster die angezeigte **OAuth Redirect URL** – diese wird gleich im Developer-Portal benötigt.
|
||||
4) Lasse dieses Credentials-Fenster in n8n geöffnet.
|
||||
|
||||
👉 Screenshot geeignet: n8n – neues Credentials-Fenster mit sichtbarer Redirect-URL
|
||||
|
||||
[!TIP]
|
||||
Die Redirect-URL immer aus dem geöffneten n8n-Fenster kopieren, nicht manuell eintippen.
|
||||
|
||||
### 5.5 – User-Authentication in X einrichten
|
||||
1) Zurück im **Developer-Portal → Projects & Apps → App Details** wechseln.
|
||||
2) Bei **User Authentication Settings** auf **„Set Up“** klicken.
|
||||
3) **App Permissions:** „Read and Write“ auswählen.
|
||||
4) **Type of App:** „Web App, Automated App or Bot“ auswählen.
|
||||
5) Bei **Callback URL** die zuvor aus n8n kopierte Redirect-URL einfügen.
|
||||
6) Bei **Homepage URL** die eigene Domain (z. B. `https://deinedomain.tld`) angeben.
|
||||
7) **Save** klicken und die folgende Warnung bestätigen.
|
||||
|
||||
👉 Screenshot geeignet: Formular „User Authentication Settings“ mit ausgewählter Berechtigung „Read and Write“ und Callback-URL
|
||||
|
||||
[!IMPORTANT]
|
||||
Falls die Berechtigung nicht auf „Read and Write“ steht, können später keine Posts veröffentlicht werden.
|
||||
|
||||
### 5.6 – Client-Daten in n8n eintragen und Account verknüpfen
|
||||
1) Nach dem Speichern erscheinen im Developer-Portal **Client ID** und **Client Secret**.
|
||||
2) Zurück in das noch geöffnete Credentials-Fenster in n8n wechseln.
|
||||
3) **Client ID** und **Client Secret** dort eintragen.
|
||||
4) Auf **„Account verknüpfen“** klicken.
|
||||
5) Es öffnet sich ein Pop-up-Fenster mit der X-Login-Seite.
|
||||
6) Mit dem normalen X-Konto anmelden und die App **autorisieren**.
|
||||
|
||||
[!WARNING]
|
||||
Falls statt „Authorize App“ das X-Dashboard erscheint, das Fenster schließen und den Schritt „Account verknüpfen“ in n8n erneut ausführen.
|
||||
|
||||
👉 Screenshot geeignet: Pop-up mit X-Login und „Authorize App“
|
||||
|
||||
Damit sind die **X-Credentials** in n8n eingerichtet und einsatzbereit.
|
||||
|
||||
### 5.7 – Twitch-Auth-Credentials anlegen
|
||||
|
||||
Damit n8n die geplanten Streams abrufen kann, brauchen wir eine eigene **Twitch-Anwendung** mit User-Token (Authorization-Code-Flow).
|
||||
Die benötigte **OAuth-Redirect-URL** kommt direkt aus n8n, deshalb beginnen wir dort.
|
||||
|
||||
#### 5.7.1 – Redirect-URL aus n8n kopieren
|
||||
1) n8n öffnen → links **Credentials → + Neu**.
|
||||
2) **„Twitch OAuth2 API“** als Typ auswählen.
|
||||
3) Im sich öffnenden Fenster die angezeigte **OAuth Redirect URL** vollständig kopieren.
|
||||
4) Fenster offenlassen, da wir gleich hierher zurückkehren.
|
||||
|
||||
👉 Screenshot geeignet: n8n – neues Twitch-Credential mit sichtbarer Redirect-URL
|
||||
|
||||
[!TIP]
|
||||
Die Redirect-URL immer direkt aus n8n kopieren, nicht manuell eintippen – sonst schlägt die Authentifizierung fehl.
|
||||
|
||||
#### 5.7.2 – Neue Anwendung in der Twitch-Developer-Console anlegen
|
||||
1) Twitch-Developer-Console öffnen: [https://dev.twitch.tv/console/apps](https://dev.twitch.tv/console/apps).
|
||||
2) Mit dem Twitch-Konto anmelden, das später für die Streams genutzt wird.
|
||||
3) Auf **„Register Your Application“** klicken
|
||||
*(in der deutschen Oberfläche: **„Deine Anwendung registrieren“**).*
|
||||
4) Einen aussagekräftigen Namen vergeben, z. B. `n8n-stream-schedule`.
|
||||
5) Unter **OAuth Redirect URLs** die zuvor aus n8n kopierte URL einfügen.
|
||||
6) Unter **Category** „Application Integration“ auswählen.
|
||||
7) Bei **Public / Öffentlich** die Option **„Öffentlich“** aktivieren.
|
||||
8) Auf **Create** klicken.
|
||||
|
||||
👉 Screenshot geeignet: Twitch-Developer-Console – Formular „Register Your Application / Deine Anwendung registrieren“ mit eingetragener Redirect-URL und aktivierter Option „Öffentlich“
|
||||
|
||||
[!IMPORTANT]
|
||||
Die Redirect-URL muss exakt der aus n8n entsprechen, sonst schlägt die spätere Verknüpfung fehl.
|
||||
|
||||
#### 5.7.3 – Client-ID und Secret sichern
|
||||
1) Nach dem Erstellen erscheint die Anwendung in der Übersicht.
|
||||
2) Auf **Manage** klicken.
|
||||
3) Die **Client ID** kopieren.
|
||||
4) Über **New Secret** einen neuen **Client Secret** erzeugen und kopieren.
|
||||
5) Beide Werte sicher speichern.
|
||||
|
||||
👉 Screenshot geeignet: Twitch-Developer-Console – App-Details mit sichtbarer Client ID und Button „New Secret“
|
||||
|
||||
[!WARNING]
|
||||
Der Client Secret ist nur einmal sichtbar. Nicht öffentlich teilen und sicher aufbewahren.
|
||||
|
||||
#### 5.7.4 – Credential in n8n fertigstellen
|
||||
1) Zurück zu n8n in das noch geöffnete Credential-Fenster wechseln.
|
||||
2) Folgende Felder ausfüllen:
|
||||
* **Client ID:** Wert aus der Twitch-Anwendung einfügen
|
||||
* **Client Secret:** Wert aus der Twitch-Anwendung einfügen
|
||||
* **Auth URL:** `https://id.twitch.tv/oauth2/authorize`
|
||||
* **Access Token URL:** `https://id.twitch.tv/oauth2/token`
|
||||
* **Grant Type:** `Authorization Code`
|
||||
* **Scope:** `user:read:broadcast`
|
||||
* **Auth URI Query Parameters:** leer lassen
|
||||
* **Authentication:** `Body`
|
||||
3) Auf **„Account verknüpfen“** klicken.
|
||||
4) Im neuen Fenster mit dem Twitch-Konto anmelden und die Anwendung **autorisieren**.
|
||||
5) Falls statt „Authorize App“ das Twitch-Dashboard erscheint, Fenster schließen und den Vorgang **„Account verknüpfen“** erneut ausführen.
|
||||
|
||||
👉 Screenshot geeignet: Twitch – OAuth-Freigabeseite mit „Authorize App“
|
||||
|
||||
[!NOTE]
|
||||
Der Scope `user:read:broadcast` erlaubt n8n, die geplanten Streams des angegebenen Kanals über die Helix-API abzurufen.
|
||||
|
||||
### 5.8 – Hinweis zu Access Tokens
|
||||
|
||||
Mit den bisher eingerichteten **Credentials** für X und Twitch sind zwar die Schnittstellen verbunden, aber das reicht für den geplanten Workflow noch nicht aus.
|
||||
Viele API-Endpunkte – insbesondere bei Twitch – benötigen zusätzlich einen **Access Token** (Bearer-Token) für jeden Abruf.
|
||||
|
||||
Zwar kann dieser Token theoretisch auch manuell über die Developer-Seiten erzeugt und in n8n eingetragen werden, doch solche Tokens laufen nach kurzer Zeit ab (bei Twitch z. B. meist nach 60 Tagen oder früher).
|
||||
Ein händisches Nachtragen würde bedeuten, dass der Workflow regelmäßig ausfällt und manuell nachgepflegt werden muss.
|
||||
|
||||
[!IMPORTANT]
|
||||
Wir werden deshalb im **Verlauf des Workflows** einen eigenen Node hinzufügen, der den Access Token automatisch anfordert und bei Bedarf erneuert.
|
||||
So bleibt der Workflow stabil und benötigt keine manuelle Pflege.
|
||||
|
||||
## Schritt 6 – Workflow in n8n aufbauen
|
||||
|
||||
In diesem Schritt erstellen wir den eigentlichen Workflow in **n8n**.
|
||||
Wir fügen die benötigten Nodes hinzu und konfigurieren sie so, dass der Workflow regelmäßig die geplanten Twitch-Streams prüft und bei Bedarf automatisch Ankündigungen auf X erstellt.
|
||||
|
||||
### 6.1 – Cron Trigger (Workflow alle 30 Minuten starten)
|
||||
|
||||
**Zweck:**
|
||||
Der Cron-Trigger ist der Startpunkt des Workflows.
|
||||
Er sorgt dafür, dass alle 30 Minuten geprüft wird, ob ein geplanter Stream in Kürze startet.
|
||||
|
||||
**Node-Typ:** `Schedule Trigger`
|
||||
**Name:** `Cron – Workflow alle 30 Minuten starten`
|
||||
|
||||
**Einstellungen im Node:**
|
||||
- **Trigger Interval:** `Minutes`
|
||||
- **Minutes Between Triggers:** `30`
|
||||
|
||||
👉 Screenshot geeignet: n8n – Schedule Trigger mit „Trigger Interval: Minutes“ und Wert „30“
|
||||
|
||||
[!NOTE]
|
||||
Die Zeitzone wird nicht im Node eingestellt.
|
||||
Sie richtet sich nach der **Workflow-Zeitzone** (oben rechts im Workflow → *Settings → Time Zone*).
|
||||
Ist dort nichts gesetzt, gilt die Zeitzone des Servers, auf dem n8n läuft.
|
||||
|
||||
[!TIP]
|
||||
Die Intervalldauer (hier 30 Minuten) kann bei Bedarf angepasst werden. Für Ankündigungen kurz vor dem Stream reicht ein Intervall von 30 Minuten in der Regel aus.
|
||||
|
||||
### 6.2 – Code Node: Access Token prüfen
|
||||
|
||||
**Zweck:**
|
||||
Dieser Node prüft bei jedem Durchlauf, ob bereits ein gültiger Twitch-Access-Token vorhanden ist und wie lange er noch gültig ist.
|
||||
Wenn kein Token existiert oder die Restlaufzeit unter 24 Stunden liegt, markieren wir das für die nächste Stufe (Token erneuern).
|
||||
|
||||
**Node-Typ:** `Code`
|
||||
**Programmiersprache:** `JavaScript`
|
||||
**Name:** `Code – Access Token prüfen`
|
||||
|
||||
**Einstellungen:**
|
||||
- **Language:** `JavaScript`
|
||||
- Den folgenden Code einfügen:
|
||||
|
||||
```javascript
|
||||
// Liest gespeicherten Token aus den globalen Workflow-Daten
|
||||
const sd = $getWorkflowStaticData('global');
|
||||
const token = sd.twitch_token || '';
|
||||
const expISO = sd.twitch_expires_at || '';
|
||||
const expMs = expISO ? new Date(expISO).getTime() : 0;
|
||||
|
||||
const now = Date.now();
|
||||
const msLeft = expMs ? (expMs - now) : 0;
|
||||
const hoursLeft = msLeft > 0 ? (msLeft / (1000*60*60)) : 0;
|
||||
|
||||
// true, wenn kein Token vorhanden ist oder wenn er in <24h abläuft
|
||||
const needsRefresh = !token || !expMs || hoursLeft < 24;
|
||||
|
||||
return [{
|
||||
json: {
|
||||
needsRefresh,
|
||||
token,
|
||||
expires_at: expISO,
|
||||
hoursLeft: Number(hoursLeft.toFixed(2))
|
||||
}
|
||||
}];
|
||||
```
|
||||
|
||||
👉 Screenshot geeignet: n8n – Code-Node mit eingefügtem JavaScript-Code
|
||||
|
||||
[!NOTE]
|
||||
Dieser Node speichert nichts, sondern liefert nur Statusdaten (`needsRefresh`, `hoursLeft`, `expires_at`).
|
||||
Die tatsächliche Erneuerung des Tokens erfolgt später im Workflow.
|
||||
|
||||
### 6.3 – IF Node: Access Token erneuern?
|
||||
|
||||
**Zweck:**
|
||||
Dieser Node prüft, ob aus dem vorherigen Code-Node das Flag `needsRefresh` auf **true** steht.
|
||||
Nur in diesem Fall wird im nächsten Schritt ein neuer Access-Token angefordert.
|
||||
|
||||
**Node-Typ:** `IF`
|
||||
**Name:** `IF – Access Token erneuern?`
|
||||
|
||||
**Einstellungen:**
|
||||
- **Conditions:**
|
||||
- `{{$json.needsRefresh}}`
|
||||
- `is true` *(Type: Boolean)*
|
||||
|
||||
👉 Screenshot geeignet: n8n – IF-Node mit Bedingung `{{$json.needsRefresh}}` → `is true (Boolean)`
|
||||
|
||||
[!IMPORTANT]
|
||||
Stelle sicher, dass der Vergleichs-Typ auf **Boolean** gesetzt ist, sonst wird der Wert eventuell als Text interpretiert und die Abfrage funktioniert nicht korrekt.
|
||||
|
||||
[!NOTE]
|
||||
- **TRUE-Pfad:** Token wird im nächsten Schritt erneuert.
|
||||
- **FALSE-Pfad:** Es wird mit dem bestehenden Token fortgefahren.
|
||||
|
||||
### 6.4 – HTTP Request: Neuen Twitch-Access-Token anfordern *(TRUE-Pfad)*
|
||||
|
||||
**Zweck:**
|
||||
Fordert über die Twitch-API einen neuen Access-Token an, wenn der IF-Node festgestellt hat, dass keiner vorhanden ist oder der aktuelle bald abläuft.
|
||||
|
||||
**Node-Typ:** `HTTP Request`
|
||||
**Name:** `HTTP – Access Token anfordern`
|
||||
|
||||
**Einstellungen:**
|
||||
- **Method:** `POST`
|
||||
- **URL:** `https://id.twitch.tv/oauth2/token`
|
||||
- **Send Body:** aktivieren
|
||||
- **Content Type:** `Form-URL-Encoded`
|
||||
- **Body Parameters:**
|
||||
- `client_id` → Wert aus den in n8n hinterlegten Twitch-Credentials
|
||||
- `client_secret` → Wert aus den Twitch-Credentials
|
||||
- `grant_type` → `client_credentials`
|
||||
|
||||
👉 Screenshot geeignet: n8n – HTTP-Request-Node mit konfigurierten Body-Parametern
|
||||
|
||||
[!NOTE]
|
||||
Der Node gibt als Antwort ein JSON-Objekt mit `access_token` und `expires_in` zurück.
|
||||
Diese Werte werden im nächsten Node gespeichert.
|
||||
|
||||
### 6.5 – Code Node: Neuen Access-Token speichern *(TRUE-Pfad)*
|
||||
|
||||
**Zweck:**
|
||||
Speichert den vom HTTP-Request erhaltenen Twitch-Access-Token und dessen Ablaufzeitpunkt in den globalen Workflow-Daten.
|
||||
So bleibt der Token auch für spätere Workflow-Durchläufe verfügbar.
|
||||
|
||||
**Node-Typ:** `Code`
|
||||
**Programmiersprache:** `JavaScript`
|
||||
**Name:** `Code – Access Token speichern`
|
||||
|
||||
**Einstellungen:**
|
||||
- **Language:** `JavaScript`
|
||||
- Den folgenden Code einfügen:
|
||||
|
||||
```javascript
|
||||
// Speichert neuen Token + Ablaufzeit in Workflow-Static-Data
|
||||
const sd = $getWorkflowStaticData('global');
|
||||
|
||||
const access = $json.access_token;
|
||||
const ttlSec = Number($json.expires_in || 0);
|
||||
|
||||
// Ablaufzeitpunkt berechnen und speichern
|
||||
const expISO = new Date(Date.now() + ttlSec * 1000).toISOString();
|
||||
|
||||
sd.twitch_token = access;
|
||||
sd.twitch_expires_at = expISO;
|
||||
|
||||
// Optional: verbleibende Stunden ausgeben
|
||||
const msLeft = (new Date(expISO).getTime() - Date.now());
|
||||
const hoursLeft = msLeft / (1000 * 60 * 60);
|
||||
|
||||
return [{
|
||||
json: {
|
||||
token: access,
|
||||
expires_at: expISO,
|
||||
hoursLeft: Number(hoursLeft.toFixed(2))
|
||||
}
|
||||
}];
|
||||
```
|
||||
|
||||
👉 Screenshot geeignet: n8n – Code-Node mit eingefügtem JavaScript-Code
|
||||
|
||||
[!NOTE]
|
||||
Dieser Node speichert den neuen Token und gibt ihn zusätzlich mit seiner Restlaufzeit (`hoursLeft`) aus, sodass nachfolgende Nodes die Werte sofort verwenden können.
|
||||
|
||||
### 6.6 – Set Node: Token aus Cache bereitstellen *(FALSE-Pfad)*
|
||||
|
||||
**Zweck:**
|
||||
Wenn der IF-Node feststellt, dass der vorhandene Token noch gültig ist, brauchen wir keinen neuen anzufordern.
|
||||
Dieser Node liest die bereits gespeicherten Token-Daten aus den globalen Workflow-Daten und stellt sie den nachfolgenden Nodes zur Verfügung.
|
||||
|
||||
**Node-Typ:** `Set`
|
||||
**Name:** `Set – Token aus Cache bereitstellen`
|
||||
|
||||
**Einstellungen:**
|
||||
- **Mode:** `Add Field`
|
||||
- **Felder hinzufügen:**
|
||||
- `token` → `{{$json.token}}`
|
||||
- `expires_at` → `{{$json.expires_at}}`
|
||||
- `hoursLeft` → `{{$json.hoursLeft}}`
|
||||
|
||||
👉 Screenshot geeignet: n8n – Set-Node mit eingetragenen drei Feldern (token, expires_at, hoursLeft)
|
||||
|
||||
[!NOTE]
|
||||
Der Set-Node wird nur im **FALSE-Pfad** des IF-Nodes ausgeführt.
|
||||
Er sorgt dafür, dass auch ohne Erneuerung dieselben Felder (`token`, `expires_at`, `hoursLeft`) für die nächsten Schritte bereitstehen.
|
||||
|
||||
### 6.7 – Merge Node: Token-Ströme zusammenführen
|
||||
|
||||
**Zweck:**
|
||||
Führt die beiden möglichen Pfade aus dem IF-Node wieder zusammen:
|
||||
- TRUE-Pfad: liefert den **neu angeforderten Token** aus dem Code-Node „Access Token speichern“.
|
||||
- FALSE-Pfad: liefert den **bereits vorhandenen Token** aus dem Set-Node „Token aus Cache bereitstellen“.
|
||||
|
||||
So steht dem Workflow anschließend unabhängig vom Pfad derselbe Datensatz für die weiteren Schritte zur Verfügung.
|
||||
|
||||
**Node-Typ:** `Merge`
|
||||
**Name:** `Merge – Token zusammenführen`
|
||||
|
||||
**Einstellungen:**
|
||||
- **Mode:** `Append`
|
||||
- **Number of Inputs:** `2`
|
||||
|
||||
👉 Screenshot geeignet: n8n – Merge-Node mit „Mode: Append“ und „Number of Inputs: 2“
|
||||
|
||||
[!NOTE]
|
||||
Da jeweils nur einer der beiden Pfade aktiv ist, genügt der Append-Modus, um den ausgegebenen Datensatz an den Hauptfluss zurückzugeben.
|
||||
|
||||
### 6.8 – HTTP Request: Twitch-Termine laden
|
||||
|
||||
**Zweck:**
|
||||
Dieser Node ruft über die Twitch-Helix-API den aktuellen Stream-Zeitplan des Kanals ab, um zu prüfen, ob innerhalb der nächsten 30 Minuten ein Stream startet.
|
||||
|
||||
**Node-Typ:** `HTTP Request`
|
||||
**Name:** `HTTP – Twitch-Termine laden`
|
||||
|
||||
#### Twitch-User-ID ermitteln (ohne Programmierung)
|
||||
Die `broadcaster_id` ist eine **numerische ID**, die jedem Twitch-Kanal zugeordnet ist.
|
||||
Du brauchst diese Zahl (nicht den Kanalnamen), um die API-Abfrage auszuführen.
|
||||
|
||||
**So findest du sie leicht:**
|
||||
|
||||
1) Öffne im Browser die Seite
|
||||
[https://streamscharts.com/tools/convert-username](https://streamscharts.com/tools/convert-username)
|
||||
2) Gib deinen Twitch-Kanalnamen ein (z. B. `bratonien_tv`).
|
||||
3) Klicke auf **Convert**.
|
||||
4) Die angezeigte Zahl unter „Channel ID“ ist deine `broadcaster_id`.
|
||||
5) Kopiere diese Zahl und trage sie später im HTTP-Request-Node in das Feld **broadcaster_id** ein.
|
||||
|
||||
👉 Screenshot geeignet: StreamsCharts-Tool mit eingegebenem Kanalnamen und angezeigter Channel-ID
|
||||
|
||||
[!TIP]
|
||||
Dieses Tool verwendet offiziell die Twitch-API, du brauchst dort keine eigenen Entwickler-Anmeldungen.
|
||||
|
||||
#### Einstellungen im Node
|
||||
- **Method:** `GET`
|
||||
- **URL:** `https://api.twitch.tv/helix/schedule`
|
||||
- **Send Query:** aktivieren
|
||||
- **Query Parameters:**
|
||||
- `broadcaster_id` → `<Twitch-User-ID>` des Kanals
|
||||
- `start_time` → `{{$now.toUTC().startOf('day').toISO()}}`
|
||||
- **Send Headers:** aktivieren
|
||||
- **Header Parameters:**
|
||||
- `Authorization` → `Bearer {{$json.token}}`
|
||||
- `Client-ID` → `<deine Client-ID aus Twitch-Credentials>`
|
||||
|
||||
👉 Screenshot geeignet: n8n – HTTP-Request-Node mit eingetragenen Query- und Header-Parametern
|
||||
|
||||
[!NOTE]
|
||||
Die `broadcaster_id` ist die eindeutige numerische ID des Kanals.
|
||||
Der Header **Authorization** enthält den Access-Token aus dem Merge-Node.
|
||||
Der Header **Client-ID** ist zwingend erforderlich, sonst verweigert die Helix-API den Zugriff.
|
||||
|
||||
### 6.8 – HTTP Request: Twitch-Termine laden
|
||||
|
||||
**Zweck:**
|
||||
Dieser Node ruft über die Twitch-Helix-API den aktuellen Stream-Zeitplan des Kanals ab, um zu prüfen, ob innerhalb der nächsten 30 Minuten ein Stream startet.
|
||||
|
||||
**Node-Typ:** `HTTP Request`
|
||||
**Name:** `HTTP – Twitch-Termine laden`
|
||||
|
||||
#### Twitch-User-ID ermitteln (ohne Programmierung)
|
||||
Die `broadcaster_id` ist eine **numerische ID**, die jedem Twitch-Kanal zugeordnet ist.
|
||||
Du brauchst diese Zahl (nicht den Kanalnamen), um die API-Abfrage auszuführen.
|
||||
|
||||
**So findest du sie leicht:**
|
||||
|
||||
1) Öffne im Browser die Seite
|
||||
[https://streamscharts.com/tools/convert-username](https://streamscharts.com/tools/convert-username)
|
||||
2) Gib deinen Twitch-Kanalnamen ein (z. B. `bratonien_tv`).
|
||||
3) Klicke auf **Convert**.
|
||||
4) Die angezeigte Zahl unter „Channel ID“ ist deine `broadcaster_id`.
|
||||
5) Kopiere diese Zahl und trage sie später im HTTP-Request-Node in das Feld **broadcaster_id** ein.
|
||||
|
||||
👉 Screenshot geeignet: StreamsCharts-Tool mit eingegebenem Kanalnamen und angezeigter Channel-ID
|
||||
|
||||
[!TIP]
|
||||
Dieses Tool verwendet offiziell die Twitch-API und erfordert keine eigenen Entwickler-Anmeldungen.
|
||||
|
||||
#### Einstellungen im Node
|
||||
- **Method:** `GET`
|
||||
- **URL:** `https://api.twitch.tv/helix/schedule`
|
||||
- **Authentication:** `Generic Credential Type`
|
||||
- **Generic Auth Type:** `OAuth2 API` → wähle hier die zuvor in n8n angelegten **Twitch-Credentials** aus
|
||||
- **Send Query Parameters:** aktivieren
|
||||
- **Query Parameters:**
|
||||
- **Name:** `broadcaster_id` → `<deine Twitch-User-ID>`
|
||||
- **Name:** `start_time` → `{{ $now.toUTC().startOf('day').toISO() }}`
|
||||
- **Send Headers:** aktivieren
|
||||
- **Header Parameters:**
|
||||
- **Name:** `Client-ID` → `<deine Client-ID aus den Twitch-Credentials>`
|
||||
|
||||
👉 Screenshot geeignet: n8n – HTTP-Request-Node mit allen sichtbaren Parametern wie auf den beiden Referenz-Screenshots
|
||||
|
||||
[!NOTE]
|
||||
Der Access-Token wird über die ausgewählte OAuth2-Credential automatisch mitgesendet.
|
||||
Zusätzlich ist nur der **Client-ID**-Header notwendig.
|
||||
Die Option **Never Error** bleibt deaktiviert, da sie hier nicht benötigt wird.
|
||||
|
||||
### 6.9 – Code-Node: „Parse ICS“
|
||||
|
||||
**Zweck:**
|
||||
Dieser Node verarbeitet die Antwort des Nodes **„Twitch-Termine laden“**.
|
||||
Er liest das JSON aus der Helix-API und erzeugt für jedes Stream-Segment ein einheitliches Objekt mit Start- und Endzeit, Titel, Beschreibung und einer Hash-ID.
|
||||
So können wir die Termine später leichter filtern und weiterverarbeiten.
|
||||
|
||||
**Node-Typ:** `Code`
|
||||
**Name:** `Parse ICS`
|
||||
|
||||
👉 Screenshot geeignet: n8n – geöffneter Code-Node mit eingefügtem Skript
|
||||
|
||||
#### Node-Einstellungen
|
||||
- **Programming Language:** `JavaScript`
|
||||
- Weitere Einstellungen bleiben auf Standard.
|
||||
|
||||
#### Eingabe
|
||||
Der Node erwartet die Antwort des HTTP-Requests **„Twitch-Termine laden“**.
|
||||
Der Inhalt liegt meist als Text-String in `items[0].json.body` vor.
|
||||
|
||||
#### Code-Inhalt
|
||||
Kopiere den folgenden Code komplett in das Editorfeld des Code-Nodes:
|
||||
|
||||
```
|
||||
/**
|
||||
* INPUT: items[0].json ODER items[0].json.body (String) vom HTTP Request /helix/schedule
|
||||
* OUTPUT: pro Segment ein Item in folgendem Schema:
|
||||
* { uid, cancelled, title, description, startIso, endIso, tz, hash }
|
||||
*/
|
||||
|
||||
const input = items[0]?.json ?? {};
|
||||
let payload;
|
||||
|
||||
if (typeof input.body === 'string') {
|
||||
// HTTP-Node hat "Response Format: Text" -> JSON-String in body
|
||||
try { payload = JSON.parse(input.body); }
|
||||
catch (e) { throw new Error('HTTP body ist kein gültiges JSON'); }
|
||||
} else if (input.data) {
|
||||
// HTTP-Node hat "Response Format: JSON"
|
||||
payload = input;
|
||||
} else if (typeof input === 'string') {
|
||||
payload = JSON.parse(input);
|
||||
} else {
|
||||
throw new Error('Unerwartete Eingabeform. Erwartet JSON oder body-String.');
|
||||
}
|
||||
|
||||
const segments = Array.isArray(payload.data?.segments) ? payload.data.segments : [];
|
||||
|
||||
// Hash für eindeutige Segmentkennung
|
||||
function hashHex(s) {
|
||||
let h = 5381;
|
||||
for (let i = 0; i < s.length; i++) h = ((h << 5) + h) ^ s.charCodeAt(i);
|
||||
return (h >>> 0).toString(16).padStart(8, '0');
|
||||
}
|
||||
|
||||
function buildTitle() { return 'Streamtime'; }
|
||||
|
||||
function buildDesc(seg) {
|
||||
const lines = [];
|
||||
if (seg.title) lines.push(`Originaltitel: ${seg.title}`);
|
||||
if (seg.category?.name) lines.push(`Kategorie/Game: ${seg.category.name}`);
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
const tz = 'Europe/Berlin';
|
||||
|
||||
const out = segments.map(seg => {
|
||||
const startIso = seg.start_time; // ISO-UTC laut Twitch
|
||||
const endIso = seg.end_time;
|
||||
const title = buildTitle();
|
||||
const description = buildDesc(seg);
|
||||
const hash = hashHex(`${title}|${startIso}|${endIso}|${description}`);
|
||||
|
||||
return {
|
||||
json: {
|
||||
uid: seg.id,
|
||||
cancelled: Boolean(seg.canceled_until),
|
||||
title, description,
|
||||
startIso, endIso, tz,
|
||||
hash
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return out;
|
||||
```
|
||||
|
||||
[!NOTE]
|
||||
- `tz` ist fest auf `Europe/Berlin` gesetzt, kann aber bei Bedarf angepasst werden.
|
||||
- Das Feld `cancelled` wird genutzt, um abgesagte Streams zu kennzeichnen.
|
||||
- Jeder Stream-Eintrag erhält einen Hash, der später als eindeutiger Schlüssel dient.
|
||||
Reference in New Issue
Block a user