Kapitel 10/Free Rhohtext.md aktualisiert

This commit is contained in:
2025-10-09 19:42:33 +00:00
parent a0b33cec67
commit 996722e066

View File

@@ -421,6 +421,44 @@ Ein händisches Nachtragen würde bedeuten, dass der Workflow regelmäßig ausf
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.
### 5.9 Nextcloud-Credentials anlegen
**Zweck:**
Damit n8n automatisch auf Dateien in deiner Nextcloud zugreifen kann (z. B. für vorbereitete Posts oder temporäre Daten), benötigen wir ein eigenes App-Passwort und ein passendes Credential in n8n.
#### In Nextcloud: App-Passwort erstellen
1) Melde dich in deiner **Nextcloud** an.
2) Öffne oben rechts das **Benutzermenü → Einstellungen**.
3) Wähle im linken Menü den Punkt **Sicherheit** (engl. „Security“).
4) Scrolle nach unten bis zum Bereich **App-Passwörter**.
5) Vergib unter „Neues App-Passwort“ einen Namen, z. B. `n8n`.
6) Klicke auf **App-Passwort erstellen**.
7) Kopiere den angezeigten Schlüssel sofort er wird nur einmal angezeigt.
👉 Screenshot geeignet: Nextcloud Bereich *Sicherheit / App-Passwörter*
[!IMPORTANT]
Nur dieses **App-Passwort** wird in n8n verwendet, **nicht** dein normales Login-Passwort.
Das App-Passwort kann bei Bedarf jederzeit widerrufen oder neu erstellt werden.
#### In n8n: Credential hinzufügen
1) Öffne in n8n oben links **+ → Credentials → Nextcloud**.
2) Trage folgende Werte ein:
| Feld | Wert / Beschreibung |
|------|---------------------|
| **Name** | `Nextcloud` |
| **Base URL** | `https://deine-domain.tld` *(ohne `/remote.php/...`)* |
| **Username** | dein Nextcloud-Benutzername |
| **Password** | das zuvor erstellte App-Passwort |
3) Klicke auf **Save**.
👉 Screenshot geeignet: n8n Nextcloud-Credential mit Base URL und App-Passwort
[!NOTE]
Das Credential „Nextcloud“ wird später in Schritt **6.13** verwendet, um Dateien wie `posts.txt` automatisiert aus der Cloud zu laden und lokal zu verarbeiten.
## Schritt 6 Workflow in n8n aufbauen
In diesem Schritt erstellen wir den eigentlichen Workflow in **n8n**.
@@ -810,3 +848,179 @@ return out;
- `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.
### 6.10 Code-Node: „Nächstes Event finden“
**Zweck:**
Dieser Node wählt aus allen vom **„Parse ICS“**-Node gelieferten Terminen den **nächsten bevorstehenden Stream** aus.
Er liefert das Start-Datum und die relevanten Infos des nächsten Events als einzelnes Item.
**Node-Typ:** `Code`
**Name:** `Nächstes Event finden`
👉 Screenshot geeignet: n8n geöffneter Code-Node mit dem folgenden Script
#### Node-Einstellungen
- **Programming Language:** `JavaScript`
- Alle weiteren Optionen bleiben auf Standard.
#### Eingabe
Dieser Node erwartet als Input die komplette Liste der Stream-Segmente aus dem Node **„Parse ICS“**.
#### Code-Inhalt
Kopiere den folgenden Code vollständig in das Code-Feld:
```
/**
* INPUT: Array von Items aus "Parse ICS"
* OUTPUT: nur das nächste bevorstehende Event
*/
const now = Date.now();
const upcoming = items
.map(i => i.json)
.filter(e => !e.cancelled && new Date(e.startIso).getTime() > now)
.sort((a, b) => new Date(a.startIso) - new Date(b.startIso));
if (upcoming.length === 0) {
return [{ json: { message: 'Kein bevorstehender Stream gefunden' } }];
}
const next = upcoming[0];
return [{
json: {
uid: next.uid,
title: next.title,
description: next.description,
startIso: next.startIso,
endIso: next.endIso,
tz: next.tz,
hash: next.hash
}
}];
```
[!TIP]
Dieser Node gibt **genau ein Item** mit dem nächsten Stream zurück.
Fehlt ein Termin, wird eine kurze Meldung im Feld `message` ausgegeben.
### 6.11 Code-Node: „Stream prüfen“
**Zweck:**
Dieser Node überprüft, ob der nächste geplante Stream in den kommenden **30 Minuten** beginnt und ob für diesen Stream bereits ein Post veröffentlicht wurde.
Nur wenn beide Bedingungen erfüllt sind, wird der Workflow fortgesetzt.
**Node-Typ:** `Code`
**Name:** `Stream prüfen`
👉 Screenshot geeignet: n8n geöffneter Code-Node mit folgendem Script
#### Node-Einstellungen
- **Programmiersprache:** `JavaScript`
- Keine weiteren Optionen ändern
#### Eingabe
Der Node erhält den Output aus **„Nächstes Event finden“** also einen einzelnen Stream-Eintrag mit `uid`, `title`, `startIso` und weiteren Feldern.
#### Code-Inhalt
Kopiere den folgenden Code:
```
/**
* Prüft:
* 1. Startet der Stream in ≤ 30 Minuten?
* 2. Wurde bereits ein Post erstellt?
*
* Zeitumwandlung: Twitch liefert UTC ("2025-10-15T16:00:00Z").
* Wir rechnen in lokale Zeit (Europe/Berlin), um MEZ/MESZ korrekt zu berücksichtigen.
*/
const event = items[0]?.json ?? {};
if (!event.startIso) {
return [{
json: {
postAllowed: false,
reason: 'Kein Termin gefunden'
}
}];
}
// Aktuelle Zeit + Startzeit in lokale Zeitzone überführen
const tz = 'Europe/Berlin';
const now = new Date(); // lokale Zeit des n8n-Servers
const startUtc = new Date(event.startIso);
// Startzeit in lokales Format (inkl. Sommer-/Winterzeit)
const startLocal = new Date(startUtc.toLocaleString('en-US', { timeZone: tz }));
// Differenz in Minuten
const diffMin = (startLocal - now) / 60000;
const within30 = diffMin > 0 && diffMin <= 30;
// Zugriff auf global gespeicherte IDs
const sd = $getWorkflowStaticData('global');
sd.postedIds = sd.postedIds || [];
const alreadyPosted = sd.postedIds.includes(event.uid);
// Wenn innerhalb von 30 Minuten und noch kein Post → erlauben
if (within30 && !alreadyPosted) {
sd.postedIds.push(event.uid);
return [{
json: {
...event,
postAllowed: true,
reason: 'Stream startet bald, noch kein Post vorhanden',
localStart: startLocal.toISOString(),
diffMinutes: Math.round(diffMin)
}
}];
}
// Keine Aktion notwendig
return [{
json: {
...event,
postAllowed: false,
reason: alreadyPosted
? 'Für diesen Stream wurde bereits gepostet'
: 'Stream liegt außerhalb des 30-Minuten-Fensters',
localStart: startLocal.toISOString(),
diffMinutes: Math.round(diffMin)
}
}];
```
[!NOTE]
Dieser Node speichert die **UID jedes angekündigten Streams** im Workflow-Speicher (`global static data`).
So wird sichergestellt, dass kein Termin doppelt angekündigt wird auch nicht nach einem Neustart des Systems.
Der Zeitvergleich erfolgt in **MEZ/MESZ (Europe/Berlin)**, damit lokale Streamzeiten korrekt erkannt werden.
### 6.12 IF-Node: „Post ausführen?“
**Zweck:**
Der IF-Node entscheidet, ob tatsächlich ein Social-Post (z. B. auf X) ausgelöst werden soll.
Er prüft das Feld `postAllowed`, das aus dem vorherigen Code-Node stammt.
**Node-Typ:** `IF`
**Name:** `Post ausführen?`
👉 Screenshot geeignet: n8n geöffneter IF-Node mit konfigurierter Bedingung
#### Node-Einstellungen
**Conditions**
| Feld | Einstellung |
|------|--------------|
| **Left Value** | `{{$json.postAllowed}}` |
| **Operator** | `is true` |
| **Type** | `Boolean` |
[!NOTE]
- Der *True*-Pfad wird nur ausgeführt, wenn der Stream innerhalb der nächsten 30 Minuten startet **und** noch kein Post gesendet wurde.
- Der *False*-Pfad kann später genutzt werden, um Debug-Logs oder Benachrichtigungen zu schreiben (z. B. „Kein Post nötig“).
👉 Screenshot geeignet: n8n IF-Node mit `{{$json.postAllowed}} is true (Boolean)`