Platform bundle: marketing publish, IT ops, packaging, agents mesh.
Volledige Foodlinkk Command Center uitbreiding met social automatisering, reclamefolder filters, Proxmox monitoring en documentatie.
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
"""Foodlinkk Email Agent — IMAP sync + CEO approval workflow."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Any
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.config import settings
|
||||
from app.db import close_pool, fetch_one, init_pool
|
||||
from app import imap_sync
|
||||
|
||||
|
||||
class DraftIn(BaseModel):
|
||||
title: str = Field(..., min_length=3, max_length=255)
|
||||
to: str
|
||||
subject: str
|
||||
body: str
|
||||
|
||||
|
||||
async def _sync_loop() -> None:
|
||||
while True:
|
||||
try:
|
||||
imap_sync.sync_all_accounts()
|
||||
except Exception:
|
||||
pass
|
||||
await asyncio.sleep(settings.SYNC_INTERVAL_SEC)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
init_pool()
|
||||
task = asyncio.create_task(_sync_loop())
|
||||
yield
|
||||
task.cancel()
|
||||
close_pool()
|
||||
|
||||
|
||||
app = FastAPI(title="Foodlinkk Email Agent", version="1.0.0", lifespan=lifespan)
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health() -> dict[str, Any]:
|
||||
db_ok = bool(fetch_one("SELECT 1 AS ok"))
|
||||
accounts = fetch_one(
|
||||
"SELECT COUNT(*) AS n FROM email_accounts WHERE is_active = TRUE AND sync_enabled = TRUE"
|
||||
)
|
||||
return {
|
||||
"status": "ok" if db_ok else "degraded",
|
||||
"database": "connected" if db_ok else "error",
|
||||
"imap_accounts": int((accounts or {}).get("n") or 0),
|
||||
}
|
||||
|
||||
|
||||
@app.post("/sync")
|
||||
def sync_now() -> dict[str, Any]:
|
||||
return imap_sync.sync_all_accounts()
|
||||
|
||||
|
||||
@app.get("/drafts/pending")
|
||||
def pending_drafts() -> dict[str, Any]:
|
||||
items = imap_sync.list_pending_drafts()
|
||||
return {"items": items, "count": len(items)}
|
||||
|
||||
|
||||
@app.post("/drafts")
|
||||
def create_draft(payload: DraftIn) -> dict[str, Any]:
|
||||
row = imap_sync.create_draft(payload.title, payload.body, payload.to, payload.subject)
|
||||
return {"draft": row}
|
||||
|
||||
|
||||
@app.post("/drafts/{rec_id}/approve")
|
||||
def approve_draft(rec_id: int) -> dict[str, Any]:
|
||||
try:
|
||||
return imap_sync.approve_draft(rec_id)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(400, str(exc)) from exc
|
||||
except Exception as exc: # noqa: BLE001
|
||||
raise HTTPException(502, str(exc)) from exc
|
||||
Reference in New Issue
Block a user