"""DingTalk webhook signing and message formatting (ported from monitor script).""" import base64 import hashlib import hmac import json import time from typing import Any from urllib.parse import quote_plus def dingtalk_signed_url(webhook_url: str, secret: str) -> str: timestamp = str(int(time.time() * 1000)) string_to_sign = f"{timestamp}\n{secret}".encode("utf-8") digest = hmac.new(secret.encode("utf-8"), string_to_sign, hashlib.sha256).digest() sign = quote_plus(base64.b64encode(digest).decode("utf-8")) sep = "&" if "?" in webhook_url else "?" return f"{webhook_url}{sep}timestamp={timestamp}&sign={sign}" def format_dingtalk_rate_changed(upstream_name: str, changed_at: str, changes: list[dict[str, Any]]) -> dict[str, Any]: lines = [ f"### πŸ“Š {upstream_name} εˆ†η»„ε€ηŽ‡ε˜ζ›΄", "", f"- **ζ—Άι—΄**:{changed_at}", f"- **ε˜εŒ–ζ•°ι‡**:{len(changes)}", "", ] for ch in changes: name = ch.get("group_name") or ch.get("group_id") or "unknown" platform = ch.get("platform") or "-" old = ch.get("old_rate") new = ch.get("new_rate") lines.append(f"- `{name}` ({platform}):`{old}` β†’ `{new}`") return { "msgtype": "markdown", "markdown": { "title": f"{upstream_name} εˆ†η»„ε€ηŽ‡ε˜ζ›΄", "text": "\n".join(lines), }, } def format_dingtalk_website_rate_changed( website_name: str, target_group_name: str, changed_at: str, old_rate: Any, new_rate: Any, ) -> dict[str, Any]: group_name = target_group_name or "unknown" lines = [ f"### η½‘η«™ε€ηŽ‡ε˜ζ›΄οΌš{website_name}", "", f"- ζ—Άι—΄οΌš{changed_at}", f"- εˆ†η»„οΌš`{group_name}`", f"- ε€ηŽ‡οΌš`{old_rate}` -> `{new_rate}`", ] return { "msgtype": "markdown", "markdown": { "title": f"{website_name} η½‘η«™ε€ηŽ‡ε˜ζ›΄", "text": "\n".join(lines), }, } def format_dingtalk_balance_low( upstream_name: str, balance: float, threshold: float, changed_at: str ) -> dict[str, Any]: lines = [ f"### ⚠️ {upstream_name} 余钝不袳", "", f"- **当前余钝**:{balance:.2f}", f"- **ε‘Šθ­¦ι˜ˆε€Ό**:{threshold:.2f}", f"- **ζ—Άι—΄**:{changed_at}", ] return { "msgtype": "markdown", "markdown": { "title": f"{upstream_name} 余钝不袳", "text": "\n".join(lines), }, } def format_dingtalk_status(upstream_name: str, event: str, changed_at: str, error: str = "") -> dict[str, Any]: emoji = "πŸ”΄" if event == "upstream_unhealthy" else "🟒" label = "ζœεŠ‘εΌ‚εΈΈ" if event == "upstream_unhealthy" else "服劑恒倍" lines = [ f"### {emoji} {upstream_name} {label}", "", f"- **ζ—Άι—΄**:{changed_at}", ] if error: lines.append(f"- **ι”™θ――**:{error}") return { "msgtype": "markdown", "markdown": { "title": f"{upstream_name} {label}", "text": "\n".join(lines), }, }