from flask import Blueprint, render_template, jsonify, request, redirect, url_for from ..db import query, query_one, execute, get_all_sessions from ..chroma import upsert_lore_enriched, CHROMA_COL_OUT bp = Blueprint("lore", __name__) def _get_proposals(faction: str = "", status: str = "pending") -> list: sql = "SELECT * FROM lore_proposals WHERE 1=1" params = [] if faction: sql += " AND faction_slug = %s" params.append(faction) if status: sql += " AND status = %s" params.append(status) sql += " ORDER BY id DESC LIMIT 100" return query(sql, params or None) def _get_stats() -> dict: rows = query("SELECT status, COUNT(*) as n FROM lore_proposals GROUP BY status") m = {r["status"]: r["n"] for r in rows} return {"pending": m.get("pending", 0), "accepted": m.get("accepted", 0), "rejected": m.get("rejected", 0), "modified": m.get("modified", 0)} def _get_factions() -> list: rows = query("SELECT DISTINCT faction_slug FROM lore_proposals ORDER BY faction_slug") return [r["faction_slug"] for r in rows] @bp.route("/lore") def lore(): all_sessions = get_all_sessions() sid = int(request.args.get("sid", all_sessions[-1]["id"] if all_sessions else 1)) session = query_one("SELECT * FROM sessions WHERE id = %s", (sid,)) filt_faction = request.args.get("faction", "") filt_status = request.args.get("status", "pending") proposals = _get_proposals(filt_faction, filt_status) flash_msg = request.args.get("msg") flash_ok = request.args.get("ok", "1") == "1" # Threads de discussion threads_raw = query("SELECT * FROM lore_proposal_threads ORDER BY created_at ASC") if proposals else [] proposal_threads = {} for row in (threads_raw or []): pid = row["proposal_id"] proposal_threads.setdefault(pid, []).append(row) return render_template("lore.html", tab="lore", current_sid=sid, all_sessions=all_sessions, session=session, proposals=proposals, lore_stats=_get_stats(), all_factions=_get_factions(), filt_faction=filt_faction, filt_status=filt_status, proposal_threads=proposal_threads, flash_msg=flash_msg, flash_ok=flash_ok, ) @bp.route("/lore/action", methods=["POST"]) def lore_action(): prop_id = int(request.form.get("id", 0)) action = request.form.get("action", "") modified_text = request.form.get("modified_text", "").strip() filt_faction = request.form.get("filt_faction", "") filt_status = request.form.get("filt_status", "pending") proposal = query_one("SELECT * FROM lore_proposals WHERE id = %s", (prop_id,)) if not proposal: return redirect(url_for("lore.lore", msg="Proposition introuvable", ok=0, faction=filt_faction, status=filt_status)) try: if action == "accept": execute("UPDATE lore_proposals SET status='accepted', reviewed_at=NOW() WHERE id=%s", (prop_id,)) upsert_lore_enriched({**proposal, "modified_text": None}) msg = f"Proposition #{prop_id} acceptée et indexée dans {CHROMA_COL_OUT}." elif action == "reject": execute("UPDATE lore_proposals SET status='rejected', reviewed_at=NOW() WHERE id=%s", (prop_id,)) msg = f"Proposition #{prop_id} rejetée." elif action == "modify": if not modified_text: modified_text = proposal["proposed_text"] execute("""UPDATE lore_proposals SET status='modified', modified_text=%s, reviewed_at=NOW() WHERE id=%s""", (modified_text, prop_id)) upsert_lore_enriched({**proposal, "modified_text": modified_text}) msg = f"Proposition #{prop_id} modifiée et indexée dans {CHROMA_COL_OUT}." else: msg = "Action inconnue." ok = 1 except Exception as e: msg = f"Erreur: {e}" ok = 0 return redirect(url_for("lore.lore", msg=msg, ok=ok, faction=filt_faction, status=filt_status))