mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 16:44:15 +08:00
refactor: 「群机器人 Webhook」统一更名为「群推送 Webhook」 (#86)
"群机器人"易与后续接入的"智能机器人(API 模式)"混淆。 该通道本质是单向往群聊推送消息, 更名为「群推送 Webhook」更准确。 涉及: 飞书/企业微信的 UI 标签、操作指引、后端文档字符串、 错误提示文案(代码逻辑/接口不变)。覆盖 6 个文件, 纯文案改动。
This commit is contained in:
@@ -829,9 +829,9 @@ class WecomWebhookPrefsIn(BaseModel):
|
||||
|
||||
@router.put("/preferences/wecom-webhook")
|
||||
def update_wecom_webhook(req: WecomWebhookPrefsIn) -> dict:
|
||||
"""企业微信群机器人 Webhook 地址 — 与飞书并列的第二推送通道。
|
||||
"""企业微信群推送 Webhook 地址 — 与飞书并列的第二推送通道。
|
||||
|
||||
- url: 传入空串表示清空配置; 非空需为合法企业微信群机器人地址, 或纯 key。
|
||||
- url: 传入空串表示清空配置; 非空需为合法企业微信群推送 Webhook 地址, 或纯 key。
|
||||
- 用户可只填 key (webhook/send?key=xxx 的 xxx 部分), 后端自动补全为完整 URL。
|
||||
"""
|
||||
from app.services import preferences
|
||||
@@ -841,7 +841,7 @@ def update_wecom_webhook(req: WecomWebhookPrefsIn) -> dict:
|
||||
if url and not webhook_adapter.is_valid_wecom_url(url):
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Webhook 地址非法, 需为企业微信群机器人地址 "
|
||||
detail="Webhook 地址非法, 需为企业微信群推送 Webhook 地址 "
|
||||
"(https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=... 或纯 key)",
|
||||
)
|
||||
saved_url = preferences.set_wecom_webhook_url(url)
|
||||
|
||||
@@ -477,7 +477,7 @@ def set_feishu_webhook_secret(secret: str) -> str:
|
||||
|
||||
|
||||
def get_wecom_webhook_url() -> str:
|
||||
"""企业微信群机器人 Webhook 地址 — 与飞书并列的第二推送通道。
|
||||
"""企业微信群推送 Webhook 地址 — 与飞书并列的第二推送通道。
|
||||
|
||||
存储完整 URL (https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx);
|
||||
用户也可只填 key, 由 webhook_adapter.normalize_wecom_url 自动补全。
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""Webhook 推送适配器 — 把告警事件推送到外部 IM / 量化软件。
|
||||
|
||||
职责: 把后端产生的告警事件, 通过用户配置的 Webhook 地址推送到外部。
|
||||
目前支持飞书群机器人; QMT / ptrade 等量化通道为待定。
|
||||
目前支持飞书群推送 Webhook; QMT / ptrade 等量化通道为待定。
|
||||
|
||||
飞书自定义机器人接入:
|
||||
1. 飞书群 → 群设置 → 群机器人 → 添加「自定义机器人」
|
||||
1. 飞书群 → 群设置 → 群推送 Webhook → 添加「自定义机器人」
|
||||
2. 复制生成的 Webhook 地址 (形如 https://open.feishu.cn/open-apis/bot/v2/hook/xxx)
|
||||
3. (可选) 安全设置 → 启用「签名校验」, 记录签名密钥(secret)
|
||||
4. 填入设置页「飞书 Webhook」配置
|
||||
@@ -28,7 +28,7 @@ _MAX_LEN = 500
|
||||
# 卡片消息正文最长字符 (飞书 interactive 卡片上限 30KB, 保守留余量给标题/结构)
|
||||
_CARD_MAX_LEN = 28000
|
||||
|
||||
# 企业微信群机器人 markdown 消息上限 4096 字节 (非字符; 中文每字 3 字节),
|
||||
# 企业微信群推送 Webhook markdown 消息上限 4096 字节 (非字符; 中文每字 3 字节),
|
||||
# 留余量给标题、格式符及截断提示行。
|
||||
_WECOM_MD_MAX_BYTES = 4000
|
||||
|
||||
@@ -144,7 +144,7 @@ def _post_feishu(webhook_url: str, payload: dict, secret: str) -> bool:
|
||||
|
||||
|
||||
def send_feishu(webhook_url: str, title: str, body: str, secret: str = "") -> bool:
|
||||
"""推送一条文本消息到飞书群机器人。
|
||||
"""推送一条文本消息到飞书群推送 Webhook。
|
||||
|
||||
Args:
|
||||
webhook_url: 飞书自定义机器人 Webhook 地址
|
||||
@@ -168,7 +168,7 @@ def send_feishu(webhook_url: str, title: str, body: str, secret: str = "") -> bo
|
||||
|
||||
|
||||
def send_feishu_card(webhook_url: str, title: str, subtitle: str, body_md: str, secret: str = "") -> bool:
|
||||
"""推送一条 interactive 卡片消息到飞书群机器人 —— 用 lark_md 渲染完整 markdown 报告。
|
||||
"""推送一条 interactive 卡片消息到飞书群推送 Webhook —— 用 lark_md 渲染完整 markdown 报告。
|
||||
|
||||
飞书「自定义机器人」webhook 不支持文件附件, 但 interactive 卡片的 lark_md 元素
|
||||
可渲染 markdown, 能承载完整复盘报告(通常 2-5KB, 远小于卡片 30KB 上限)。
|
||||
@@ -215,13 +215,13 @@ def send_feishu_card(webhook_url: str, title: str, subtitle: str, body_md: str,
|
||||
|
||||
|
||||
# ================================================================
|
||||
# 企业微信群机器人
|
||||
# 企业微信群推送 Webhook
|
||||
# ================================================================
|
||||
#
|
||||
# 与飞书自定义机器人几乎同构: 同样是"群机器人 Webhook + POST JSON"。
|
||||
# 与飞书自定义机器人几乎同构: 同样是"群推送 Webhook + POST JSON"。
|
||||
# 关键差异:
|
||||
# 1. Webhook 形态: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
|
||||
# 2. 无需签名校验 (key 本身即凭证; 企业微信群机器人可选"签名校验"但极少用)
|
||||
# 2. 无需签名校验 (key 本身即凭证; 企业微信群推送 Webhook 可选"签名校验"但极少用)
|
||||
# 3. Markdown 原生支持 (msgtype=markdown), 不必像飞书那样包进 interactive 卡片
|
||||
# 4. 成功响应: {"errcode":0,"errmsg":"ok"}
|
||||
#
|
||||
@@ -233,11 +233,11 @@ WECOM_HOOK_PREFIX = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send"
|
||||
|
||||
|
||||
def is_valid_wecom_url(url: str) -> bool:
|
||||
"""校验是否为合法的企业微信群机器人 Webhook 地址。
|
||||
"""校验是否为合法的企业微信群推送 Webhook 地址。
|
||||
|
||||
允许两种写法:
|
||||
- 完整: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
|
||||
- 仅 key: xxx (企业微信群机器人 key 为 36 位 UUID 样式, 保存时自动补全)
|
||||
- 仅 key: xxx (企业微信群推送 Webhook 的 key 为 36 位 UUID 样式, 保存时自动补全)
|
||||
"""
|
||||
if not url:
|
||||
return False
|
||||
@@ -289,10 +289,10 @@ def _post_wecom(webhook_url: str, payload: dict) -> bool:
|
||||
|
||||
|
||||
def send_wecom(webhook_url: str, title: str, body: str) -> bool:
|
||||
"""推送一条文本消息到企业微信群机器人。
|
||||
"""推送一条文本消息到企业微信群推送 Webhook。
|
||||
|
||||
Args:
|
||||
webhook_url: 企业微信群机器人 Webhook 地址 (或纯 key, 会自动补全)
|
||||
webhook_url: 企业微信群推送 Webhook 地址 (或纯 key, 会自动补全)
|
||||
title: 消息标题 (与正文拼接为一条文本)
|
||||
body: 消息正文
|
||||
|
||||
@@ -313,13 +313,13 @@ def send_wecom(webhook_url: str, title: str, body: str) -> bool:
|
||||
|
||||
|
||||
def send_wecom_markdown(webhook_url: str, title: str, body_md: str) -> bool:
|
||||
"""推送一条 Markdown 消息到企业微信群机器人 —— 承载完整复盘报告。
|
||||
"""推送一条 Markdown 消息到企业微信群推送 Webhook —— 承载完整复盘报告。
|
||||
|
||||
企业微信群机器人原生支持 markdown 类型 (比飞书 interactive 卡片简单),
|
||||
企业微信群推送 Webhook 原生支持 markdown 类型 (比飞书 interactive 卡片简单),
|
||||
支持 # ## **粗体** >引用 - 列表 等基础语法, 单条上限 4096 字节。
|
||||
|
||||
Args:
|
||||
webhook_url: 企业微信群机器人 Webhook 地址 (或纯 key)
|
||||
webhook_url: 企业微信群推送 Webhook 地址 (或纯 key)
|
||||
title: 标题 (作为一级标题 ## 拼到正文前)
|
||||
body_md: markdown 正文
|
||||
|
||||
|
||||
@@ -433,7 +433,7 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) {
|
||||
className="h-3 w-3 accent-accent cursor-pointer"
|
||||
/>
|
||||
<span className="text-[11px] text-foreground">飞书</span>
|
||||
<span className="text-[9px] text-muted">群机器人</span>
|
||||
<span className="text-[9px] text-muted">群推送 Webhook</span>
|
||||
{(draft.webhook_channels ?? []).includes('feishu') && (
|
||||
<span className={`ml-auto text-[9px] ${feishuConfigured ? 'text-emerald-500' : 'text-warning'}`}>
|
||||
{feishuConfigured ? '已配置' : '未配置'}
|
||||
@@ -450,7 +450,7 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) {
|
||||
className="h-3 w-3 accent-accent cursor-pointer"
|
||||
/>
|
||||
<span className="text-[11px] text-foreground">企业微信</span>
|
||||
<span className="text-[9px] text-muted">群机器人</span>
|
||||
<span className="text-[9px] text-muted">群推送 Webhook</span>
|
||||
{(draft.webhook_channels ?? []).includes('wecom') && (
|
||||
<span className={`ml-auto text-[9px] ${wecomConfigured ? 'text-emerald-500' : 'text-warning'}`}>
|
||||
{wecomConfigured ? '已配置' : '未配置'}
|
||||
|
||||
@@ -439,7 +439,7 @@ export function Review() {
|
||||
{reviewPushChannels.includes('feishu') && <Check className="h-2.5 w-2.5" />}
|
||||
</span>
|
||||
<span className="text-[11px] text-foreground">飞书</span>
|
||||
<span className="text-[9px] text-muted">群机器人</span>
|
||||
<span className="text-[9px] text-muted">群推送 Webhook</span>
|
||||
<span className={cn('ml-auto text-[9px]', feishuConfigured ? 'text-emerald-500' : 'text-warning')}>
|
||||
{feishuConfigured ? '已配置' : '未配置'}
|
||||
</span>
|
||||
@@ -460,7 +460,7 @@ export function Review() {
|
||||
{reviewPushChannels.includes('wecom') && <Check className="h-2.5 w-2.5" />}
|
||||
</span>
|
||||
<span className="text-[11px] text-foreground">企业微信</span>
|
||||
<span className="text-[9px] text-muted">群机器人</span>
|
||||
<span className="text-[9px] text-muted">群推送 Webhook</span>
|
||||
<span className={cn('ml-auto text-[9px]', wecomConfigured ? 'text-emerald-500' : 'text-warning')}>
|
||||
{wecomConfigured ? '已配置' : '未配置'}
|
||||
</span>
|
||||
|
||||
@@ -447,7 +447,7 @@ export function SettingsMonitoringPanel({ highlight }: { highlight?: string } =
|
||||
className="h-3 w-3 accent-accent cursor-pointer"
|
||||
/>
|
||||
<span className="text-[11px] font-medium text-foreground">飞书</span>
|
||||
<span className="text-[9px] text-muted">群机器人</span>
|
||||
<span className="text-[9px] text-muted">群推送 Webhook</span>
|
||||
{webhookDefaultChannels.includes('feishu') && (
|
||||
<span className="rounded bg-accent/15 px-1 py-px text-[9px] text-accent">默认</span>
|
||||
)}
|
||||
@@ -501,7 +501,7 @@ export function SettingsMonitoringPanel({ highlight }: { highlight?: string } =
|
||||
<details className="mt-3 text-[10px] text-muted">
|
||||
<summary className="cursor-pointer hover:text-secondary">如何获取飞书 Webhook 地址?</summary>
|
||||
<ol className="mt-1.5 space-y-1 pl-4 list-decimal leading-relaxed">
|
||||
<li>打开飞书,进入目标群聊 → 群设置 → <b>群机器人</b></li>
|
||||
<li>打开飞书,进入目标群聊 → 群设置 → <b>群推送 Webhook</b></li>
|
||||
<li>点击「添加机器人」→ 选择「<b>自定义机器人</b>」</li>
|
||||
<li>填写机器人名称后添加,复制生成的 Webhook 地址</li>
|
||||
<li>安全设置若启用了「<b>签名校验</b>」,把密钥一并复制填到「签名密钥」框</li>
|
||||
@@ -518,7 +518,7 @@ export function SettingsMonitoringPanel({ highlight }: { highlight?: string } =
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 企业微信群机器人 (可用): 与飞书并列, 勾选默认 + 展开地址配置 */}
|
||||
{/* 企业微信群推送 Webhook (可用): 与飞书并列, 勾选默认 + 展开地址配置 */}
|
||||
<div className="rounded-btn border border-border/60 bg-base/40 overflow-hidden">
|
||||
<div
|
||||
onClick={() => setWecomOpen(o => !o)}
|
||||
@@ -533,7 +533,7 @@ export function SettingsMonitoringPanel({ highlight }: { highlight?: string } =
|
||||
className="h-3 w-3 accent-accent cursor-pointer"
|
||||
/>
|
||||
<span className="text-[11px] font-medium text-foreground">企业微信</span>
|
||||
<span className="text-[9px] text-muted">群机器人</span>
|
||||
<span className="text-[9px] text-muted">群推送 Webhook</span>
|
||||
{webhookDefaultChannels.includes('wecom') && (
|
||||
<span className="rounded bg-accent/15 px-1 py-px text-[9px] text-accent">默认</span>
|
||||
)}
|
||||
@@ -575,7 +575,7 @@ export function SettingsMonitoringPanel({ highlight }: { highlight?: string } =
|
||||
<details className="mt-3 text-[10px] text-muted">
|
||||
<summary className="cursor-pointer hover:text-secondary">如何获取企业微信 Webhook 地址?</summary>
|
||||
<ol className="mt-1.5 space-y-1 pl-4 list-decimal leading-relaxed">
|
||||
<li>打开企业微信,进入目标群聊 → 右上角「...」→ <b>群机器人</b></li>
|
||||
<li>打开企业微信,进入目标群聊 → 右上角「...」→ <b>群推送 Webhook</b></li>
|
||||
<li>点击「添加」→ 选择「<b>自定义机器人</b>」→ 填写名字</li>
|
||||
<li>复制生成的 <b>Webhook 地址</b>(含 key 参数),粘贴到上方输入框</li>
|
||||
<li>也可只复制 key 参数部分(= 后面的内容)填入</li>
|
||||
@@ -584,7 +584,7 @@ export function SettingsMonitoringPanel({ highlight }: { highlight?: string } =
|
||||
<p className="mt-1.5 pl-4 text-muted/70">
|
||||
📖 官方文档:
|
||||
<a href="https://developer.work.weixin.qq.com/document/path/91770" target="_blank" rel="noreferrer" className="text-accent hover:text-accent/80">
|
||||
群机器人使用指南 ↗
|
||||
群推送 Webhook 使用指南 ↗
|
||||
</a>
|
||||
</p>
|
||||
</details>
|
||||
|
||||
Reference in New Issue
Block a user