myrmidon / python /src /server /services /marketing /approval_manager.py
tek Atrust
chore(deploy): build monolithic server for Hugging Face
d5ef46f
Raw
History Blame Contribute Delete
3.47 kB
import asyncio
from typing import Any
from google import genai
from ...config.model_ssot import SYSTEM_MODELS
from ..librarian_service import LibrarianService
from ..prompt_service import prompt_service
from .content_handler import get_logger
logger = get_logger(__name__)
class ApprovalManager:
"""Handles content approval workflows and feedback suggestion generation."""
def __init__(self, supabase_client: Any):
self.supabase_client = supabase_client
async def process_approval(self, item_type: str, item_id: str, action: str, notes: str | None) -> bool:
if item_type == "blog":
new_status = "published" if action == "approve" else "changes_requested"
res = (
self.supabase_client.table("blog_posts")
.update({"status": new_status, "review_notes": notes})
.eq("id", item_id)
.execute()
)
if action != "approve" and notes and res.data:
try:
post_data = res.data[0]
asyncio.create_task(
LibrarianService().archive_style_critique(
post_title=post_data.get("title", "Untitled"),
original_content=post_data.get("content", ""),
review_notes=notes,
)
)
except Exception as e:
logger.error(f"ApprovalManager: Failed to archive style critique for blog {item_id}: {e}")
return True
return False
async def get_pending_approvals(self) -> dict:
res = (
self.supabase_client.table("blog_posts")
.select("*")
.eq("status", "review")
.order("updated_at", desc=True)
.execute()
)
return {"blogs": res.data or [], "leads": []}
async def generate_reject_suggestion(self, item_type: str, item_id: str) -> dict:
if item_type != "blog":
return {"notes": "Content type not supported for AI rejection."}
post = self.supabase_client.table("blog_posts").select("*").eq("id", item_id).single().execute().data
if not post:
return {"notes": "Item not found."}
from ..credential_service import credential_service
api_key = await credential_service.get_credential("GEMINI_API_KEY")
if not api_key:
return {"notes": "Cannot generate AI reason: AI provider missing."}
client = genai.Client(api_key=api_key)
default_prompt = (
"You are a marketing director reviewing a blog post draft.\n"
"The draft is slightly off-brand or has quality issues.\n"
"Content:\n{content}\n\n"
"Provide exactly ONE brief, constructive paragraph (max 50 words) explaining why this is rejected and what needs to be improved. Use Traditional Chinese."
)
prompt_template = prompt_service.get_prompt("REJECT_SUGGESTION", default=default_prompt)
prompt = prompt_template.format(content=post.get("content", ""))
try:
response = await client.aio.models.generate_content(model=SYSTEM_MODELS["DEFAULT_TEXT"], contents=prompt)
return {"notes": response.text.strip() if response.text else "Failed to generate reason."}
except Exception as e:
return {"notes": f"AI Generation Failed: {str(e)}"}