forked from erp-dev/erp
132 lines
3.7 KiB
Python
132 lines
3.7 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from dataclasses import dataclass
|
|
from urllib.parse import urljoin
|
|
from urllib.error import HTTPError, URLError
|
|
from urllib.request import Request, urlopen
|
|
|
|
from django.conf import settings
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class MessageAPIResponse:
|
|
errcode: int
|
|
errmsg: str
|
|
raw: dict
|
|
|
|
@property
|
|
def ok(self) -> bool:
|
|
return int(self.errcode) == 0
|
|
|
|
|
|
def _request_json(
|
|
*,
|
|
url: str,
|
|
method: str = "GET",
|
|
payload: dict | None = None,
|
|
timeout_seconds: float = 10.0,
|
|
headers: dict | None = None,
|
|
) -> dict:
|
|
data = None
|
|
request_headers = dict(headers or {})
|
|
if payload is not None:
|
|
data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
|
|
request_headers.setdefault("Content-Type", "application/json")
|
|
|
|
req = Request(url=url, data=data, headers=request_headers, method=method)
|
|
try:
|
|
with urlopen(req, timeout=float(timeout_seconds)) as resp:
|
|
body = resp.read().decode("utf-8", errors="replace")
|
|
except HTTPError as exc:
|
|
body = ""
|
|
try:
|
|
body = exc.read().decode("utf-8", errors="replace")
|
|
except Exception:
|
|
pass
|
|
raise RuntimeError(f"Message API HTTPError: status={exc.code}, body={body}") from exc
|
|
except URLError as exc:
|
|
raise RuntimeError(f"Message API URLError: {exc}") from exc
|
|
|
|
try:
|
|
return json.loads(body) if body else {}
|
|
except Exception as exc:
|
|
raise RuntimeError(f"Message API 响应不是合法 JSON: {body}") from exc
|
|
|
|
|
|
def _get_message_api_base_url() -> str:
|
|
base_url = str(getattr(settings, "MESSAGE_API_BASE_URL", "") or "").strip().rstrip("/")
|
|
if not base_url:
|
|
raise ValueError("MESSAGE_API_BASE_URL 未配置")
|
|
return base_url
|
|
|
|
|
|
def _get_message_api_authorization() -> str:
|
|
authorization = str(getattr(settings, "MESSAGE_API_AUTHORIZATION", "") or "").strip()
|
|
if not authorization:
|
|
raise ValueError("MESSAGE_API_AUTHORIZATION 未配置")
|
|
return authorization
|
|
|
|
|
|
def _build_url(path: str) -> str:
|
|
return urljoin(f"{_get_message_api_base_url()}/", path.lstrip("/"))
|
|
|
|
|
|
def _post_message_api(*, path: str, payload: dict, timeout_seconds: float) -> dict:
|
|
raw = _request_json(
|
|
url=_build_url(path),
|
|
method="POST",
|
|
payload=payload,
|
|
timeout_seconds=timeout_seconds,
|
|
headers={
|
|
"Authorization": _get_message_api_authorization(),
|
|
"Content-Type": "application/json",
|
|
},
|
|
)
|
|
return raw
|
|
|
|
|
|
def send_message_api_text_message(
|
|
*,
|
|
agent_id: int,
|
|
content: str,
|
|
user_ids: list[str] | None = None,
|
|
timeout_seconds: float = 10.0,
|
|
) -> MessageAPIResponse:
|
|
payload = {
|
|
"agent_id": int(agent_id),
|
|
"content": str(content or "").strip(),
|
|
}
|
|
if user_ids:
|
|
payload["user_ids"] = user_ids
|
|
|
|
raw = _post_message_api(path="/api/message/send", payload=payload, timeout_seconds=timeout_seconds)
|
|
return MessageAPIResponse(
|
|
errcode=int(raw.get("errcode") or 0),
|
|
errmsg=str(raw.get("errmsg") or ""),
|
|
raw=raw,
|
|
)
|
|
|
|
|
|
def send_message_api_news_to_agents(
|
|
*,
|
|
agent_ids: list[int],
|
|
title: str,
|
|
description: str,
|
|
url: str,
|
|
image_url: str,
|
|
user_ids: list[str] | None = None,
|
|
timeout_seconds: float = 10.0,
|
|
) -> list[dict]:
|
|
payload = {
|
|
"agent_ids": [int(agent_id) for agent_id in agent_ids],
|
|
"title": title,
|
|
"description": description,
|
|
"url": url,
|
|
"image_url": image_url,
|
|
}
|
|
if user_ids:
|
|
payload["user_ids"] = user_ids
|
|
|
|
raw = _post_message_api(path="/api/message/send/news", payload=payload, timeout_seconds=timeout_seconds)
|
|
return raw.get("results") or [] |