Skip to content

refactor(notify): 新增通知中间层, 8 个脚本渠道扇出去重 - #417

Open
1w1w11w1 wants to merge 1 commit into
devfrom
refactor/notify-middle-layer
Open

refactor(notify): 新增通知中间层, 8 个脚本渠道扇出去重#417
1w1w11w1 wants to merge 1 commit into
devfrom
refactor/notify-middle-layer

Conversation

@1w1w11w1

@1w1w11w1 1w1w11w1 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

摘要

  • 新增 app/services/notify_dispatch.py 作为通知中间层承接渠道扇出:NotifyPayload 描述「一份已渲染的报告」,NotifyTarget 描述「推给谁」。用户级与脚本级报告的差异收敛成一个 targets 列表,8 个脚本的 tools/notify.py 只保留自己独有的正文构造与模板选择,共减少 863 行、新增 338 行。
  • 修复单渠道失败中断后续渠道的问题:此前只有 M9A 做了失败隔离,其余 7 个脚本任一渠道抛异常会导致后面的渠道全部不发。
  • 修复推送失败时签到汇总丢失的问题:push_notification 改为返回失败渠道列表,8 个管理器据此决定是否消费签到汇总,不再在发送失败后把汇总误标为已推送。

测试

以 characterization test 兜底(tests/task/test_notify_channels_parity.py):录制 8 脚本 × 10 场景 × 5 mode 下对各渠道的调用序列,与重构前的基线逐字节比对。413 项完全不变,21 项差异全部落在 _channel_failure,即上述有意变更的失败隔离行为;M9A 不在差异列表中,印证它原本就有隔离。

已运行:tests/task/test_notify_channels_parity.pytests/services/test_notification.pytests/task/test_okww_manual_stop_history.pytests/task/test_maa_statistics.py —— 13 passed。

tests/tools/test_game_sign_notification.py 有 6 项失败,与本 PR 无关:origin/devappend_task_game_sign_summary(task_info, result) 的签名与其测试传的 uncompleted_count= 不符,已在 origin/dev 的干净检出上复现同样的 6 项失败,本 PR 未改动这两个文件。

未包含

前端仍有一份同构的重复(4 份近乎相同的 NotifyConfigSection.vue + General/Okww/OkNte 三份内联副本;HSR 后端配置齐全但没有通知 UI;除 HSRUserConfig_Notify 外 7 个用户 Notify schema 漏了 CustomWebhooks;用户级 webhook 没有 test 端点)。与后端解耦,留作后续 PR。

Sourcery 摘要

在所有脚本之间集中处理通知发送,同时改进故障隔离,防止推送失败导致登录摘要丢失。

新功能:

  • 为全部八个脚本中的全局目标和用户目标引入共享通知分发层。
  • 返回发送失败的通知渠道,使调用方在通知未完整送达时避免消费登录摘要。

错误修复:

  • 隔离通知渠道故障,使某个渠道失败时不会再阻止后续渠道尝试发送。
  • 当任意通知渠道失败时,保留登录摘要以便重试。

增强功能:

  • 整合重复的通知扇出、格式化、签名、收件人处理和发送时机逻辑,同时保留脚本特定的报告渲染方式和历史行为。
  • 通过覆盖脚本、场景和模式的特征测试,保持通知渠道的一致性。

测试:

  • 添加通知一致性基线和测试,覆盖八个脚本、多种配置、模式以及渠道失败行为。
Original summary in English

Summary by Sourcery

Centralize notification delivery across all scripts while improving failure isolation and preventing failed pushes from losing sign-in summaries.

New Features:

  • Introduce a shared notification dispatch layer for global and user targets across all eight scripts.
  • Return failed notification channels so callers can avoid consuming sign-in summaries when delivery is incomplete.

Bug Fixes:

  • Isolate notification channel failures so one failed channel no longer prevents subsequent channels from being attempted.
  • Preserve sign-in summaries for retry when any notification channel fails.

Enhancements:

  • Consolidate duplicated notification fan-out, formatting, signing, recipient handling, and send-timing logic while preserving script-specific report rendering and historical behavior.
  • Preserve notification-channel parity with characterization coverage across scripts, scenarios, and modes.

Tests:

  • Add notification parity baselines and tests covering eight scripts, multiple configurations, modes, and channel-failure behavior.

新增 app/services/notify_dispatch.py 承接渠道扇出: NotifyPayload 只描述
「一份已渲染的报告」, NotifyTarget 描述「推给谁」, 用户级与脚本级的差异
收敛成 targets 列表, 各脚本只保留自己独有的正文构造与模板选择。

顺带修掉两处行为问题:
- 单渠道失败不再中断后续渠道 (此前仅 M9A 有隔离, 其余 7 个脚本一炸全停)
- push_notification 返回失败渠道列表, 管理器据此决定是否消费签到汇总,
  避免推送失败时汇总被误标为已发送而丢失

