Kapitel 10/Free Rhohtext.md aktualisiert

This commit is contained in:
2025-10-08 20:14:18 +00:00
parent ffbc6d7a02
commit a0b33cec67

View File

@@ -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.