Files
foodlinkk-command-center/cockpit/app/services/platform_live.py
T
Aissa 5d60d33db1 Platform bundle: marketing publish, IT ops, packaging, agents mesh.
Volledige Foodlinkk Command Center uitbreiding met social automatisering,
reclamefolder filters, Proxmox monitoring en documentatie.
2026-06-09 00:41:27 +00:00

114 lines
3.9 KiB
Python

"""Unified live platform feed — events with traceable sources."""
from __future__ import annotations
from datetime import datetime, timezone
from typing import Any, Optional
from app.db import fetch_all
CHANNEL_ROUTES = {
"dashboard": "/",
"retail": "/retail",
"marketing": "/marketing",
"beurs": "/beurs",
"agents": "/agents",
"hermes": "/hermes",
"browser": "/browser",
"documents": "/documents",
"settings": "/settings",
}
def _resolve_source(row: dict[str, Any]) -> dict[str, Any]:
meta = row.get("metadata") or {}
if isinstance(meta, str):
import json
try:
meta = json.loads(meta)
except Exception:
meta = {}
source_url = meta.get("source_url") or meta.get("url") or meta.get("link")
source_label = meta.get("source") or meta.get("feed_name")
if not source_url:
channel = row.get("channel") or "dashboard"
source_url = CHANNEL_ROUTES.get(channel, "/")
source_label = source_label or f"Foodlinkk · {channel}"
if row.get("related_table") == "rss_items" and row.get("related_id"):
source_url = meta.get("link") or source_url
event_type = (row.get("event_type") or "").lower()
agent = (row.get("agent_name") or "").lower()
if event_type in ("briefing", "report"):
source_url = "/"
elif event_type in ("sync", "score", "import") and "retail" in agent:
source_url = "/retail"
elif event_type == "refresh" and "rss" in agent:
source_url = "/marketing"
elif event_type in ("sync",) and "halal" in agent:
source_url = "/retail"
elif agent == "herman":
source_url = "/"
elif agent in ("marketing", "rss_feeds"):
source_url = "/marketing"
elif agent in ("wholesale_scraper", "retail_intel"):
source_url = "/retail"
elif agent == "hermes":
source_url = "/hermes"
internal_url = source_url if source_url.startswith("/") else None
external_url = source_url if source_url and source_url.startswith("http") else None
return {
"source_url": source_url,
"source_label": source_label or "Foodlinkk platform",
"internal_url": internal_url,
"external_url": external_url,
}
def fetch_platform_events(limit: int = 80, agent: Optional[str] = None) -> list[dict[str, Any]]:
clauses, params = [], []
if agent:
clauses.append("LOWER(agent_name) = %s")
params.append(agent.lower())
where = (" WHERE " + " AND ".join(clauses)) if clauses else ""
rows = fetch_all(
f"""SELECT id, agent_name, agent_type, event_type, title, body, status,
channel, metadata, related_table, related_id, created_at
FROM agent_events{where}
ORDER BY created_at DESC LIMIT %s""",
tuple(params + [limit]),
)
events = []
for r in rows:
item = dict(r)
if item.get("created_at"):
item["created_at"] = item["created_at"].isoformat()
src = _resolve_source(item)
item.update(src)
item["click_url"] = src.get("external_url") or src.get("internal_url") or "/agents"
item["is_external"] = bool(src.get("external_url"))
events.append(item)
return events
def platform_stats() -> dict[str, Any]:
try:
total = fetch_all("SELECT COUNT(*) AS n FROM agent_events")[0]["n"]
pending = fetch_all("SELECT COUNT(*) AS n FROM agent_events WHERE status = 'needs_approval'")[0]["n"]
last_hour = fetch_all(
"SELECT COUNT(*) AS n FROM agent_events WHERE created_at >= NOW() - INTERVAL '1 hour'"
)[0]["n"]
except Exception:
total = pending = last_hour = 0
return {
"total_events": int(total or 0),
"pending_approvals": int(pending or 0),
"events_last_hour": int(last_hour or 0),
"updated_at": datetime.now(timezone.utc).isoformat(),
}