以 characterization test 兜底: 8 脚本 x 10 场景 x 5 mode 的渠道调用序列
与重构前逐字节比对, 413 项不变, 21 项差异全部落在 _channel_failure,
即上述有意变更的失败隔离行为。

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @1w1w11w1, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 2 days and 10 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Aug 25, 2026

Copy link
Copy Markdown

审查者指南

本 PR 新增通知分发中间层,将 8 个脚本重复的渠道扇出、格式转换和错误处理集中复用,同时保留各脚本正文与模板差异;通知入口现返回失败渠道列表,管理器据此避免在部分发送失败时丢失签到汇总,并以跨脚本 characterization baseline 验证非预期行为未变。

隔离通知渠道失败的时序图

sequenceDiagram
    participant Manager
    participant NotifyTool
    participant Dispatch as notify_dispatch
    participant Mail
    participant ServerChan
    participant Webhook

    Manager->>NotifyTool: push_notification
    NotifyTool->>Dispatch: dispatch(payload, targets)
    Dispatch->>Mail: send_mail
    Mail-->>Dispatch: failure
    Dispatch->>ServerChan: ServerChanPush
    ServerChan-->>Dispatch: success
    Dispatch->>Webhook: WebhookPush
    Webhook-->>Dispatch: success
    Dispatch-->>NotifyTool: failed channel list
    NotifyTool-->>Manager: failed channel list
Loading

通知失败后保留签到汇总的时序图

sequenceDiagram
    participant Manager
    participant NotifyTool
    participant Dispatch as notify_dispatch
    participant Channels
    participant Summary

    Manager->>NotifyTool: push_notification
    NotifyTool->>Dispatch: dispatch(payload, targets)
    Dispatch->>Channels: send channels independently
    Channels-->>Dispatch: failed channel list
    Dispatch-->>NotifyTool: failed channel list
    NotifyTool-->>Manager: failed channel list
    alt failed channel list is empty
        Manager->>Summary: mark_task_game_sign_summary_consumed
    else channel failure
        Manager-->>Summary: retain summary for a later report
    end
Loading

文件级变更

变更 详情 文件
集中实现通知目标建模、渠道扇出与消息格式转换,并在单渠道失败时继续发送后续渠道。
  • 新增 NotifyPayload、NotifyTarget 及全局/用户目标构造器
  • 统一处理邮件、ServerChan、自定义 Webhook、Koishi 的发送、签名和空配置策略
  • 捕获单渠道异常并返回失败渠道列表
app/services/notify_dispatch.py
将 8 个脚本的通知入口精简为正文构造、模板选择和目标选择,并统一返回发送失败结果。
  • 复用中间层处理代理结果、统计信息及 MAA 六星通知
  • 保留各脚本独有的正文格式、模板和签名换行差异
  • 统一通知时机判断及全局/用户统计目标组合
app/task/HSR/tools/notify.py
app/task/M9A/tools/notify.py
app/task/MAA/tools/notify.py
app/task/MaaEnd/tools/notify.py
app/task/OkNte/tools/notify.py
app/task/Okww/tools/notify.py
app/task/SRC/tools/notify.py
app/task/general/tools/notify.py
避免通知部分失败时消费签到汇总,使未完整送达的汇总能够随下一份报告重发。
  • 各脚本管理器根据 push_notification 返回的失败渠道列表决定是否标记签到汇总已消费
  • 覆盖 HSR、M9A、MAA、MaaEnd、OkNte、Okww、SRC 和 general
app/task/HSR/manager.py
app/task/M9A/manager.py
app/task/MAA/manager.py
app/task/MaaEnd/manager.py
app/task/OkNte/manager.py
app/task/Okww/manager.py
app/task/SRC/manager.py
app/task/general/manager.py
增加跨脚本通知行为表征测试,验证重构后渠道调用序列与历史基线保持一致。
  • 覆盖 8 个脚本、10 个配置场景和多个通知模式
  • 记录渠道调用顺序及参数,并单独验证渠道失败隔离行为
  • 提供受控的基线生成脚本
tests/task/test_notify_channels_parity.py
tests/task/regen_notify_baseline.py
tests/data/notify_parity_baseline.json
更新版本元数据。
  • 递增版本信息
res/version.json

提示与命令

