Spaces:
Runtime error
Runtime error
File size: 1,892 Bytes
3291500 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | """
钉钉自定义机器人:加签并 POST 发送 Markdown 消息。
"""
import base64
import hashlib
import hmac
import os
import time
import urllib.parse
from pathlib import Path
import requests
from dotenv import load_dotenv
# 从项目根目录加载 .env
_project_root = Path(__file__).resolve().parent.parent
load_dotenv(_project_root / ".env")
def _sign(secret: str) -> tuple[str, str]:
timestamp = str(round(time.time() * 1000))
string_to_sign = f"{timestamp}\n{secret}"
hmac_code = hmac.new(
secret.encode("utf-8"),
string_to_sign.encode("utf-8"),
digestmod=hashlib.sha256,
).digest()
sign = urllib.parse.quote(base64.b64encode(hmac_code))
return timestamp, sign
def build_signed_url(webhook: str, secret: str) -> str:
"""在 Webhook URL 后追加 timestamp 与 sign 参数。"""
timestamp, sign = _sign(secret)
sep = "&" if "?" in webhook else "?"
return f"{webhook}{sep}timestamp={timestamp}&sign={sign}"
def send_markdown(title: str, text: str) -> tuple[bool, str]:
"""
发送钉钉 Markdown 消息。
返回 (成功与否, 错误信息)。
"""
webhook = os.environ.get("DINGTALK_WEBHOOK", "").strip()
secret = os.environ.get("DINGTALK_SECRET", "").strip()
if not webhook:
return False, "未配置 DINGTALK_WEBHOOK"
url = build_signed_url(webhook, secret) if secret else webhook
body = {
"msgtype": "markdown",
"markdown": {
"title": title,
"text": text,
},
}
try:
r = requests.post(url, json=body, headers={"Content-Type": "application/json"}, timeout=10)
data = r.json()
if r.status_code != 200 or data.get("errcode") != 0:
return False, data.get("errmsg", r.text) or str(r.status_code)
return True, ""
except Exception as e:
return False, str(e)
|