From 6eadb7342bcb1f8c6250d630fee310ea46dea565 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Fri, 19 Jun 2026 13:04:27 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20Frontpage-Text=20gek=C3=BCrzt=20(erster?= =?UTF-8?q?=20Satz/80=20Zeichen)=20+=20Triage-Timing=206min=20+=20SQLite-F?= =?UTF-8?q?ix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Frontpage: Nur erster Satz pro Karte (max 80 Zeichen) - Triage: 6 Min Verzögerung nach letzter Nachricht (Thread-Window) - _run_triage_async: Direkt-SQLite statt get_db() (kein Flask-Context nötig) --- app.py | 64 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/app.py b/app.py index e842da8..0054143 100644 --- a/app.py +++ b/app.py @@ -473,44 +473,69 @@ def triage_submission(db, submission_id: int) -> dict: def _run_triage_async(submission_id: int): - """Führt die Triage in einem separaten Thread aus (nicht blockierend für Webhooks).""" + """Führt die Triage VERZÖGERT aus — wartet 6 Minuten (Thread-Window + Puffer). + + Das stellt sicher, dass Foto + Sprachnachricht + Text alle im selben + Thread landen, BEVOR die KI den Inhalt bewertet. + """ import time as _time - _time.sleep(0.3) - - db = get_db() + import sqlite3 as _sqlite3 + + THREAD_WINDOW_SEC = 360 # 6 Minuten (5 Min Thread-Window + 1 Min Puffer) + + print(f"[triage] #{submission_id} geplant in {THREAD_WINDOW_SEC}s", file=sys.stderr) + _time.sleep(THREAD_WINDOW_SEC) + + # Direkter SQLite-Connection (ohne Flask-Context, da im Hintergrund-Thread) + conn = _sqlite3.connect(DB_PATH) + conn.row_factory = _sqlite3.Row try: - result = triage_submission(db, submission_id) - + # Prüfen ob der Eintrag inzwischen gelöscht oder schon triagiert wurde + row = conn.execute( + "SELECT triage_tier, deleted_at FROM submissions WHERE id=?", + (submission_id,) + ).fetchone() + if not row or row["deleted_at"]: + print(f"[triage] #{submission_id} übersprungen (gelöscht)", file=sys.stderr) + return + if row["triage_tier"] is not None: + print(f"[triage] #{submission_id} übersprungen (schon triagiert)", file=sys.stderr) + return + + result = triage_submission(conn, submission_id) + # Auto-Antwort senden if result.get("auto_response"): - row = db.execute( + row2 = conn.execute( "SELECT channel, sender_id FROM submissions WHERE id=?", (submission_id,) ).fetchone() - if row: - if row["channel"] == "whatsapp" and META_TOKEN: + if row2: + if row2["channel"] == "whatsapp" and META_TOKEN: try: - send_whatsapp_message(row["sender_id"], result["auto_response"]) + send_whatsapp_message(row2["sender_id"], result["auto_response"]) except Exception as e: print(f"[triage] WhatsApp reply failed: {e}", file=sys.stderr) - elif row["channel"] == "telegram" and TELEGRAM_TOKEN: + elif row2["channel"] == "telegram" and TELEGRAM_TOKEN: try: requests.post( f"{TELEGRAM_API}/sendMessage", - json={"chat_id": int(row["sender_id"]), + json={"chat_id": int(row2["sender_id"]), "text": result["auto_response"]}, timeout=10, ) except Exception as e: print(f"[triage] Telegram reply failed: {e}", file=sys.stderr) - - db.execute( + + conn.execute( "UPDATE submissions SET auto_response_sent=1 WHERE id=?", (submission_id,) ) - db.commit() + conn.commit() except Exception as e: print(f"[triage] Async triage failed for {submission_id}: {e}", file=sys.stderr) + finally: + conn.close() @app.teardown_appcontext @@ -2345,8 +2370,13 @@ def public_frontend(): name = "Anonym" summary_text = (r["display_text"] or r["summary"] or r["content"] or "") - # Truncate for card preview - preview = summary_text[:200] + ("..." if len(summary_text) > 200 else "") + # Kurzer Teaser: ersten Satz oder max 80 Zeichen + first_sentence = summary_text.split(".")[0].strip() + if len(first_sentence) > 80: + first_sentence = summary_text[:77] + "..." + elif len(summary_text) > len(first_sentence) + 3: + first_sentence += "." + preview = first_sentence date_str = (r["published_at"] or r["created_at"] or "") # Format with relative + absolute time time_html = ""