与 Sourcery 交互

  • 触发新的审查: 在拉取请求中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 根据审查评论生成 GitHub issue: 回复审查评论,请 Sourcery 根据该评论创建 issue。你也可以在审查评论中回复 @sourcery-ai issue,以根据该评论创建 issue。
  • 生成拉取请求标题: 在拉取请求标题的任意位置输入 @sourcery-ai,即可随时生成标题。你也可以在拉取请求中评论 @sourcery-ai title,以随时生成或重新生成标题。
  • 生成拉取请求摘要: 在拉取请求正文的任意位置输入 @sourcery-ai summary,即可在指定位置随时生成 PR 摘要。你也可以在拉取请求中评论 @sourcery-ai summary,以随时生成或重新生成摘要。
  • 生成审查者指南: 在拉取请求中评论 @sourcery-ai guide,即可随时生成或重新生成审查者指南。
  • 解决所有 Sourcery 评论: 在拉取请求中评论 @sourcery-ai resolve,即可解决所有 Sourcery 评论。如果你已经处理完所有评论且不想再看到它们,这会很有用。
  • 忽略所有 Sourcery 审查: 在拉取请求中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审查。如果你想从新的审查开始,这尤其有用——别忘了评论 @sourcery-ai review 来触发新的审查!

自定义你的体验

访问你的控制面板

  • 启用或禁用审查功能,例如 Sourcery 生成的拉取请求摘要、审查者指南等。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查说明。
  • 调整其他审查设置。

获取帮助

Original review guide in English

Reviewer's Guide

本 PR 新增通知分发中间层,将 8 个脚本重复的渠道扇出、格式转换和错误处理集中复用,同时保留各脚本正文与模板差异;通知入口现返回失败渠道列表,管理器据此避免在部分发送失败时丢失签到汇总,并以跨脚本 characterization baseline 验证非预期行为未变。

Sequence diagram for isolated notification channel failures

sequenceDiagram
    participant Manager
    participant NotifyTool
    participant Dispatch as notify_dispatch
    participant Mail
    participant ServerChan
    participant Webhook

    Manager->>NotifyTool: push_notification
    NotifyTool->>Dispatch: dispatch(payload, targets)
    Dispatch->>Mail: send_mail
    Mail-->>Dispatch: failure
    Dispatch->>ServerChan: ServerChanPush
    ServerChan-->>Dispatch: success
    Dispatch->>Webhook: WebhookPush
    Webhook-->>Dispatch: success
    Dispatch-->>NotifyTool: failed channel list
    NotifyTool-->>Manager: failed channel list
Loading

Sequence diagram for preserving sign-in summaries after notification failure

sequenceDiagram
    participant Manager
    participant NotifyTool
    participant Dispatch as notify_dispatch
    participant Channels
    participant Summary

    Manager->>NotifyTool: push_notification
    NotifyTool->>Dispatch: dispatch(payload, targets)
    Dispatch->>Channels: send channels independently
    Channels-->>Dispatch: failed channel list
    Dispatch-->>NotifyTool: failed channel list
    NotifyTool-->>Manager: failed channel list
    alt failed channel list is empty
        Manager->>Summary: mark_task_game_sign_summary_consumed
    else channel failure
        Manager-->>Summary: retain summary for a later report
    end
Loading

File-Level Changes

Change Details Files
集中实现通知目标建模、渠道扇出与消息格式转换,并在单渠道失败时继续发送后续渠道。
  • 新增 NotifyPayload、NotifyTarget 及全局/用户目标构造器
  • 统一处理邮件、ServerChan、自定义 Webhook、Koishi 的发送、签名和空配置策略
  • 捕获单渠道异常并返回失败渠道列表
app/services/notify_dispatch.py
将 8 个脚本的通知入口精简为正文构造、模板选择和目标选择,并统一返回发送失败结果。
  • 复用中间层处理代理结果、统计信息及 MAA 六星通知
  • 保留各脚本独有的正文格式、模板和签名换行差异
  • 统一通知时机判断及全局/用户统计目标组合
app/task/HSR/tools/notify.py
app/task/M9A/tools/notify.py
app/task/MAA/tools/notify.py
app/task/MaaEnd/tools/notify.py
app/task/OkNte/tools/notify.py
app/task/Okww/tools/notify.py
app/task/SRC/tools/notify.py
app/task/general/tools/notify.py
避免通知部分失败时消费签到汇总,使未完整送达的汇总能够随下一份报告重发。
  • 各脚本管理器根据 push_notification 返回的失败渠道列表决定是否标记签到汇总已消费
  • 覆盖 HSR、M9A、MAA、MaaEnd、OkNte、Okww、SRC 和 general
app/task/HSR/manager.py
app/task/M9A/manager.py
app/task/MAA/manager.py
app/task/MaaEnd/manager.py
app/task/OkNte/manager.py
app/task/Okww/manager.py
app/task/SRC/manager.py
app/task/general/manager.py
增加跨脚本通知行为表征测试,验证重构后渠道调用序列与历史基线保持一致。
  • 覆盖 8 个脚本、10 个配置场景和多个通知模式
  • 记录渠道调用顺序及参数,并单独验证渠道失败隔离行为
  • 提供受控的基线生成脚本
tests/task/test_notify_channels_parity.py
tests/task/regen_notify_baseline.py
tests/data/notify_parity_baseline.json
更新版本元数据。
  • 递增版本信息
res/version.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant