xtc-backend / app /api /webhooks.py
a3216's picture
deploy: initial release to Hugging Face Spaces
36fae79
Raw
History Blame Contribute Delete
3.06 kB
"""Webhook 管理 API(admin):/admin/api/webhooks
- GET /admin/api/webhooks 列出全部
- POST /admin/api/webhooks 创建
- GET /admin/api/webhooks/{id} 获取
- PUT /admin/api/webhooks/{id} 更新
- DELETE /admin/api/webhooks/{id} 删除
- POST /admin/api/webhooks/{id}/test 发送测试事件
"""
from __future__ import annotations
from fastapi import APIRouter, Body, Depends
from ..errors import HttpError
from ..services import webhook_store
from ._common import ok_with_cors
from .admin import _require_admin
router = APIRouter(prefix="/admin/api/webhooks", tags=["webhooks"])
@router.get("")
async def list_wh(_admin: str = Depends(_require_admin)):
return ok_with_cors({"items": webhook_store.list_webhooks()})
@router.post("")
async def create_wh(
body: dict = Body(default={}),
_admin: str = Depends(_require_admin),
):
name = body.get("name")
url = body.get("url")
events = body.get("events") or []
if not name or not url:
raise HttpError("name and url are required", status=400, code="bad_request")
if not isinstance(events, list):
raise HttpError("events must be a list", status=400, code="bad_request")
wh = webhook_store.create_webhook(
name=name,
url=url,
events=events,
enabled=bool(body.get("enabled", True)),
)
return ok_with_cors({"webhook": wh})
@router.get("/{webhook_id}")
async def get_wh(webhook_id: int, _admin: str = Depends(_require_admin)):
wh = webhook_store.get_webhook(webhook_id)
if not wh:
raise HttpError(f"webhook not found: {webhook_id}", status=404, code="not_found")
return ok_with_cors({"webhook": wh})
@router.put("/{webhook_id}")
async def update_wh(
webhook_id: int,
body: dict = Body(default={}),
_admin: str = Depends(_require_admin),
):
events = body.get("events")
if events is not None and not isinstance(events, list):
raise HttpError("events must be a list", status=400, code="bad_request")
wh = webhook_store.update_webhook(
webhook_id,
name=body.get("name"),
url=body.get("url"),
events=events,
enabled=body.get("enabled"),
)
if not wh:
raise HttpError(f"webhook not found: {webhook_id}", status=404, code="not_found")
return ok_with_cors({"webhook": wh})
@router.delete("/{webhook_id}")
async def delete_wh(webhook_id: int, _admin: str = Depends(_require_admin)):
ok = webhook_store.delete_webhook(webhook_id)
return ok_with_cors({"deleted": ok, "id": webhook_id})
@router.post("/{webhook_id}/test")
async def test_wh(webhook_id: int, _admin: str = Depends(_require_admin)):
wh = webhook_store.get_webhook(webhook_id)
if not wh:
raise HttpError(f"webhook not found: {webhook_id}", status=404, code="not_found")
await webhook_store.notify(
"test.ping",
{"webhook_id": webhook_id, "name": wh["name"], "message": "test from admin"},
)
return ok_with_cors({"sent": True, "id": webhook_id})