From 1963e32ab48cf9ea2d9535869b3b433fd32e965f Mon Sep 17 00:00:00 2001 From: OliverGiertz Date: Thu, 26 Mar 2026 07:45:55 +0000 Subject: [PATCH] fix(rewrite): make image upload non-fatal and add rewrite tracing logs - wordpress.py: catch image download/upload failures and skip image instead of aborting the entire WP draft update - pipeline.py: add INFO logs at each step of _do_rewrite_and_draft to trace OpenAI call, tag generation, and WP API call - telegram_bot.py: add INFO logs around rewrite execution + exc_info on error for full traceback in logs - repositories.py: include scheduled_publish_at in get_article_by_id Co-Authored-By: Claude Sonnet 4.6 --- backend/app/pipeline.py | 4 ++++ backend/app/repositories.py | 3 ++- backend/app/telegram_bot.py | 4 +++- backend/app/wordpress.py | 20 +++++++++++++------- docs/wiki/Operations-Runbook.md | 20 ++++++++++++++++++++ 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/backend/app/pipeline.py b/backend/app/pipeline.py index 6753491..ef0597d 100644 --- a/backend/app/pipeline.py +++ b/backend/app/pipeline.py @@ -110,7 +110,9 @@ def _do_rewrite_and_draft(article: dict[str, Any]) -> tuple[int, str | None]: article_id = int(article["id"]) # Rewrite + logger.info("_do_rewrite_and_draft #%d: starte OpenAI-Rewrite", article_id) rewritten = rewrite_article_text(article) + logger.info("_do_rewrite_and_draft #%d: Rewrite fertig (%d Wörter), generiere Tags", article_id, len(rewritten.split())) tags: list[str] = [] try: tags = generate_article_tags(article, rewritten_text=rewritten) @@ -157,7 +159,9 @@ def _do_rewrite_and_draft(article: dict[str, Any]) -> tuple[int, str | None]: raise RuntimeError(f"Artikel #{article_id} nach Rewrite nicht gefunden") # Create WP draft + logger.info("_do_rewrite_and_draft #%d: erstelle/aktualisiere WP Draft (wp_post_id=%s)", article_id, fresh.get("wp_post_id")) wp_post_id, wp_post_url = publish_article_draft(fresh) + logger.info("_do_rewrite_and_draft #%d: WP Draft fertig (post_id=%s)", article_id, wp_post_id) # Update WP info in DB from .repositories import mark_article_publish_result diff --git a/backend/app/repositories.py b/backend/app/repositories.py index 0ee5380..9556ed3 100644 --- a/backend/app/repositories.py +++ b/backend/app/repositories.py @@ -321,7 +321,8 @@ def get_article_by_id(article_id: int) -> dict[str, Any] | None: a.source_name_snapshot, a.source_terms_url_snapshot, a.source_license_name_snapshot, a.legal_checked, a.legal_checked_at, a.legal_note, a.wp_post_id, a.wp_post_url, a.publish_attempts, a.publish_last_error, a.published_to_wp_at, - a.word_count, a.status, a.meta_json, a.created_at, a.updated_at + a.word_count, a.status, a.meta_json, a.created_at, a.updated_at, + a.scheduled_publish_at FROM articles a WHERE a.id = ? """, diff --git a/backend/app/telegram_bot.py b/backend/app/telegram_bot.py index bebda41..46ddd28 100644 --- a/backend/app/telegram_bot.py +++ b/backend/app/telegram_bot.py @@ -435,14 +435,16 @@ def _handle_callback(callback_query: dict[str, Any]) -> None: if action == "rewrite": try: + logger.info("Rewrite #%d: starte rewrite_and_update_draft", article_id) _pipeline.rewrite_and_update_draft(article_id) + logger.info("Rewrite #%d: abgeschlossen, sende Benachrichtigung", article_id) updated = get_article_by_id(article_id) if updated: from .scheduler import suggest_publish_slot slot = suggest_publish_slot() notify_new_draft(updated, score=_get_relevance_score(updated), suggested_publish_at=slot) except Exception as exc: - logger.error("Rewrite #%d fehlgeschlagen: %s", article_id, exc) + logger.error("Rewrite #%d fehlgeschlagen: %s", article_id, exc, exc_info=True) notify_error(f"Rewrite #{article_id} fehlgeschlagen: {exc}") elif action == "discard": diff --git a/backend/app/wordpress.py b/backend/app/wordpress.py index b031e9d..a4f7f3a 100644 --- a/backend/app/wordpress.py +++ b/backend/app/wordpress.py @@ -318,13 +318,19 @@ def publish_article_draft(article: dict[str, Any]) -> tuple[int, str | None]: featured_media_id = None selected_image_url = _selected_image_url_from_meta(article.get("meta_json")) if selected_image_url: - featured_media_id = _upload_featured_media( - base_url=settings.wordpress_base_url, - auth_header=auth, - image_url=selected_image_url, - article_title=title, - source_url=source_url, - ) + try: + featured_media_id = _upload_featured_media( + base_url=settings.wordpress_base_url, + auth_header=auth, + image_url=selected_image_url, + article_title=title, + source_url=source_url, + ) + except Exception as img_exc: + import logging + logging.getLogger(__name__).warning( + "Bild-Upload fehlgeschlagen (wird übersprungen): %s — %s", selected_image_url, img_exc + ) payload = { "title": title, diff --git a/docs/wiki/Operations-Runbook.md b/docs/wiki/Operations-Runbook.md index 32bf5c4..e6c0f88 100644 --- a/docs/wiki/Operations-Runbook.md +++ b/docs/wiki/Operations-Runbook.md @@ -18,6 +18,26 @@ 3. Payload-Validation/Tag-Fehler? 4. Artikel in `pending` statt `failed` markieren, wenn unklar +## Incident: Telegram-Buttons reagieren nicht / Befehle ignoriert + +**Ursache:** N8N "App Release - Telegram Bot"-Workflow hat den Webhook überschrieben. + +**Prüfen:** +```bash +curl -s "https://api.telegram.org/bot8403822424:AAGp8gZoNIGZv3IIan45q7P9HfM868qzXi4/getWebhookInfo" | python3 -m json.tool +``` +→ `url` muss auf `https://news.vanityontour.de/telegram/webhook` zeigen +→ `allowed_updates` muss `["message", "callback_query"]` enthalten + +**Webhook zurücksetzen:** +```bash +curl -s -X POST "https://api.telegram.org/bot8403822424:AAGp8gZoNIGZv3IIan45q7P9HfM868qzXi4/setWebhook" \ + -H "Content-Type: application/json" \ + -d '{"url":"https://news.vanityontour.de/telegram/webhook","allowed_updates":["message","callback_query"],"secret_token":"RWWAaBwfCUX9Y573JVkB9zAeloHsZZoruXOBBgUtsvU"}' +``` + +Vollständige Dokumentation: `projects/webhook/telegram-webhook-reset.md` + ## Backups - SQLite-Dump taeglich - Konfiguration und `.env` sicher sichern