Skip to content

Commit 56bf7e1

Browse files
authored
feat: complete p6 notification channel cleanup (ZhuLinsen#1275)
1 parent e1f9cc5 commit 56bf7e1

29 files changed

Lines changed: 833 additions & 34 deletions

.env.example

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,11 @@ AGENT_SKILLS=
423423
# NTFY_URL=
424424
# NTFY_TOKEN= # 可选,用于需要 Bearer Token 的 topic 或自建 ntfy server
425425
#
426+
# 【方式六扩展】Gotify 配置
427+
# GOTIFY_URL 是 Gotify server base URL,不包含 /message;系统会拼接 /message 并用 X-Gotify-Key Header 发送 token。
428+
# GOTIFY_URL=
429+
# GOTIFY_TOKEN= # Gotify application token
430+
#
426431
# 【方式七】PushPlus 配置(国内推送服务,推荐)
427432
# 注册PushPlus账号并获取Token https://www.pushplus.plus
428433
# PUSHPLUS_TOKEN=
@@ -486,7 +491,7 @@ AGENT_SKILLS=
486491
#
487492
# 【通知路由策略】(Issue #1200 P3)
488493
# 默认留空:该类型通知发送到所有已配置渠道。填写后仅发送到列出的已配置渠道。
489-
# 允许值:wechat,feishu,telegram,email,pushover,ntfy,pushplus,serverchan3,custom,discord,slack,astrbot
494+
# 允许值:wechat,feishu,telegram,email,pushover,ntfy,gotify,pushplus,serverchan3,custom,discord,slack,astrbot
490495
# NOTIFICATION_REPORT_CHANNELS=
491496
# NOTIFICATION_ALERT_CHANNELS=
492497
# NOTIFICATION_SYSTEM_ERROR_CHANNELS=

.github/workflows/daily_analysis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ jobs:
291291
# 方式五扩展:ntfy
292292
NTFY_URL: ${{ secrets.NTFY_URL }}
293293
NTFY_TOKEN: ${{ secrets.NTFY_TOKEN }}
294+
295+
# 方式五扩展:Gotify
296+
GOTIFY_URL: ${{ secrets.GOTIFY_URL }}
297+
GOTIFY_TOKEN: ${{ secrets.GOTIFY_TOKEN }}
294298

295299
# 方式六:PushPlus ⬅️ 新增!
296300
PUSHPLUS_TOKEN: ${{ secrets.PUSHPLUS_TOKEN }}
@@ -427,6 +431,7 @@ jobs:
427431
echo "【通知渠道】"
428432
echo " PushPlus: $([ -n "$PUSHPLUS_TOKEN" ] && echo '✅ 已配置' || echo '⚪ 未配置')"
429433
echo " ntfy: $([ -n "$NTFY_URL" ] && echo '✅ 已配置' || echo '⚪ 未配置')"
434+
echo " Gotify: $([ -n "$GOTIFY_URL" ] && [ -n "$GOTIFY_TOKEN" ] && echo '✅ 已配置' || echo '⚪ 未配置')"
430435
echo " 企业微信: $([ -n "$WECHAT_WEBHOOK_URL" ] && echo '✅ 已配置' || echo '⚪ 未配置')"
431436
echo " 飞书: $([ -n "$FEISHU_WEBHOOK_URL" ] && echo '✅ 已配置' || echo '⚪ 未配置')"
432437
echo " Telegram: $([ -n "$TELEGRAM_BOT_TOKEN" ] && echo '✅ 已配置' || echo '⚪ 未配置')"

api/v1/schemas/system_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"email",
1616
"pushover",
1717
"ntfy",
18+
"gotify",
1819
"pushplus",
1920
"serverchan3",
2021
"custom",

apps/dsa-web/src/components/settings/NotificationTestPanel.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const CHANNEL_OPTIONS: Array<{ value: NotificationTestChannel; label: string }>
1818
{ value: 'email', label: '邮件' },
1919
{ value: 'pushover', label: 'Pushover' },
2020
{ value: 'ntfy', label: 'ntfy' },
21+
{ value: 'gotify', label: 'Gotify' },
2122
{ value: 'pushplus', label: 'PushPlus' },
2223
{ value: 'serverchan3', label: 'Server酱3' },
2324
{ value: 'custom', label: '自定义 Webhook' },

apps/dsa-web/src/components/settings/__tests__/NotificationTestPanel.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ describe('NotificationTestPanel', () => {
4545
);
4646

4747
expect(screen.getByRole('option', { name: 'ntfy' })).toBeInTheDocument();
48+
expect(screen.getByRole('option', { name: 'Gotify' })).toBeInTheDocument();
4849
fireEvent.change(screen.getByLabelText('渠道'), { target: { value: 'custom' } });
4950
fireEvent.click(screen.getByRole('button', { name: // }));
5051

apps/dsa-web/src/locales/settingsHelp.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,23 @@ const settingsHelpZhCN: SettingsHelpMap = {
8181
'如果飞书侧配置 IP 白名单,需要确认当前运行环境出口 IP 已加入白名单。',
8282
],
8383
},
84+
'settings.notification.CUSTOM_WEBHOOK_URLS': {
85+
title: '自定义 Webhook',
86+
summary: '配置任意支持 POST JSON 的通知端点,可用于钉钉、Bark、Slack、Discord 或自建服务。',
87+
usage: '多个 URL 使用英文逗号分隔。Bark 可直接填写 https://api.day.app/YOUR_BARK_KEY。',
88+
valueNotes: [
89+
'未配置 CUSTOM_WEBHOOK_BODY_TEMPLATE 时,系统会按 URL 类型自动生成常见 payload。',
90+
'配置全局 Body 模板后,会覆盖 Bark、Slack、Discord 等自动 payload。',
91+
'需要认证的通用 webhook 可搭配 CUSTOM_WEBHOOK_BEARER_TOKEN。',
92+
],
93+
impact: [
94+
'影响 custom 通知渠道;单个 URL 失败不会阻断其他 URL 或主分析流程。',
95+
],
96+
notes: [
97+
'Bark 仍作为 custom webhook 使用,不需要新增 BARK_* 配置。',
98+
'自签名内网端点可评估 WEBHOOK_VERIFY_SSL=false,但不要用于公网链路。',
99+
],
100+
},
84101
'settings.system.WEBUI_HOST': {
85102
title: 'WebUI 监听地址',
86103
summary: '控制 WebUI 服务绑定在哪个网络地址上。',
@@ -159,6 +176,23 @@ const settingsHelpEnUS: SettingsHelpMap = {
159176
'If IP allowlisting is enabled in Feishu, add the outbound IP of your runtime environment.',
160177
],
161178
},
179+
'settings.notification.CUSTOM_WEBHOOK_URLS': {
180+
title: 'Custom Webhook',
181+
summary: 'Sends notifications to any endpoint that accepts POST JSON, such as DingTalk, Bark, Slack, Discord, or a self-hosted service.',
182+
usage: 'Separate multiple URLs with commas. For Bark, use https://api.day.app/YOUR_BARK_KEY.',
183+
valueNotes: [
184+
'Without CUSTOM_WEBHOOK_BODY_TEMPLATE, the sender auto-builds payloads for known URL types.',
185+
'A global body template overrides auto-detected payloads for Bark, Slack, Discord, and similar URLs.',
186+
'Use CUSTOM_WEBHOOK_BEARER_TOKEN for generic webhook endpoints that require bearer auth.',
187+
],
188+
impact: [
189+
'Affects the custom notification channel only; one URL failure does not block other URLs or the analysis flow.',
190+
],
191+
notes: [
192+
'Bark stays on the custom webhook baseline and does not use BARK_* settings.',
193+
'Only consider WEBHOOK_VERIFY_SSL=false for trusted internal self-signed endpoints, not public routes.',
194+
],
195+
},
162196
'settings.system.WEBUI_HOST': {
163197
title: 'WebUI Host',
164198
summary: 'Controls the network address the WebUI service binds to.',

apps/dsa-web/src/types/systemConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ export type NotificationTestChannel =
198198
| 'email'
199199
| 'pushover'
200200
| 'ntfy'
201+
| 'gotify'
201202
| 'pushplus'
202203
| 'serverchan3'
203204
| 'custom'

apps/dsa-web/src/utils/systemConfigI18n.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,12 @@ const fieldTitleMap: Record<string, string> = {
6262
FEISHU_APP_SECRET: '飞书应用 App Secret',
6363
DINGTALK_APP_KEY: '钉钉 App Key',
6464
DINGTALK_APP_SECRET: '钉钉 App Secret',
65+
CUSTOM_WEBHOOK_URLS: '自定义 Webhook 地址',
6566
CUSTOM_WEBHOOK_BODY_TEMPLATE: '自定义 Webhook Body 模板',
67+
NTFY_URL: 'ntfy URL',
68+
NTFY_TOKEN: 'ntfy Token',
69+
GOTIFY_URL: 'Gotify URL',
70+
GOTIFY_TOKEN: 'Gotify Token',
6671
PUSHPLUS_TOKEN: 'PushPlus Token',
6772
REPORT_SUMMARY_ONLY: '仅分析结果摘要',
6873
MAX_WORKERS: '最大并发线程数',
@@ -128,7 +133,12 @@ const fieldDescriptionMap: Record<string, string> = {
128133
FEISHU_APP_SECRET: '仅用于飞书应用机器人 / Stream Bot / 云文档等应用模式,不会直接开启群 Webhook 推送。',
129134
DINGTALK_APP_KEY: '钉钉应用模式 App Key。',
130135
DINGTALK_APP_SECRET: '钉钉应用模式 App Secret。',
136+
CUSTOM_WEBHOOK_URLS: '自定义通知端点,多个用英文逗号分隔;Bark 可直接填写 https://api.day.app/YOUR_BARK_KEY。',
131137
CUSTOM_WEBHOOK_BODY_TEMPLATE: '全局 JSON body 模板,会先于 Bark、Slack、Discord 等自动 payload 生效;推荐使用 $content_json / $title_json,裸 $content / $title 不做 JSON 转义。',
138+
NTFY_URL: 'ntfy 完整 topic endpoint,必须包含 topic path,例如 https://ntfy.sh/my-topic。',
139+
NTFY_TOKEN: 'ntfy Bearer Token;公开 topic 可留空。',
140+
GOTIFY_URL: 'Gotify server base URL,不包含 /message;系统发送时会自动拼接 /message。',
141+
GOTIFY_TOKEN: 'Gotify application token,系统通过 X-Gotify-Key Header 发送,不会放进 URL。',
132142
PUSHPLUS_TOKEN: 'PushPlus 推送令牌。',
133143
REPORT_SUMMARY_ONLY: '仅推送分析结果摘要,不包含个股详情。多股时适合快速浏览。',
134144
MAX_WORKERS: '异步任务队列最大并发数。配置保存后,队列空闲时会自动应用;繁忙时延后生效。',

docs/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
1212
<!-- 新条目格式:- [类型] 描述(类型取值:新功能/改进/修复/文档/测试/chore)-->
1313
<!-- 每条独立一行追加到本段末尾,无需分类标题,合并时冲突最小 -->
1414
- [新功能] 通知网关新增 ntfy 一等渠道,支持通过 `NTFY_URL` / `NTFY_TOKEN` 推送并接入 Web 测试、路由、Actions 与诊断。
15+
- [新功能] 通知网关新增 Gotify 一等渠道,支持通过 `GOTIFY_URL` / `GOTIFY_TOKEN` 推送 Markdown 文本并接入 Web 测试、路由、Actions 与诊断。
16+
- [修复] 收紧 ntfy 结构化校验,避免 URL 编码空白 topic 被误判为有效通知端点。
17+
- [文档] 补充 Bark custom webhook 示例和 WebPush / Apprise 通知渠道评估,明确本轮不新增运行时依赖或配置入口。
1518
- [修复] 聚合报告通知按静态渠道隔离发送失败,并补充自定义 Webhook 部分成功诊断与脱敏测试。
1619
- [修复] 未配置 Tushare / Longbridge 凭据时不再实例化对应可选 fetcher,避免缺失凭据的数据源进入候选集。
1720
- [修复] Longbridge 遇到连接关闭类异常后会进入冷却期,并在美股/港股实时与日线请求中临时跳过该数据源,避免请求级频繁重连。

docs/full-guide.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,16 @@ daily_stock_analysis/
9797
| `ASTRBOT_TOKEN` | AstrBot Bearer Token(可选) | 可选 |
9898
| `NTFY_URL` | ntfy 完整 topic endpoint,必须包含 topic path,例如 `https://ntfy.sh/my-topic` | 可选 |
9999
| `NTFY_TOKEN` | ntfy Bearer Token(可选) | 可选 |
100+
| `GOTIFY_URL` | Gotify server base URL,不包含 `/message`;系统会自动拼接 `/message` | 可选 |
101+
| `GOTIFY_TOKEN` | Gotify application token,通过 `X-Gotify-Key` Header 发送 | 可选 |
100102
| `CUSTOM_WEBHOOK_URLS` | 自定义 Webhook(支持钉钉等,多个用逗号分隔) | 可选 |
101103
| `CUSTOM_WEBHOOK_BEARER_TOKEN` | 自定义 Webhook 的 Bearer Token(用于需要认证的 Webhook) | 可选 |
102104
| `CUSTOM_WEBHOOK_BODY_TEMPLATE` | 自定义 Webhook JSON body 模板,适配 AstrBot、NapCat、自建服务等特殊 payload | 可选 |
103105
| `WEBHOOK_VERIFY_SSL` | 读取该配置的 webhook-style HTTPS 通知请求证书校验(默认 true)。设为 false 可支持自签名证书。警告:关闭有严重安全风险(MITM),仅限可信内网 | 可选 |
104106

105107
> *注:至少配置一个渠道,配置多个则同时推送
106108
>
107-
> 当前默认 `daily_analysis.yml` 只显式映射固定 Secret / Variable 名称,不会自动把 `STOCK_GROUP_1``EMAIL_GROUP_1` 这类任意编号变量导入运行环境。所以分组邮箱功能目前不适用于仓库自带默认 GitHub Actions workflow;它适用于本地 `.env`、Docker,或你自行显式扩展过 `env:` 映射的运行环境。Actions 已显式映射 `CUSTOM_WEBHOOK_BODY_TEMPLATE``WEBHOOK_VERIFY_SSL``FEISHU_WEBHOOK_SECRET``FEISHU_WEBHOOK_KEYWORD``PUSHPLUS_TOPIC``NTFY_URL``NTFY_TOKEN`、P3 通知路由键以及 P4 通知降噪键;`MARKDOWN_TO_IMAGE_CHANNELS``MERGE_EMAIL_NOTIFICATION` 仍作为行为开关不在默认 workflow 中自动映射。
109+
> 当前默认 `daily_analysis.yml` 只显式映射固定 Secret / Variable 名称,不会自动把 `STOCK_GROUP_1``EMAIL_GROUP_1` 这类任意编号变量导入运行环境。所以分组邮箱功能目前不适用于仓库自带默认 GitHub Actions workflow;它适用于本地 `.env`、Docker,或你自行显式扩展过 `env:` 映射的运行环境。Actions 已显式映射 `CUSTOM_WEBHOOK_BODY_TEMPLATE``WEBHOOK_VERIFY_SSL``FEISHU_WEBHOOK_SECRET``FEISHU_WEBHOOK_KEYWORD``PUSHPLUS_TOPIC``NTFY_URL``NTFY_TOKEN``GOTIFY_URL``GOTIFY_TOKEN`P3 通知路由键以及 P4 通知降噪键;`MARKDOWN_TO_IMAGE_CHANNELS``MERGE_EMAIL_NOTIFICATION` 仍作为行为开关不在默认 workflow 中自动映射。
108110
109111
#### 推送行为配置
110112

@@ -264,11 +266,13 @@ daily_stock_analysis/
264266
| `PUSHOVER_API_TOKEN` | Pushover API Token | 可选 |
265267
| `NTFY_URL` | ntfy 完整 topic endpoint,必须包含 topic path,例如 `https://ntfy.sh/my-topic` | 可选 |
266268
| `NTFY_TOKEN` | ntfy Bearer Token(可选) | 可选 |
269+
| `GOTIFY_URL` | Gotify server base URL,不包含 `/message` | 可选 |
270+
| `GOTIFY_TOKEN` | Gotify application token,通过 `X-Gotify-Key` Header 发送 | 可选 |
267271
| `PUSHPLUS_TOKEN` | PushPlus Token(国内推送服务) | 可选 |
268272
| `SERVERCHAN3_SENDKEY` | Server酱³ Sendkey | 可选 |
269273
| `ASTRBOT_URL` | AstrBot Webhook URL | 可选 |
270274
| `ASTRBOT_TOKEN` | AstrBot Bearer Token(可选) | 可选 |
271-
| `NOTIFICATION_REPORT_CHANNELS` | report 路由渠道,逗号分隔;允许值:wechat,feishu,telegram,email,pushover,ntfy,pushplus,serverchan3,custom,discord,slack,astrbot | 可选 |
275+
| `NOTIFICATION_REPORT_CHANNELS` | report 路由渠道,逗号分隔;允许值:wechat,feishu,telegram,email,pushover,ntfy,gotify,pushplus,serverchan3,custom,discord,slack,astrbot | 可选 |
272276
| `NOTIFICATION_ALERT_CHANNELS` | alert 路由渠道,逗号分隔;留空保持全渠道 | 可选 |
273277
| `NOTIFICATION_SYSTEM_ERROR_CHANNELS` | system_error 预留路由渠道,逗号分隔;留空保持全渠道 | 可选 |
274278
| `NOTIFICATION_DEDUP_TTL_SECONDS` | 通知去重 TTL 秒数,`0` 关闭 | 可选 |
@@ -794,6 +798,32 @@ NapCat / OneBot 示例需按实际 endpoint、`user_id` 或 `group_id` 调整:
794798
CUSTOM_WEBHOOK_BODY_TEMPLATE={"user_id":123456,"message":$content_json}
795799
```
796800

801+
### ntfy / Gotify
802+
803+
ntfy 和 Gotify 都是一等通知渠道,只发送文本 / JSON,不参与 Markdown 转图片。
804+
805+
ntfy 使用完整 topic endpoint,最后一个 path segment 会作为 topic:
806+
807+
```env
808+
NTFY_URL=https://ntfy.sh/my-topic
809+
NTFY_TOKEN=
810+
```
811+
812+
Gotify 使用 server base URL,系统会自动拼接固定 `/message` API,并通过 `X-Gotify-Key` Header 发送 application token。`GOTIFY_URL` 可包含反向代理 path prefix,但不要包含 `/message`:
813+
814+
```env
815+
GOTIFY_URL=https://gotify.example
816+
GOTIFY_TOKEN=app-token
817+
```
818+
819+
```env
820+
# 实际请求会发送到 https://example.com/gotify/message
821+
GOTIFY_URL=https://example.com/gotify
822+
GOTIFY_TOKEN=app-token
823+
```
824+
825+
`NTFY_URL` 与 `GOTIFY_URL` 的语义不同是两个服务 API 设计不同导致的刻意选择:ntfy 由用户 topic 构成 endpoint,Gotify 的 `/message` 是固定服务 API。
826+
797827
### Discord
798828

799829
Discord 支持两种方式推送:

0 commit comments

Comments
 (0)