diff --git a/Kapitel 13/Tutorial.md b/Kapitel 13/Tutorial.md index 15116fd..b72397b 100644 --- a/Kapitel 13/Tutorial.md +++ b/Kapitel 13/Tutorial.md @@ -354,24 +354,27 @@ In diesem Schritt erstellen wir den eigentlichen Workflow in **n8n**. Er sorgt d - Dieser Node löst den Workflow regelmäßig aus. - Stelle ein: alle **10 Minuten** ausführen. -2. **HTTP Request – Twitch Videos abfragen** (Node-Name: `HTTP – Get Videos`) - - Dieser Node ruft über die Twitch-API alle VODs deines Accounts ab. - - URL: - ``` - https://api.twitch.tv/helix/videos?user_id=&type=archive - ``` - - Authentifizierung: OAuth2 (Credential „Twitch API“) - - Header: `Client-Id: ` +2. **HTTP Request – Get Videos** (Node-Name: `Get Twitch VOD IDs`) + - **Node-Typ:** HTTP Request + - **Methode:** GET + - **URL:** `https://api.twitch.tv/helix/videos?user_id=&type=archive&first=20` + - **Authentifizierung:** OAuth2 (Credential: *Twitch API*) + - **Header:** Client-Id: + - **Response Format:** JSON ** -3. **SSH Credentials in n8n anlegen** - - Damit n8n mit dem Clipper kommunizieren kann, brauchst du SSH-Zugangsdaten. - - Trage in n8n ein: - * Name: `SSH Clipper` - * Host: `` (z. B. `10.0.0.42`) - * Port: `22` - * Username: `clipper` - * Private Key: Inhalt von `~/.ssh/id_n8n_clipper` - * Working Directory: `/srv/clipper` + 2.1 **SSH Credentials in n8n anlegen** + - Damit n8n mit dem Clipper kommunizieren kann, brauchst du SSH-Zugangsdaten. + - Trage in n8n ein: + * Name: `SSH Clipper` + * Host: `` (z. B. `10.0.0.42`) + * Port: `22` + * Username: `clipper` + * Private Key: Inhalt von `~/.ssh/id_n8n_clipper` + * Working Directory: `/srv/clipper` + +3. **Split Out – vods** (Node-Name: `Split Out – Twitch VOD`) + - Node-Typ: Split Out + - Field to Split Out: `data` 4. **SSH Node – State-Datei prüfen** (Node-Name: `SSH – Check State`) - Dieser Schritt prüft, ob die Datei `/srv/clipper/state/vod_seen.list` bereits existiert und ob VOD-IDs eingetragen sind. @@ -386,37 +389,49 @@ In diesem Schritt erstellen wir den eigentlichen Workflow in **n8n**. Er sorgt d {"file_exists":true,"non_empty":true,"vods":["123456789","987654321"]} ``` -5. **Set Node – Ergebnisse übernehmen** (Node-Name: `Set – State Ergebnis`) - - Ziel: die Ausgabe aus dem vorherigen Schritt in Felder umwandeln, die n8n versteht. - - Expressions: - * file_exists → `{{ JSON.parse($json.stdout).file_exists }}` - * non_empty → `{{ JSON.parse($json.stdout).non_empty }}` - * vods → `{{ JSON.parse($json.stdout).vods }}` +5. **Set – File Information** (Node-Name: `Set – File Information`) + - Node-Typ: Set + - Field: file_exists + - Type: Boolean + - Expression: `{{ JSON.parse($json.stdout).file_exists }}` + - Field: non_empty + - Type: Boolean + - Expression: `{{ JSON.parse($json.stdout).non_empty }}` + - Field: vods + - Type: Array + - Expression: `{{ JSON.parse($json.stdout).vods }} ` + - Add Option: Ignore Type Conversion Errors -> "ON" - > [!IMPORTANT] - > Hier nur die Expressions eintragen, keine Typ-Konvertierungen vornehmen. - -6. **If-Node – Entscheidung** (Node-Name: `If – State Prüfung`) - - Dieser Node entscheidet, ob neue VODs heruntergeladen werden müssen. - - Bedingungen: +6. **Set – vods in Array** (Node-Name: `Set – vods in Array`) + - Node-Typ: Set + - Field: vods + - Type: Array + - Expression: + ```js + {{ (typeof $json.vods === 'string' ? $json.vods : String($json.vods)) + .split(',') + .map(s => s.trim()) + .filter(Boolean) }} ``` - 1. Bedingung: {{ $json.file_exists }} is true (Boolean) - 2. Bedingung: {{ $json.non_empty }} is true (Boolean) - Operator: AND - ``` - - Ergebnis: zwei mögliche Pfade → False = neu anlegen, True = prüfen auf neue VODs. ---- +7. **Split Out – vods** (Node-Name: `Split Out – vods`) + - Node-Typ: Split Out + - Field to Split Out: `vods` -7. **False-Pfad – VODs herunterladen und hochladen** +8. **Vorbereitungen für VOD Download und Speicherung** - > [!NOTE] - > Dieser Pfad läuft, wenn die State-Datei nicht existiert oder leer ist. Es werden alle VODs heruntergeladen und in Nextcloud hochgeladen. - - **A. Vorbereitung (einmalig) – rclone an Nextcloud anbinden** - **Ort:** Clipper-LXC Shell + **8.1 Vorbereitung (einmalig) – rclone an Nextcloud anbinden** + Ort: Clipper-LXC Shell + Öffne hierzu in Proxmox, Putty, oder einer anderen Konsole den Clipper LXC und gebe die folgenden Befehele ein: ```bash apt update && apt install -y rclone + ``` + Hiermit installieren wie rclone, was wir später für den Upload zu Nextcloud nutzen werden + + Wechsel dann zu dem vorhin erstellten NUtzer (in diesem Tutorial Clipper) und erstelle eine WebDAV Anbindung an deine Nextcloud. + Hierfür verwnedest du die folgenden Befehle: + + ```bash su - clipper rclone config create nc webdav \ url=https://DEINE_DOMAIN/remote.php/dav/files/DEIN_BENUTZERNAME/ \ @@ -425,15 +440,16 @@ In diesem Schritt erstellen wir den eigentlichen Workflow in **n8n**. Er sorgt d pass=$(rclone obscure 'DEIN_APP_PASSWORT') rclone ls nc: --config /home/clipper/.config/rclone/rclone.conf ``` - > [!NOTE] - > Uploads laufen im Clipper mit rclone. Das ist robuster als Upload-Nodes in n8n, vermeidet Fehler und räumt lokale Dateien auf. - **B. Download/Upload Skript erstellen** + **8.2 Download/Upload Skript erstellen** **Ort:** Clipper-LXC Shell + + Noch immer in der Konsole des Clipper LXC verlässt du mit `exit` den User und bist wieder root User. + Im Anschluss erstellst du eine neue Datei mit ```bash nano /bin/clipper-vod-get ``` - Inhalt: + Nun befüllst du sie mit: ```bash #!/usr/bin/env bash set -euo pipefail @@ -512,7 +528,9 @@ In diesem Schritt erstellen wir den eigentlichen Workflow in **n8n**. Er sorgt d log "=== Done VOD $ID ===" ``` - Rechte setzen: + Mit diesem Skript laden wir die aktuellen VODs herunter, laden sie in die Nextcloud für die weitere Verabeitung und räumen wieder auf. Zusätzlich erzeugen wir logs in `/logs/.log`. + + Damit die Datei auch ausgeführt werden kann, musst du die folgenden zwei Befehle eingeben: ```bash chmod 755 /bin/clipper-vod-get chown clipper:clipper /bin/clipper-vod-get @@ -520,48 +538,27 @@ In diesem Schritt erstellen wir den eigentlichen Workflow in **n8n**. Er sorgt d > [!NOTE] > Pro VOD entsteht ein Logfile in `/logs/.log`. Du kannst es live mit `tail -f /logs/.log` verfolgen. - --- - - Mit diesem Aufbau ist der **False-Pfad** fertig: Wenn die State-Datei fehlt oder leer ist, werden alle VODs verarbeitet und in Nextcloud hochgeladen. Der True-Pfad folgt im nächsten Abschnitt. - - **C. n8n‑Verkabelung (Überblick)** - Ort: *n8n Weboberfläche* - - **Verkabelung (Kurzüberblick):** - 1) HTTP Request → - 2) Split Out: → 3) Merge → - 4) Split In Batches → - 5) SSH Node 1 (State-Datei schreiben) → - 6) SSH Node 2 (Download & Upload) - --- - - ** Node-Einstellungen (1:1 in n8n eintragen)** - **1) HTTP Request – Get Videos** - - - **Node-Typ:** HTTP Request - - - **Methode:** GET - - - **URL:** `https://api.twitch.tv/helix/videos?user_id=&type=archive&first=20` - - **Authentifizierung:** OAuth2 (Credential: *Twitch API*) - - **Header:** Client-Id: - - **Response Format:** JSON ** - - 2) Item Lists – Split Out** - - **Node-Typ:** Split Out - - **Field to Split Out:** data ** - - 3) Merge – Combine** +9. **Merge – Combine** (Node-Name: `Select VODs to Download`) - **Node-Typ:** Merge - **Mode:** Combine - - **Combine Mode:** All Possible Combinations - - **Eingang 1:** If False Ausgang - - **Eingang 2:** Item Lists: Split Out - - **4) Split In Batches** + - **Combine By:** Matching Fields + - **Fields To Match Have Different Names**: "ON" + - **Eingang 1:** Split Out – vods + - **Eingang 2:** Split Out – Twitch VOD + - **Input 1 Field**: vods + - **Input 2 Field**: data.id + - **Output Type**: Keep Non-Matches + - **Output Data From**: Input 2 + Mit diesem Merge Node sorgen wir dafür, dass wir nur die VODs herunter laden, die neu sind und noch nicht von Clipper bearbeitet wurden. + +10. **Split In Batches** (Node-Name: `Einzeldurchlauf`) - **Node-Typ:** Split In Batches - **Batch Size:** 1 - - **5) SSH Node 1 – State-Datei schreiben** + Dieser Node sorgt dafür, dass wenn mal mehr wie ein VOD heruntergaladen werden muss dies nicht parallel geschieht. S sparen wir Ressourcen und sind schneller mit der Arbeit fertig. + +11. **SSH Node 1 – State-Datei schreiben** (Node-Name: `State Datei schreiben`) - **Node-Typ:** SSH - - **Credentials:** *SSH Clipper* (User = clipper) + - **Credentials:** *SSH Clipper* - **Operation:** Execute Command - **Command is an Expression:** **ON** - **Command:** @@ -569,108 +566,27 @@ In diesem Schritt erstellen wir den eigentlichen Workflow in **n8n**. Er sorgt d {{`set -euo pipefail; STATE="/srv/clipper/state/vod_seen.list"; mkdir -p "$(dirname "$STATE")"; if [ -s "$STATE" ]; then printf "%s\n" "${$json.data.id}" >> "$STATE"; else printf "%s\n" "${$json.data.id}" > "$STATE"; fi`}} ``` - **6) SSH Node 2 – Download & Upload (Skript)** +12. **SSH Node 2 – Download & Upload** (Node-Name: `Down 'n' Up`) - **Node-Typ:** SSH - - **Credentials:** *SSH Clipper* (User = clipper) + - **Credentials:** *SSH Clipper* - **Operation:** Execute Command - **Command is an Expression:** **ON** - **Command:** ```bash /bin/clipper-vod-get "{{$('Merge').item.json.data.id}}" "{{ $json.url || ('https://www.twitch.tv/videos/' + $('Merge').item.json.data.id) }}" ``` +Diese 11 Nodes werden das gesamte Grundgerüst der gesamten Automation sein. Wie aber müssen sie verbudnen werden? +Das folgende Schaubild zeigt dir die konkrete Verkabelung - --- - **Ergebnis** - - n8n steuert den gesamten Prozess, Upload erfolgt zuverlässig im Clipper via rclone. - - Pro VOD entsteht **eine** MP4 in Nextcloud: /VODs//. - - Pro VOD gibt es ein eigenes Logfileverzeichnis unter /logs//download.log. - - Lokaler Speicher bleibt frei (automatisches Löschen nach Upload). - - Logs der Schritte findest du im SSH‑Node‑Output und persistent im Logfile. - - --- - -### Schritt 8: True-Pfad – Check und ggf. Download +```bash + --- *SSH – Check State* --- *Set – File Information* --- *Set – vods in Array* --- *Split Out – vods* ------ + | | +*Cron – Alle 10 Min* ---- | *Select VODs to Download* --- *Einzeldurchlauf* --- *State Datei schreiben* --- *Down 'n' Up* --- (Hier folgen später weitere Nodes, aber da der Einzeldurchlauf ein Loop ist wird der letzte Node mit Einzeldurchlauf verbunden) + | | + --- *Get Twitch VOD IDs* --- *Split Out* – *Twitch VOD* -------------------------------------------------- +``` - > [!NOTE] - > Der **False-Pfad** wurde bereits im vorherigen Abschnitt vollständig erklärt. Viele Nodes überschneiden sich mit dem True-Pfad. Damit du nicht alles doppelt anlegen musst, verweisen wir hier auf die bereits erstellten und konfigurierten Nodes. - - - --- - - - **Verkabelung (Kurzüberblick):** - 1) HTTP Request → - 2) Split Out → - 3) Set – vods in Array → - 4) Split Out Array → - 5) Merge → - 6) Split In Batches → - 7) SSH – Write State → - 8) SSH – Download VOD - - - --- - - - ### Node-Einstellungen (1:1 in n8n eintragen) - - - > [!IMPORTANT] - > Die folgenden Nodes haben wir im vorherigen Schritt (False-Pfad) bereits erstellt und konfiguriert. Wenn du dem Tutorial bis hierhin gefolgt bist, musst du an diesen Nodes nichts mehr verändern: - > - **HTTP Request – Get Videos** - > - **Split Out – data** - > - **Split In Batches** - > - **SSH – Write State** - > - **SSH – Download VOD** - - - --- - - - **Neu im True-Pfad:** - - - **3) Set – vods in Array** (Node-Name: `Set – vods in Array`) - - Node-Typ: Set - - Field: vods - - Expression: - ```js - {{ (typeof $json.vods === 'string' ? $json.vods : String($json.vods)) - .split(',') - .map(s => s.trim()) - .filter(Boolean) }} - ``` - - - **4) Split Out – vods** (Node-Name: `Split Out – vods`) - - Node-Typ: Split Out - - Field to Split Out: vods - - - **5) Merge – Combine** (Node-Name: `Merge – Combine`) - - Node-Typ: Merge - - Mode: Combine - - Combine Mode: Matching Fields - - Fields To Match Have Different Names: ON - - Field 1: vods - - Field 2: data.id - - Output Type: Keep Non-Matches - - Output Data From: Input 2 - - Eingang 1: Split Out Array VODs - - Eingang 2: Split Out Twitch VODs - - - --- - - - ### Ergebnis - - Es werden nur **neue VODs** heruntergeladen und hochgeladen. - - Die State-Datei wird erweitert, ohne bestehende IDs zu überschreiben. - - Logs bleiben konsistent, Doppel-Downloads werden vermieden. - - Jeder Node ist eindeutig benannt, was die Übersicht verbessert. - - --- # 🧪 Abschnitt 4 – Analyse