diff --git a/README.md b/README.md index f47cbf3..3906dea 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,14 @@ Die Workflow-Dateien bleiben unveraendert. Mit `read:repository` allein scheitert jeder Schreibvorgang mit HTTP 403 und der Meldung `token does not have at least one of required scope(s)`. +**Gitea-Adresse:** beide Workflows sprechen Gitea als `http://gitea:3000` an, +also ueber das Docker-Netz, nicht ueber `https://gitea.lucas-orth.de`. +Grund: der oeffentliche Hostname loest auf die NetBird-Adresse `100.98.99.19` +auf, die der n8n-Host nur auf Port 80 erreicht, nicht auf 443. +Details in `docs/testlauf.md`. Der Docker-Weg ist ausserdem schneller und +unabhaengig vom Reverse Proxy. Aendern laesst sich das im Node **Konfiguration**, +Feld `gitea_base`. + **WordPress-Benutzer:** eigener Benutzer mit Rolle Redakteur, kein Administrator. Die Rolle Redakteur darf technisch auch veroeffentlichen. Der Workflow setzt `status: draft` hart und bricht ab, falls WordPress etwas anderes zurueckmeldet. @@ -173,6 +181,40 @@ der Workflow fuer diesen Artikel ab. Fehlt `stand_datum`, setzt der Workflow das heutige Datum. Fehlt `seo_titel`, wird `titel` verwendet. +### Schreibregeln fuer content_html + +**Preise niemals ausschreiben.** Sie werden zentral gepflegt und per Shortcode +eingesetzt: + +``` +[skrift_preis key="SCHLUESSEL" ab="0|1" brutto="0|1"] +``` + +| Parameter | Bedeutung | +|---|---| +| `key` | Produkt- oder Positionsschluessel, z. B. `briefe`, `postkarten`, `porto_inland` | +| `ab=1` | guenstigster Staffelpreis; `ab=0` der Standardpreis | +| `brutto=1` | inkl. MwSt.; `brutto=0` netto | + +Das Wort "ab" gehoert in den Fliesstext, der Shortcode liefert nur die Zahl: + +``` +Handschriftliche Briefe ab [skrift_preis key="briefe" ab="1"] pro Stueck. +``` + +Ein unbekannter `key` erzeugt eine leere Ausgabe, keinen Fehler. + +Workflow 2 durchsucht `content_html` nach ausgeschriebenen Betraegen +(`2,56 EUR`, `0,95 €`) und meldet jeden Treffer in der Benachrichtigung. +Der Import wird deswegen nicht abgebrochen, der Beitrag ist ja ein Entwurf. + +**FAQ nicht in content_html schreiben.** Sie gehoeren in das Feld `faq` und +werden im Beitrag ueber `[skrift_faq]` ausgegeben. Dasselbe gilt fuer die +Kurzantwort, die als eigenes Feld `kurzantwort` transportiert wird. + +Workflow 1 legt diese Regeln als Block `schreibregeln` in jeden Brief, damit +sie beim Schreiben direkt vorliegen. + ### Ablauf 1. Ordner `artikel/` auflisten, alle `artikel-*.json` einsammeln @@ -188,7 +230,7 @@ Fehlt `seo_titel`, wird `titel` verwendet. - Kategorie suchen, bei Bedarf anlegen - Beitrag anlegen oder aktualisieren, immer `status: draft` - Meta-Felder und SEOPress-Felder im selben Request - - Cache leeren + - Cache leeren (siehe Hinweis unten) - Zeile in `status-importe.json` 6. Benachrichtigung mit Vorschaulinks @@ -196,6 +238,16 @@ Fehlt `seo_titel`, wird `titel` verwendet. Im Node **Konfiguration**, Feld `score_ziel`. Standard ist 72. Der Wert gilt fuer alle Artikel eines Laufs. + +Fuer einen einzelnen Lauf laesst er sich ueber den Webhook uebersteuern, +ohne den Workflow zu aendern: + +```bash +curl -X POST https://n8n.lucas-orth.de/webhook/pruefen-und-importieren \ + -H "Content-Type: application/json" -d '{"score_ziel":60}' +``` + +Ohne Angabe bleibt es bei 72. Alle anderen Stellschrauben liegen im selben Node: Basis-URLs, Ordnernamen, Pause zwischen Artikeln, Empfaengeradresse. @@ -246,6 +298,18 @@ Analysen doppelt erzeugt und Kontingent verbraucht. HTTP-Nodes wiederholen bei technischen Fehlern dreimal mit drei Sekunden Abstand. Zwischen zwei Artikeln liegt eine Pause von fuenf Sekunden. +**Cache leeren gibt HTTP 403.** Der Redakteur-Benutzer darf +`POST /wp-json/seopress/v1/commands/clear-cache` nicht aufrufen. Das ist +protokolliert und bewusst kein Abbruchgrund: der importierte Beitrag ist ein +Entwurf, ein Cache-Purge waere wirkungslos. Relevant wird es erst beim +Aktualisieren eines bereits veroeffentlichten Beitrags. + +**Achtung bei haengenden Zielen.** Der `timeout` eines HTTP-Nodes greift erst +nach dem Verbindungsaufbau. Ein Ziel, das SYN-Pakete verschluckt statt sie +abzulehnen, laesst den Node unbegrenzt stehen, der Fehlerpfad feuert nie und die +Execution blockiert. Dagegen hilft nur `EXECUTIONS_TIMEOUT` in der +n8n-Umgebung. + --- ## 5. Aufbau des Repos @@ -256,7 +320,7 @@ artikel/ fertige Artikel aus Cowork briefe/ NeuronWriter-Briefe aus Workflow 1 nachbessern/ Berichte zu Artikeln unter Zielwert status-importe.json was wann als Entwurf nach WordPress ging -workflows/ die beiden importfertigen n8n-Dateien +workflows/ die importfertigen n8n-Dateien, dazu netzcheck build/ Generatorskripte, die die Workflow-JSONs erzeugen wordpress/ Mu-Plugin fuer die Meta-Felder docs/ Feldnachweis und Rohbelege der API-Antworten @@ -278,8 +342,26 @@ anschliessend wieder nach `workflows/` und laesst die Generatoren liegen. --- -## 6. Belege +## 6. Hilfsworkflow netzcheck + +In n8n liegt `netzcheck (Hilfswerkzeug)`. Er fragt aus n8n heraus eine beliebige +URL ab und meldet Statuscode, Groesse und Fehlercode zurueck. Nuetzlich, wenn +ein Ziel aus n8n nicht erreichbar scheint: + +```bash +curl -X POST https://n8n.lucas-orth.de/webhook/probe \ + -H "Content-Type: application/json" \ + -d '{"url":"http://gitea:3000/api/v1/version"}' +``` + +--- + +## 7. Belege `docs/feldnachweis.md` listet jede Stelle, an der ein Feldname aus einer echten API-Antwort ermittelt wurde, mit Beispielantwort. Die Rohantworten liegen als `docs/beleg-*.json` daneben. + +`docs/testlauf.md` protokolliert den Testlauf vom 20.09.2026 gegen die echten +Systeme, inklusive der beiden Fehler, die er gefunden hat, und des +Netzwerkbefunds zu Gitea.