from collections.abc import Mapping from datetime import UTC, datetime from typing import Any from motor.motor_asyncio import AsyncIOMotorCollection from app.core.mongodb import get_database from app.models.template import ProxyTemplateCreateInput, ProxyTemplateDocument COLLECTION_NAME = "addon_templates" def utcnow() -> datetime: return datetime.now(UTC) async def collection() -> AsyncIOMotorCollection[dict[str, Any]]: database = await get_database() return database[COLLECTION_NAME] def deserialize(raw: Mapping[str, Any] | None) -> ProxyTemplateDocument | None: if raw is None: return None document = dict(raw) document.pop("_id", None) return ProxyTemplateDocument.model_validate(document) async def ensure_template_indexes() -> None: templates = await collection() await templates.create_index("id", unique=True, name="uq_addon_template_id") async def list_custom_templates() -> list[ProxyTemplateDocument]: templates = await collection() cursor = templates.find({}).sort("name", 1) result: list[ProxyTemplateDocument] = [] async for raw in cursor: template = deserialize(raw) if template is not None: result.append(template) return result async def create_custom_template( payload: ProxyTemplateCreateInput, ) -> ProxyTemplateDocument: now = utcnow() template = ProxyTemplateDocument( id=payload.id, name=payload.name, description=payload.description, category=payload.category, protocol=payload.protocol, family=payload.family, tags=payload.tags, action=payload.action, summary=payload.summary, behavior=payload.behavior, code=payload.code, source_url=payload.source_url, built_in=False, created_at=now, updated_at=now, ) templates = await collection() await templates.insert_one(template.model_dump(exclude_none=True)) return template async def delete_custom_template(template_id: str) -> bool: templates = await collection() result = await templates.delete_one({"id": template_id}) return result.deleted_count > 0