Files
mai-bot/plugin-templates/MaiBot-Napcat-Adapter/codecs/notice/helpers.py

84 lines
2.5 KiB
Python

"""NapCat 通知编解码公共辅助函数。"""
from __future__ import annotations
from hashlib import sha1
from typing import Any, Mapping, Optional
import json
def build_payload_digest(payload: Mapping[str, Any]) -> str:
"""对通知载荷生成稳定哈希。
Args:
payload: 原始通知载荷。
Returns:
str: 基于规范化 JSON 文本生成的 SHA-1 十六进制摘要。
"""
normalized_payload = normalize_payload_value(payload)
serialized_payload = json.dumps(
normalized_payload,
ensure_ascii=False,
separators=(",", ":"),
sort_keys=True,
)
return sha1(serialized_payload.encode("utf-8")).hexdigest()
def normalize_optional_string(value: Any) -> Optional[str]:
"""将任意值规范化为可选字符串。
Args:
value: 待规范化的值。
Returns:
Optional[str]: 规范化后的字符串;若值为空则返回 ``None``。
"""
if value is None:
return None
normalized_value = str(value).strip()
return normalized_value if normalized_value else None
def normalize_payload_value(value: Any) -> Any:
"""将通知载荷递归规范化为稳定 JSON 结构。
Args:
value: 待规范化的任意值。
Returns:
Any: 仅包含 JSON 基础类型的稳定结构。
"""
if isinstance(value, Mapping):
return {
str(key): normalize_payload_value(child_value)
for key, child_value in sorted(value.items(), key=lambda item: str(item[0]))
}
if isinstance(value, (list, tuple)):
return [normalize_payload_value(item) for item in value]
if isinstance(value, set):
normalized_items = [normalize_payload_value(item) for item in value]
return sorted(normalized_items, key=lambda item: json.dumps(item, ensure_ascii=False, sort_keys=True))
if value is None or isinstance(value, (bool, int, float, str)):
return value
return str(value)
def resolve_actor_user_id(payload: Mapping[str, Any]) -> str:
"""解析通知事件中的操作者用户号。
Args:
payload: 原始通知事件。
Returns:
str: 规范化后的操作者用户号;无法确定时返回空字符串。
"""
if bool(payload.get("is_natural_lift", False)):
return ""
actor_user_id = str(payload.get("operator_id") or payload.get("user_id") or "").strip()
if actor_user_id == "0":
return ""
return actor_user_id