1167 lines
41 KiB
JSON
1167 lines
41 KiB
JSON
{
|
|
"name": "brief-vorbereiten",
|
|
"nodes": [
|
|
{
|
|
"parameters": {},
|
|
"type": "n8n-nodes-base.manualTrigger",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
-460,
|
|
40
|
|
],
|
|
"id": "1dab9a40-e8e4-4ed9-9d08-f2fb190e84e9",
|
|
"name": "Manuell starten"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"rule": {
|
|
"interval": [
|
|
{
|
|
"field": "weeks",
|
|
"triggerAtDay": [
|
|
1
|
|
],
|
|
"triggerAtHour": 7,
|
|
"triggerAtMinute": 0
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.scheduleTrigger",
|
|
"typeVersion": 1.2,
|
|
"position": [
|
|
-460,
|
|
200
|
|
],
|
|
"id": "97b85f88-70a1-4809-9d9f-c4c42bd3e9e3",
|
|
"name": "Zeitplan Montag 07:00",
|
|
"disabled": true
|
|
},
|
|
{
|
|
"parameters": {
|
|
"httpMethod": "POST",
|
|
"path": "brief-vorbereiten",
|
|
"responseMode": "onReceived",
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.webhook",
|
|
"typeVersion": 2.1,
|
|
"position": [
|
|
-460,
|
|
360
|
|
],
|
|
"id": "31c56760-74e3-47ce-8a4d-6bd2c7457b57",
|
|
"name": "Webhook Start",
|
|
"webhookId": "a8ccffdc-60e5-44cf-a265-36a8adc3f8e3"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "manual",
|
|
"assignments": {
|
|
"assignments": [
|
|
{
|
|
"id": "f6274e65-1885-4e17-9705-000b0e6278e8",
|
|
"name": "nw_base",
|
|
"value": "https://app.neuronwriter.com/neuron-api/0.5/writer",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"id": "d147d08b-df1e-4c2c-9c61-ca8b98964e04",
|
|
"name": "nw_project",
|
|
"value": "3da4d745e0e223cb",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"id": "f19059cd-b921-4e8d-b858-7a82f3b7cd13",
|
|
"name": "nw_engine",
|
|
"value": "google.de",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"id": "fe8977fb-eda6-4822-906e-2a540af9800c",
|
|
"name": "nw_language",
|
|
"value": "German",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"id": "c0e4d454-74d6-47a1-aeaa-afe02be159df",
|
|
"name": "gitea_base",
|
|
"value": "http://gitea:3000",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"id": "1b412202-179b-435d-bb0d-91e6457b0e77",
|
|
"name": "gitea_owner",
|
|
"value": "lucas.orth",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"id": "dc874ab8-3902-4f47-8ce5-eb942b6ed0a3",
|
|
"name": "gitea_repo",
|
|
"value": "Skrift-Auto-Article",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"id": "15d0ffcf-3553-469a-ae47-4611dba81385",
|
|
"name": "branch",
|
|
"value": "main",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"id": "aef6b9cb-6e4e-431f-9170-3348609db189",
|
|
"name": "index_pfad",
|
|
"value": "artikel-index.json",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"id": "558a0e5e-dedb-4980-ae3e-8b9d5ebc2073",
|
|
"name": "brief_ordner",
|
|
"value": "briefe",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"id": "d19f00fe-1f58-4481-a4a9-ff0c37a1575b",
|
|
"name": "poll_max",
|
|
"value": 30,
|
|
"type": "number"
|
|
},
|
|
{
|
|
"id": "a586e75e-cf55-4058-bde0-91ae53405566",
|
|
"name": "poll_sekunden",
|
|
"value": 20,
|
|
"type": "number"
|
|
},
|
|
{
|
|
"id": "bb43c442-b040-473e-a77b-d6b785785563",
|
|
"name": "pause_zwischen_artikeln",
|
|
"value": 5,
|
|
"type": "number"
|
|
},
|
|
{
|
|
"id": "ad45dd10-9b09-4113-bd0e-1e2625bd4c2f",
|
|
"name": "benachrichtigung_an",
|
|
"value": "privat@lucas-orth.de",
|
|
"type": "string"
|
|
}
|
|
]
|
|
},
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 3.4,
|
|
"position": [
|
|
-240,
|
|
200
|
|
],
|
|
"id": "8d2693c2-31b1-421a-83aa-9c04f898105b",
|
|
"name": "Konfiguration"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "GET",
|
|
"url": "={{ $json.gitea_base }}/api/v1/repos/{{ $json.gitea_owner }}/{{ $json.gitea_repo }}/contents/{{ $json.index_pfad }}?ref={{ $json.branch }}",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"options": {
|
|
"response": {
|
|
"response": {
|
|
"neverError": false
|
|
}
|
|
},
|
|
"timeout": 60000
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
-20,
|
|
200
|
|
],
|
|
"id": "c00ff479-1649-419a-b084-07dc1468838f",
|
|
"name": "Artikeltabelle lesen",
|
|
"credentials": {
|
|
"httpHeaderAuth": {
|
|
"id": "VOD4JM5zwpSC8wAr",
|
|
"name": "Gitea Skrift Auto Article"
|
|
}
|
|
},
|
|
"onError": "continueErrorOutput",
|
|
"retryOnFail": true,
|
|
"maxTries": 3,
|
|
"waitBetweenTries": 3000
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst e = $input.first().json;\nthrow new Error(\n 'Artikeltabelle konnte nicht gelesen werden. Pruefen: Gitea-Token-Scope (write:repository noetig), '\n + 'Pfad artikel-index.json im Branch main, Repo-Name. Antwort: '\n + JSON.stringify(e).slice(0, 600)\n);\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
-20,
|
|
420
|
|
],
|
|
"id": "1463b817-36ba-4442-97c1-552752bfde17",
|
|
"name": "Fehler Artikeltabelle"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\n// Gitea liefert den Dateiinhalt base64-kodiert.\nconst antwort = $input.first().json;\nif (!antwort.content) {\n throw new Error('Gitea-Antwort enthaelt kein Feld \"content\". Erhalten: ' + JSON.stringify(antwort).slice(0,400));\n}\nconst roh = Buffer.from(antwort.content, 'base64').toString('utf8');\nlet tabelle;\ntry { tabelle = JSON.parse(roh); }\ncatch (e) { throw new Error('artikel-index.json ist kein gueltiges JSON: ' + e.message); }\nif (!Array.isArray(tabelle)) {\n throw new Error('artikel-index.json muss ein Array sein, ist aber: ' + typeof tabelle);\n}\n\nconst konf = $('Konfiguration').first().json;\nconst pflicht = ['slug','titel','keyword','kategorie','cta_ziel','status'];\n\nconst offen = [];\ntabelle.forEach((zeile, i) => {\n if (zeile.status !== 'offen') return;\n const fehlt = pflicht.filter(f => !zeile[f]);\n if (fehlt.length) {\n throw new Error(`Zeile ${i} (slug: ${zeile.slug || '?'}) fehlen Pflichtfelder: ${fehlt.join(', ')}`);\n }\n offen.push({ json: { ...zeile, zeilen_index: i } });\n});\n\n// Kontext fuer spaetere Nodes einmal ablegen\nconst kontext = { index_sha: antwort.sha, tabelle_gesamt: tabelle, anzahl_offen: offen.length };\n$getWorkflowStaticData('global').lauf = kontext;\n\nif (offen.length === 0) return [{ json: { ...kontext, leer: true } }];\nreturn offen.map(o => ({ json: { ...o.json, index_sha: antwort.sha } }));\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
200,
|
|
200
|
|
],
|
|
"id": "27ac6860-1b4d-4aef-b96c-02638881474d",
|
|
"name": "Tabelle auswerten"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"options": {
|
|
"caseSensitive": true,
|
|
"leftValue": "",
|
|
"typeValidation": "loose",
|
|
"version": 2
|
|
},
|
|
"conditions": [
|
|
{
|
|
"id": "5d2351d2-9aeb-48b9-b505-34bf9399d7ab",
|
|
"leftValue": "={{ $json.leer === true }}",
|
|
"rightValue": "",
|
|
"operator": {
|
|
"type": "boolean",
|
|
"operation": "true",
|
|
"singleValue": true
|
|
}
|
|
}
|
|
],
|
|
"combinator": "and"
|
|
},
|
|
"looseTypeValidation": true,
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 2.2,
|
|
"position": [
|
|
420,
|
|
200
|
|
],
|
|
"id": "a73f8011-23c7-4e03-8544-28d06f66c463",
|
|
"name": "Offene Artikel vorhanden?"
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"type": "n8n-nodes-base.noOp",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
640,
|
|
60
|
|
],
|
|
"id": "157f932d-c655-4374-b6df-0618b9591f63",
|
|
"name": "Nichts zu tun"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"batchSize": 1,
|
|
"options": {
|
|
"reset": false
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.splitInBatches",
|
|
"typeVersion": 3,
|
|
"position": [
|
|
640,
|
|
320
|
|
],
|
|
"id": "86fafde7-9cdb-48f0-a003-931e12db12ab",
|
|
"name": "Artikel nacheinander"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "={{ $('Konfiguration').first().json.nw_base }}/new-query",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"options": {
|
|
"response": {
|
|
"response": {
|
|
"neverError": false
|
|
}
|
|
},
|
|
"timeout": 60000
|
|
},
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ JSON.stringify({ project: $('Konfiguration').first().json.nw_project, keyword: $json.keyword, engine: $('Konfiguration').first().json.nw_engine, language: $('Konfiguration').first().json.nw_language }) }}",
|
|
"sendHeaders": true,
|
|
"specifyHeaders": "json",
|
|
"jsonHeaders": "={\"Content-Type\":\"application/json\"}"
|
|
},
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
900,
|
|
420
|
|
],
|
|
"id": "a697e29c-a103-4b9d-8eae-599a66ef29cb",
|
|
"name": "Analyse starten",
|
|
"credentials": {
|
|
"httpHeaderAuth": {
|
|
"id": "U23n2O980GKWocWq",
|
|
"name": "NeuronWriter API"
|
|
}
|
|
},
|
|
"onError": "continueErrorOutput",
|
|
"retryOnFail": true,
|
|
"maxTries": 3,
|
|
"waitBetweenTries": 3000
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst artikel = $('Artikel nacheinander').first().json;\nconst e = $input.first().json;\nreturn [{ json: {\n slug: artikel.slug, keyword: artikel.keyword, ergebnis: 'fehler',\n stufe: 'new-query',\n meldung: 'NeuronWriter /new-query fehlgeschlagen fuer Keyword \"' + artikel.keyword\n + '\". Haeufige Ursachen: Query-Kontingent erschoepft, falsche Projekt-ID, API-Key ungueltig. Antwort: '\n + JSON.stringify(e).slice(0, 500)\n}}];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
900,
|
|
640
|
|
],
|
|
"id": "4df6b64a-d30d-4723-aac7-f91a011b9c20",
|
|
"name": "Fehler Analyse starten",
|
|
"onError": "continueRegularOutput"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst artikel = $('Artikel nacheinander').first().json;\nconst neu = $input.first().json;\nif (!neu.query) {\n throw new Error('NeuronWriter lieferte kein Feld \"query\". Antwort: ' + JSON.stringify(neu).slice(0,400));\n}\nreturn [{ json: { ...artikel, query: neu.query, query_url: neu.query_url,\n share_url: neu.share_url, versuch: 0 } }];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1120,
|
|
420
|
|
],
|
|
"id": "8cca16df-9dcd-4597-841f-97a582a51b95",
|
|
"name": "Poll vorbereiten"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"amount": "={{ $('Konfiguration').first().json.poll_sekunden }}",
|
|
"unit": "seconds"
|
|
},
|
|
"type": "n8n-nodes-base.wait",
|
|
"typeVersion": 1.1,
|
|
"position": [
|
|
1340,
|
|
420
|
|
],
|
|
"id": "f9574347-0e39-418c-b944-d09862bb80c9",
|
|
"name": "Warten",
|
|
"webhookId": "b6229a99-62d1-42e0-8478-cdecca73f05c"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "={{ $('Konfiguration').first().json.nw_base }}/get-query",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"options": {
|
|
"response": {
|
|
"response": {
|
|
"neverError": false
|
|
}
|
|
},
|
|
"timeout": 60000
|
|
},
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ JSON.stringify({ query: $json.query }) }}",
|
|
"sendHeaders": true,
|
|
"specifyHeaders": "json",
|
|
"jsonHeaders": "={\"Content-Type\":\"application/json\"}"
|
|
},
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
1560,
|
|
420
|
|
],
|
|
"id": "42891afa-983e-4634-a59d-2beb65e57b7a",
|
|
"name": "Analyse abfragen",
|
|
"credentials": {
|
|
"httpHeaderAuth": {
|
|
"id": "U23n2O980GKWocWq",
|
|
"name": "NeuronWriter API"
|
|
}
|
|
},
|
|
"onError": "continueErrorOutput",
|
|
"retryOnFail": true,
|
|
"maxTries": 3,
|
|
"waitBetweenTries": 3000
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst a = $('Poll vorbereiten').first().json;\nreturn [{ json: { slug: a.slug, keyword: a.keyword, query: a.query, ergebnis: 'fehler',\n stufe: 'get-query',\n meldung: 'NeuronWriter /get-query fehlgeschlagen fuer query ' + a.query + '. Antwort: '\n + JSON.stringify($input.first().json).slice(0, 500) }}];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1560,
|
|
640
|
|
],
|
|
"id": "db41d8b6-9542-4201-b5cd-c8374bc40e6c",
|
|
"name": "Fehler Analyse abfragen",
|
|
"onError": "continueRegularOutput"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"options": {
|
|
"caseSensitive": true,
|
|
"leftValue": "",
|
|
"typeValidation": "loose",
|
|
"version": 2
|
|
},
|
|
"conditions": [
|
|
{
|
|
"id": "382e7432-7a07-4a83-b6c2-41aecc147b3c",
|
|
"leftValue": "={{ $json.status }}",
|
|
"rightValue": "ready",
|
|
"operator": {
|
|
"type": "string",
|
|
"operation": "equals"
|
|
}
|
|
}
|
|
],
|
|
"combinator": "and"
|
|
},
|
|
"looseTypeValidation": true,
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 2.2,
|
|
"position": [
|
|
1780,
|
|
420
|
|
],
|
|
"id": "01c6c412-0c34-40bd-a3a5-70437fa97662",
|
|
"name": "Analyse fertig?"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\n// Zaehler je Query in den Workflow-Daten. $runIndex zaehlt ueber alle Artikel\n// eines Laufs hinweg und taugt deshalb nicht als Zaehler pro Artikel.\nconst poll = $('Poll vorbereiten').first().json;\nconst antwort = $input.first().json;\nconst sd = $getWorkflowStaticData('global');\nsd.poll = sd.poll || {};\nsd.poll[poll.query] = (sd.poll[poll.query] || 0) + 1;\nconst versuch = sd.poll[poll.query];\nreturn [{ json: { ...poll, versuch, letzter_status: antwort.status || 'unbekannt' } }];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1780,
|
|
660
|
|
],
|
|
"id": "80e0be69-80e5-4127-a514-3bd7d0b6c047",
|
|
"name": "Versuch zaehlen"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"options": {
|
|
"caseSensitive": true,
|
|
"leftValue": "",
|
|
"typeValidation": "loose",
|
|
"version": 2
|
|
},
|
|
"conditions": [
|
|
{
|
|
"id": "8192b3f4-6ecb-4546-8403-d7152be847d7",
|
|
"leftValue": "={{ $json.versuch }}",
|
|
"rightValue": "={{ $('Konfiguration').first().json.poll_max }}",
|
|
"operator": {
|
|
"type": "number",
|
|
"operation": "gte"
|
|
}
|
|
}
|
|
],
|
|
"combinator": "and"
|
|
},
|
|
"looseTypeValidation": true,
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 2.2,
|
|
"position": [
|
|
2000,
|
|
660
|
|
],
|
|
"id": "d68208d2-b9c1-40ae-868e-c6160f3361c0",
|
|
"name": "Poll-Limit erreicht?"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst a = $input.first().json;\n{ const sd = $getWorkflowStaticData('global'); if (sd.poll) delete sd.poll[a.query]; }\nreturn [{ json: { slug: a.slug, keyword: a.keyword, query: a.query, ergebnis: 'fehler',\n stufe: 'poll-timeout',\n meldung: 'NeuronWriter-Analyse fuer \"' + a.keyword + '\" war nach ' + a.versuch\n + ' Versuchen noch nicht fertig (letzter Status: ' + a.letzter_status\n + '). Analyse laeuft ggf. weiter, query merken: ' + a.query }}];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
2220,
|
|
780
|
|
],
|
|
"id": "6c92837b-f313-44ab-871c-e5a930a13906",
|
|
"name": "Timeout melden"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\n// Feldnamen stammen aus einer echten /get-query-Antwort, siehe docs/feldnachweis.md\nconst a = $('Poll vorbereiten').first().json;\nconst n = $input.first().json;\n{ const sd = $getWorkflowStaticData('global'); if (sd.poll) delete sd.poll[a.query]; }\n\nconst liste = (arr) => (arr || []).map(x => ({\n begriff: x.t,\n min: Array.isArray(x.sugg_usage) ? x.sugg_usage[0] : null,\n max: Array.isArray(x.sugg_usage) ? x.sugg_usage[1] : null,\n bei_wettbewerbern_pc: x.usage_pc ?? null,\n}));\n\nconst fragen = [];\nconst gesehen = new Set();\nconst addFrage = (q, quelle, gewicht) => {\n if (!q) return;\n const k = q.trim().toLowerCase();\n if (gesehen.has(k)) return;\n gesehen.add(k);\n fragen.push({ frage: q.trim(), quelle, gewicht });\n};\nObject.entries((n.ideas && n.ideas.topic_matrix) || {})\n .sort((x, y) => (y[1].importance || 0) - (x[1].importance || 0))\n .forEach(([q, v]) => addFrage(q, 'topic_matrix', v.importance || null));\n((n.ideas || {}).people_also_ask || []).forEach(x => addFrage(x.q, 'people_also_ask', null));\n((n.ideas || {}).suggest_questions || []).forEach(x => addFrage(x.q, 'suggest_questions', null));\n((n.ideas || {}).content_questions || []).forEach(x => addFrage(x.q, 'content_questions', null));\n\nconst brief = {\n // --- die vom Auftrag geforderten Felder ---\n query_id: n.query,\n keyword: n.keyword,\n begriffe_pflicht: liste((n.terms || {}).content_basic),\n begriffe_erweitert: liste((n.terms || {}).content_extended),\n fragen,\n wortzahl_ziel: ((n.metrics || {}).word_count || {}).target ?? null,\n\n // --- Artikelkontext aus der Tabelle ---\n artikel: { slug: a.slug, titel: a.titel, kategorie: a.kategorie, cta_ziel: a.cta_ziel,\n praxis: Array.isArray(a.praxis) ? a.praxis : [] },\n\n // --- Zusatz fuer die Schreibvorlage ---\n zusatz: {\n wortzahl_median: ((n.metrics || {}).word_count || {}).median ?? null,\n lesbarkeit_ziel: ((n.metrics || {}).readability || {}).target ?? null,\n begriffe_titel: ((n.terms || {}).title || []).map(x => x.t),\n begriffe_description: ((n.terms || {}).desc || []).map(x => x.t),\n begriffe_h1: ((n.terms || {}).h1 || []).map(x => x.t),\n begriffe_h2: ((n.terms || {}).h2 || []).map(x => x.t),\n entitaeten: ((n.terms || {}).entities || []).slice(0, 15).map(x => ({ name: x.t, wichtigkeit: x.importance })),\n suchintention: (n.serp_summary || {}).top_intent ?? null,\n haeufigster_inhaltstyp: (n.serp_summary || {}).top_content_type ?? null,\n gliederungen_top5: (n.competitors || []).slice(0, 5).map(c => ({\n rang: c.rank, url: c.url, score: c.content_score, wortzahl: c.word_count,\n ueberschriften: (c.headers || []).map(h => `${h[0]}: ${h[1]}`).slice(0, 25),\n })),\n terms_txt_content_basic: ((n.terms_txt || {}).content_basic_w_ranges) ?? null,\n },\n\n schreibregeln: {\n preise: 'Preise niemals ausschreiben. Immer den Shortcode einsetzen, immer inklusive MwSt.: '\n + '[skrift_preis key=\"SCHLUESSEL\" ab=\"0|1\" brutto=\"1\"]. '\n + 'key ist der Produktschluessel (briefe, postkarten). ab=1 liefert den guenstigsten Staffelpreis, '\n + 'ab=0 den Standardpreis. brutto ist immer 1. Hinter dem Preis steht immer \"inkl. 19 % MwSt.\", '\n + 'nie \"netto\", \"brutto\" oder \"zzgl.\". Das Wort \"ab\" gehoert in den Fliesstext. Beispiel: '\n + 'Handschriftliche Briefe ab [skrift_preis key=\"briefe\" ab=\"1\" brutto=\"1\"] pro Stueck inkl. 19 % MwSt.',\n faq: 'FAQ nicht in content_html schreiben, sondern als Feld faq mit Frage-Antwort-Paaren. '\n + 'Die Ausgabe im Beitrag uebernimmt der Shortcode [skrift_faq].',\n kurzantwort: 'Ein Absatz, der die Hauptfrage direkt beantwortet, als eigenes Feld kurzantwort.',\n praxis: 'Der Artikel baut auf den Stichpunkten in artikel.praxis auf. Jeder Stichpunkt kommt '\n + 'erkennbar im Text vor, als Beispiel, Erfahrung oder klare Empfehlung. Ist die Liste leer, '\n + 'wird der Artikel nicht geschrieben, sondern zuerst Praxiswissen bei Lucas erfragt.',\n begriffe: 'begriffe_pflicht sind verbindlich. begriffe_erweitert nur verwenden, wenn der Satz '\n + 'dadurch nicht schlechter wird. Keine Saetze, die nur fuer den NeuronWriter-Score da sind. '\n + 'Keine Wettbewerbernamen. Zielwert im Import ist 65.',\n links: 'Interne Links primaer auf Business-Leistungsseiten: handgeschriebene-businessbriefe, '\n + 'handgeschriebene-postkarten, unterschriftenservice, automatisierte-follow-ups. '\n + 'artikel.cta_ziel mindestens einmal im Fliesstext verlinken, mindestens zwei Business-Links insgesamt. '\n + 'papier-schriftmuster nur ergaenzend. Keine Links auf Privatkunden-Seiten, review, agb, datenschutz, '\n + 'impressum, zahlungsmethoden, lieferung-versand.',\n querverweise: 'Mindestens zwei, hoechstens vier Querverweise auf verwandte Ratgeberartikel, immer als '\n + '[ratgeber_link slug=\"SLUG\"]Ankertext[/ratgeber_link], nie als harter Link. Slugs aus artikel-index.json. '\n + 'Der Shortcode verlinkt erst, wenn der Zielartikel veroeffentlicht ist. Ankertext beschreibt das Ziel, '\n + 'nie \"hier\" oder \"mehr dazu\".',\n bausteine: 'Kein Block \"Auch fuer Privatpersonen.\" und kein Abschnitt \"Kostenloses Handschriftmuster '\n + 'anfordern.\" im Artikeltext, beides liefert das Seitenlayout. Der Artikel endet mit dem letzten '\n + 'inhaltlichen Abschnitt, nie mit einer Zusammenfassung.',\n faq_ueberschrift: 'Eigene FAQ-Ueberschrift als Feld faq_ueberschrift, konkret zum Thema, z. B. '\n + '\"Fragen zu den Kosten\". Satzfall, ohne Punkt am Ende.',\n stil: 'Kurze und lange Saetze mischen. Absaetze unterschiedlich lang. Keine Formeln wie '\n + '\"Genau das\", \"Der Grund ist\", \"nicht nur, sondern auch\", \"entscheidend ist\", '\n + '\"der groesste Hebel\", \"macht den Unterschied\". Keine Aufzaehlung mit erstens, zweitens. '\n + 'Keine rhetorische Frage mit Sofortantwort. Keine Behauptung ohne Beleg, also kein '\n + '\"erfahrungsgemaess\" oder \"in aller Regel\". Wo es passt, auch abraten: wann sich '\n + 'Handschrift nicht lohnt.',\n },\n\n meta: {\n erzeugt_am: new Date().toISOString(),\n analyse_url: n.query_url || a.query_url || null,\n freigabe_url: n.share_url || a.share_url || null,\n sprache: n.language, suchmaschine: n.engine, projekt: n.project,\n },\n};\n\nreturn [{ json: { slug: a.slug, zeilen_index: a.zeilen_index, query: n.query,\n keyword: n.keyword, brief } }];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
2220,
|
|
300
|
|
],
|
|
"id": "fdb0ddb4-5218-4598-9b74-dcc2f84499f1",
|
|
"name": "Brief bauen"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "GET",
|
|
"url": "={{ $('Konfiguration').first().json.gitea_base }}/api/v1/repos/{{ $('Konfiguration').first().json.gitea_owner }}/{{ $('Konfiguration').first().json.gitea_repo }}/contents/{{ $('Konfiguration').first().json.brief_ordner }}/brief-{{ $json.slug }}.json?ref={{ $('Konfiguration').first().json.branch }}",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"options": {
|
|
"response": {
|
|
"response": {
|
|
"neverError": true,
|
|
"fullResponse": true
|
|
}
|
|
},
|
|
"timeout": 60000
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
2440,
|
|
300
|
|
],
|
|
"id": "b0bafe2a-60ab-47fb-a006-6115edaf4256",
|
|
"name": "Brief vorhanden?",
|
|
"credentials": {
|
|
"httpHeaderAuth": {
|
|
"id": "VOD4JM5zwpSC8wAr",
|
|
"name": "Gitea Skrift Auto Article"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst b = $('Brief bauen').first().json;\nconst p = $input.first().json;\n// n8n liefert den Koerper bei fullResponse je nach Version als body oder data.\nconst K = (r) => (r && r.body !== undefined) ? r.body : ((r || {}).data);\nconst kp = K(p);\nconst vorhanden = p.statusCode === 200 && kp && kp.sha;\n\nconst inhalt = Buffer.from(JSON.stringify(b.brief, null, 2), 'utf8').toString('base64');\nconst konf = $('Konfiguration').first().json;\n\nreturn [{ json: {\n ...b,\n methode: vorhanden ? 'PUT' : 'POST',\n pfad: `${konf.brief_ordner}/brief-${b.slug}.json`,\n commit_body: JSON.stringify({\n content: inhalt,\n message: `Brief ${vorhanden ? 'aktualisiert' : 'erzeugt'}: ${b.slug} (${b.keyword})`,\n branch: konf.branch,\n ...(vorhanden ? { sha: kp.sha } : {}),\n }),\n}}];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
2660,
|
|
300
|
|
],
|
|
"id": "4a67bbcf-ce4f-4b76-b4f4-4ba6c8236b10",
|
|
"name": "Commit vorbereiten"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "={{ $json.methode }}",
|
|
"url": "={{ $('Konfiguration').first().json.gitea_base }}/api/v1/repos/{{ $('Konfiguration').first().json.gitea_owner }}/{{ $('Konfiguration').first().json.gitea_repo }}/contents/{{ $json.pfad }}",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"options": {
|
|
"response": {
|
|
"response": {
|
|
"neverError": false
|
|
}
|
|
},
|
|
"timeout": 60000
|
|
},
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ $json.commit_body }}",
|
|
"sendHeaders": true,
|
|
"specifyHeaders": "json",
|
|
"jsonHeaders": "={\"Content-Type\":\"application/json\"}"
|
|
},
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
2880,
|
|
300
|
|
],
|
|
"id": "a60a0aac-449d-4990-872d-c2a848ebcd08",
|
|
"name": "Brief committen",
|
|
"credentials": {
|
|
"httpHeaderAuth": {
|
|
"id": "VOD4JM5zwpSC8wAr",
|
|
"name": "Gitea Skrift Auto Article"
|
|
}
|
|
},
|
|
"onError": "continueErrorOutput",
|
|
"retryOnFail": true,
|
|
"maxTries": 3,
|
|
"waitBetweenTries": 3000
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst b = $('Brief bauen').first().json;\nreturn [{ json: { slug: b.slug, keyword: b.keyword, query: b.query, ergebnis: 'fehler',\n stufe: 'gitea-commit',\n meldung: 'Brief konnte nicht ins Repo geschrieben werden. Haeufigste Ursache: Gitea-Token ohne '\n + 'Scope write:repository. Antwort: ' + JSON.stringify($input.first().json).slice(0, 500) }}];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
2880,
|
|
520
|
|
],
|
|
"id": "1dda0054-24af-465d-bd47-8f5693968c80",
|
|
"name": "Fehler Brief committen",
|
|
"onError": "continueRegularOutput"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst b = $('Brief bauen').first().json;\nreturn [{ json: {\n slug: b.slug, keyword: b.keyword, query: b.query, zeilen_index: b.zeilen_index,\n ergebnis: 'ok', neuer_status: 'brief_bereit',\n pfad: $('Commit vorbereiten').first().json.pfad,\n wortzahl_ziel: b.brief.wortzahl_ziel,\n anzahl_pflichtbegriffe: b.brief.begriffe_pflicht.length,\n anzahl_fragen: b.brief.fragen.length,\n analyse_url: b.brief.meta.analyse_url,\n}}];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
3100,
|
|
300
|
|
],
|
|
"id": "e8741dc7-728d-4409-97f4-1fa91f219b2c",
|
|
"name": "Erfolg merken"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"amount": "={{ $('Konfiguration').first().json.pause_zwischen_artikeln }}",
|
|
"unit": "seconds"
|
|
},
|
|
"type": "n8n-nodes-base.wait",
|
|
"typeVersion": 1.1,
|
|
"position": [
|
|
3320,
|
|
400
|
|
],
|
|
"id": "cea1c3e2-f571-4c9f-8753-ab3c10d9a348",
|
|
"name": "Pause Rate Limit",
|
|
"webhookId": "ef9b2ac6-fb6a-4727-99f9-173c3c8af25f"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst alle = $input.all().map(i => i.json);\nconst tabelle = $('Tabelle auswerten').first().json.tabelle_gesamt\n || $getWorkflowStaticData('global').lauf.tabelle_gesamt;\nconst index_sha = $('Artikeltabelle lesen').first().json.sha;\n\nconst kopie = JSON.parse(JSON.stringify(tabelle));\nlet geaendert = 0;\nalle.filter(r => r.ergebnis === 'ok').forEach(r => {\n const i = kopie.findIndex(z => z.slug === r.slug);\n if (i >= 0) { kopie[i].status = 'brief_bereit'; kopie[i].query_id = r.query; geaendert++; }\n});\n\nconst ok = alle.filter(r => r.ergebnis === 'ok');\nconst fehler = alle.filter(r => r.ergebnis === 'fehler');\n\nreturn [{ json: {\n index_sha, geaendert,\n neue_tabelle: JSON.stringify(kopie, null, 2),\n ok, fehler,\n anzahl_ok: ok.length, anzahl_fehler: fehler.length,\n}}];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
900,
|
|
140
|
|
],
|
|
"id": "40489909-6d34-488c-acff-c22d3cce020d",
|
|
"name": "Ergebnisse sammeln"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst s = $input.first().json;\nconst konf = $('Konfiguration').first().json;\nreturn [{ json: { ...s, commit_body: JSON.stringify({\n content: Buffer.from(s.neue_tabelle, 'utf8').toString('base64'),\n message: `Status auf brief_bereit gesetzt (${s.geaendert} Artikel)`,\n branch: konf.branch,\n sha: s.index_sha,\n})}}];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1120,
|
|
140
|
|
],
|
|
"id": "b2acfa6d-d78a-4d92-937e-af3c5ce44d10",
|
|
"name": "Statusupdate vorbereiten"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "PUT",
|
|
"url": "={{ $('Konfiguration').first().json.gitea_base }}/api/v1/repos/{{ $('Konfiguration').first().json.gitea_owner }}/{{ $('Konfiguration').first().json.gitea_repo }}/contents/{{ $('Konfiguration').first().json.index_pfad }}",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"options": {
|
|
"response": {
|
|
"response": {
|
|
"neverError": false
|
|
}
|
|
},
|
|
"timeout": 60000
|
|
},
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ $json.commit_body }}",
|
|
"sendHeaders": true,
|
|
"specifyHeaders": "json",
|
|
"jsonHeaders": "={\"Content-Type\":\"application/json\"}"
|
|
},
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
1340,
|
|
140
|
|
],
|
|
"id": "fcb0a473-d7c5-477b-aecb-4a60341b3c5e",
|
|
"name": "Status zurueckschreiben",
|
|
"credentials": {
|
|
"httpHeaderAuth": {
|
|
"id": "VOD4JM5zwpSC8wAr",
|
|
"name": "Gitea Skrift Auto Article"
|
|
}
|
|
},
|
|
"onError": "continueErrorOutput",
|
|
"retryOnFail": true,
|
|
"maxTries": 3,
|
|
"waitBetweenTries": 3000
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nthrow new Error('Status konnte nicht zurueckgeschrieben werden. Die Briefe sind erzeugt, aber die '\n + 'Artikeltabelle steht noch auf \"offen\". Vor dem naechsten Lauf pruefen, sonst werden Analysen '\n + 'doppelt erzeugt. Antwort: ' + JSON.stringify($input.first().json).slice(0, 500));\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1340,
|
|
-60
|
|
],
|
|
"id": "030a3ede-19b7-4b85-a582-f17d5ccfd316",
|
|
"name": "Fehler Statusupdate"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"jsCode": "\nconst s = $('Ergebnisse sammeln').first().json;\nconst z = [];\nz.push(`Briefe vorbereitet: ${s.anzahl_ok}, Fehler: ${s.anzahl_fehler}`);\nz.push('');\nif (s.ok.length) {\n z.push('Fertig:');\n s.ok.forEach(r => z.push(\n ` ${r.slug} | Zielwortzahl ${r.wortzahl_ziel} | ${r.anzahl_pflichtbegriffe} Pflichtbegriffe, `\n + `${r.anzahl_fragen} Fragen\\n Datei: ${r.pfad}\\n Analyse: ${r.analyse_url}`));\n z.push('');\n}\nif (s.fehler.length) {\n z.push('Fehler:');\n s.fehler.forEach(r => z.push(` ${r.slug || '?'} [${r.stufe}]: ${r.meldung}`));\n z.push('');\n}\nz.push('Naechster Schritt: git pull, dann die Briefe in Cowork als Schreibvorlage nutzen.');\nreturn [{ json: {\n betreff: `Skrift Ratgeber: ${s.anzahl_ok} Brief(e) bereit` + (s.anzahl_fehler ? `, ${s.anzahl_fehler} Fehler` : ''),\n text: z.join('\\n'),\n}}];\n"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1560,
|
|
140
|
|
],
|
|
"id": "ba124436-2af4-4873-b5b3-7e206c34a598",
|
|
"name": "Meldung formulieren"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"fromEmail": "",
|
|
"toEmail": "={{ $('Konfiguration').first().json.benachrichtigung_an }}",
|
|
"subject": "={{ $json.betreff }}",
|
|
"emailFormat": "text",
|
|
"text": "={{ $json.text }}",
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.emailSend",
|
|
"typeVersion": 2.1,
|
|
"position": [
|
|
1780,
|
|
140
|
|
],
|
|
"id": "99f630b2-451c-4db8-b10b-47e58dd5b69d",
|
|
"name": "Benachrichtigung",
|
|
"disabled": true,
|
|
"notes": "SMTP-Credential zuweisen, Absender eintragen, dann Node aktivieren."
|
|
}
|
|
],
|
|
"connections": {
|
|
"Manuell starten": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Konfiguration",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Zeitplan Montag 07:00": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Konfiguration",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Webhook Start": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Konfiguration",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Konfiguration": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Artikeltabelle lesen",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Artikeltabelle lesen": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Tabelle auswerten",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Fehler Artikeltabelle",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Tabelle auswerten": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Offene Artikel vorhanden?",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Offene Artikel vorhanden?": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Nichts zu tun",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Artikel nacheinander",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Artikel nacheinander": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Ergebnisse sammeln",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Analyse starten",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Analyse starten": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Poll vorbereiten",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Fehler Analyse starten",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Poll vorbereiten": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Warten",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Warten": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Analyse abfragen",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Analyse abfragen": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Analyse fertig?",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Fehler Analyse abfragen",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Analyse fertig?": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Brief bauen",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Versuch zaehlen",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Versuch zaehlen": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Poll-Limit erreicht?",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Poll-Limit erreicht?": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Timeout melden",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Warten",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Brief bauen": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Brief vorhanden?",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Brief vorhanden?": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Commit vorbereiten",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Commit vorbereiten": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Brief committen",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Brief committen": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Erfolg merken",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Fehler Brief committen",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Erfolg merken": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Pause Rate Limit",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Fehler Brief committen": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Pause Rate Limit",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Fehler Analyse starten": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Pause Rate Limit",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Fehler Analyse abfragen": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Pause Rate Limit",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Timeout melden": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Pause Rate Limit",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Pause Rate Limit": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Artikel nacheinander",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Ergebnisse sammeln": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Statusupdate vorbereiten",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Statusupdate vorbereiten": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Status zurueckschreiben",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Status zurueckschreiben": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Meldung formulieren",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Fehler Statusupdate",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Meldung formulieren": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Benachrichtigung",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
},
|
|
"settings": {
|
|
"executionOrder": "v1",
|
|
"saveManualExecutions": true,
|
|
"callerPolicy": "workflowsFromSameOwner"
|
|
}
|
|
} |