Skip to content

feat: 增加全国气象预警对账补偿 - #144

Open
SunmiJJW wants to merge 6 commits into
Pancakes-Labs:mainfrom
SunmiJJW:codex/cma-weather-reconciliation
Open

feat: 增加全国气象预警对账补偿#144
SunmiJJW wants to merge 6 commits into
Pancakes-Labs:mainfrom
SunmiJJW:codex/cma-weather-reconciliation

Conversation

@SunmiJJW

@SunmiJJW SunmiJJW commented Jul 12, 2026

Copy link
Copy Markdown

📝 描述 / Description

FAN Studio 气象 WebSocket 当前只提供单条最新快照;多个地区在同一采集周期内连续发布预警时,中间事件可能在进入 AstrBot 前被覆盖。

本 PR 增加一个默认关闭、全国通用的中国天气网活动预警对账源。它不替换 FAN 实时流,也不针对上海或任何单一地区写特殊规则。

Closes #143

🛠️ 改动点 / Modifications

  • 新增中国天气网紧凑活动预警索引与详情解析,按官方标识、灾种和等级重建 FAN 兼容事件 ID。

  • 首次成功快照仅建立基线;后续只抓取新官方 ID 的详情。

  • 继续复用 china_weather_fanstudio 的解析、过滤、展示、统计和发送链。

  • 新增 24 小时、最多 4096 条的气象事件 ID 缓存,抑制 FAN 与 HTTP 到达顺序造成的重复推送。

  • 详情校验、下载或解析失败会隔离并在下一轮重试;一旦进入现有发送链,本层按最多一次语义处理,避免部分发送后的重复。

  • 严格限制详情路径,拒绝协议、主机、绝对路径、目录穿越、查询参数、片段和编码路径。

  • 新增默认关闭的 weather_alarm_fallback 配置,轮询、超时和并发均有上下界。

  • 保留既有 Wolfx 任务和 FAN WebSocket 行为;未启用配置时不创建对账任务。

  • 不是一个破坏性变更 / This is NOT a breaking change.

📸 运行截图或测试结果 / Screenshots or Test Results

python -m unittest discover -s tests -v
Ran 34 tests in 1.301s
OK

python -m compileall -q .
python -m uv tool run ruff==0.14.2 format --check .
211 files already formatted

python -m uv tool run ruff==0.14.2 check .
All checks passed!

额外验证:

  • _conf_schema.json 可正常解析。
  • 使用真实 AstrBot 环境完成服务模块导入烟测,默认配置保持关闭。
  • 工作站与香港主机对公开索引和一条详情进行只读请求,均返回 HTTP 200。
  • 真实详情可规范化为 FAN 兼容事件 ID、颜色编码、时间、标题、正文和坐标。
  • 全过程未发送测试消息,也未修改线上 AstrBot 配置。

✅ 检查清单 / Checklist

  • 😊 新功能已通过 Issue [Feature] 为 FAN 气象预警增加全国活动预警对账补偿 #143 讨论。
  • 👀 更改已完成单元测试、Ruff、编译、真实 AstrBot 导入和只读端点验证。
  • 🤓 没有引入新依赖;HTTP 客户端复用项目已有的 aiohttp
  • 😮 更改没有引入恶意代码。
  • 🥳 我已阅读并同意遵守项目贡献指南。

Summary by Sourcery

添加一个可选的全国级“中国天气”对账管线,用于补充现有的 CMA 预警,扩展天气 ID 去重能力,并记录新的回退行为和配置。

新特性:

  • 引入“中国天气”对账服务,在启用时轮询紧凑的全国活动预警索引,并通过现有的天气事件管线分发规范化后的详情。
  • 添加可配置的运行时选项 weather_alarm_fallback,为对账循环设置受限的轮询间隔、请求超时和详情并发度。
  • 实现一个对天气事件 ID 进行 24 小时有界去重的缓存,用于在 WebSocket 和 HTTP 来源之间持续抑制重复预警。

增强:

  • 强化“中国天气”详情 URL 的处理逻辑,通过严格校验在网络访问前拒绝不安全路径和格式错误的标识符。

文档:

  • 在 README 中记录可选的全国级“中国天气”活动预警对账数据源、其配置方式以及与现有 CMA FAN Studio 预警的关系。
  • 在变更日志中记录新的对账功能以及扩展后的天气 ID 去重缓存。

测试:

  • 添加针对“中国天气”对账基础组件、配置钳制、去重行为、URL 安全性检查、运行时循环控制,以及与现有天气解析器和运行时集成的全面单元测试。
Original summary in English

Summary by Sourcery

Add an optional nationwide China Weather reconciliation pipeline to complement existing CMA alerts, expanding weather ID deduplication and documenting the new fallback behaviour and configuration.

New Features:

  • Introduce a China Weather reconciliation service that polls compact national activity warning indexes and dispatches normalized details through the existing weather event pipeline when enabled.
  • Add a configurable weather_alarm_fallback runtime option, with bounded polling interval, request timeout, and detail concurrency for the reconciliation loop.
  • Implement a 24-hour bounded deduplication cache for weather event IDs to consistently suppress duplicate alerts across WebSocket and HTTP sources.

Enhancements:

  • Harden China Weather detail URL handling with strict validation to reject unsafe paths and malformed identifiers before network access.

Documentation:

  • Document the optional China Weather nationwide activity warning reconciliation source, its configuration, and its relationship to existing CMA FAN Studio alerts in the README.
  • Record the new reconciliation feature and extended weather ID dedup cache in the changelog.

Tests:

  • Add comprehensive unit tests for China Weather reconciliation primitives, configuration clamping, deduplication behaviour, URL safety checks, runtime loop control, and integration with the existing weather parser and runtime.

Summary by CodeRabbit

  • 新功能
    • 新增中国天气网全国活动预警回退对账(默认关闭):定时轮询、增量详情抓取、事件 ID 有界去重与派发。
  • 问题修复
    • 统一发布时间解析与预警编码规范化,修复图标/灾种展示错误;失败隔离后支持下一周期重试,详情路径安全校验加强。
  • 文档
    • 补充回退配置与延迟口径说明。
  • 测试
    • 增加解析、去重/TTL、回退调度与并发/取消行为测试。

@dosubot dosubot Bot added the size:XL 修改了 500-999 行代码 (忽略生成文件) label Jul 12, 2026
@sourcery-ai

sourcery-ai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

添加一个可选的全国范围“中国天气”对账(reconciliation)流水线:轮询紧凑预警索引,将详细载荷规范化为与 FAN 兼容的天气事件,并在具有稳健去重和安全检查的前提下,将其注入现有的 china_weather_fanstudio 流程。

China Weather 对账轮询与分发的时序图

sequenceDiagram
    participant Runtime as DisasterServiceRuntimeService
    participant Reconciler as ChinaWeatherReconciler
    participant HTTP as aiohttp_ClientSession
    participant Parser as WeatherAlarmParser
    participant Pipeline as DisasterEventPipeline

    Runtime->>Runtime: start_scheduled_http_fetch()
    Runtime->>Runtime: _run_china_weather_loop(fallback_config)
    Runtime->>HTTP: ClientSession(timeout, headers)
    loop every poll_interval_seconds while service.running
        Runtime->>HTTP: fetch_text(_CHINA_WEATHER_INDEX_URL)
        HTTP-->>Runtime: index_script
        Runtime->>Reconciler: reconcile(index_script, fetch_detail, _dispatch_china_weather_payload)
        Reconciler->>HTTP: fetch_detail(detail_path)
        HTTP-->>Reconciler: detail_script
        Reconciler->>Reconciler: parse_warning_detail(detail_script, reference)
        Reconciler->>Runtime: _dispatch_china_weather_payload(payload)
        Runtime->>Parser: parse_event("china_weather_fanstudio", json.dumps(payload))
        Parser-->>Runtime: event
        Runtime->>Pipeline: _handle_disaster_event(event)
    end
Loading

File-Level Changes

Change Details Files
将一个可选的 China Weather 对账轮询循环接入灾害运行时,由配置和现有数据源启用状态进行控制。
  • 在灾害运行时服务中导入 aiohttp 和新的 China Weather 对账原语。
  • 从顶层服务配置中解析 WeatherFallbackConfig,限定轮询间隔、超时时间和并发度的边界。
  • 仅在 fallback 启用且 china_weather_fanstudio 数据源处于激活状态时启动一个命名的 China Weather HTTP 任务。
  • 实现 _run_china_weather_loop,维护一个 aiohttp 会话,以配置的间隔轮询公共 China Weather 索引,并使用索引脚本、详情获取器和分发回调调用对账器。
  • 添加 _dispatch_china_weather_payload,通过 china_weather_fanstudio 解析器解析对账后的载荷,并仅一次性注入现有的灾害事件流水线。
  • 定义 China Weather 索引 URL、详情基准 URL 以及必需的 HTTP 头(User-Agent 和 Referer)的常量。
core/app/runtime/disaster_service_runtime.py
引入纯粹的 China Weather 对账服务,包含索引/详情解析、事件 ID 重建、去重和安全的详情路径校验。
  • 在新的 china_weather_reconciliation 模块中创建 WeatherFallbackConfig、WarningReference、WarningSnapshotTracker、BoundedTTLSet、ReconciliationCycleResult 和 ChinaWeatherReconciler。
  • 实现 resolve_fallback_config,读取 weather_alarm_fallback,对数值边界进行钳制,并暴露不可变配置 dataclass。
  • 将紧凑索引脚本解析为 WarningReference 列表,拒绝格式错误的载荷或行,并支持空快照。
  • 将详情脚本解析为与 FAN 兼容的载荷,包括类型/等级代码规范化、严重程度颜色映射、标题/名称/内容提取、坐标以及传输元数据。
  • 校验和规范预警标识符为 FAN 风格的事件 ID,强制时间戳结构并进行基本合理性检查。
  • 实现 WarningSnapshotTracker,在获得一个有效索引后进行预热,并在后续只发出新的标识符,同时限制存储快照大小。
  • 实现 BoundedTTLSet,用于跟踪已处理事件 ID,并基于 TTL 过期和容量限制进行管理。
  • 实现 ChinaWeatherReconciler.reconcile,识别新的引用,以受限并发度获取/解析详情,对每个引用调用一次下游分发,并报告新增/已消费/失败的标识符;将详情失败视为可重试,将分发返回值/异常视为“至多一次”消费语义。
  • 实现 validate_detail_path,严格仅接受安全的、未编码的相对文件名,并拒绝 URL、目录遍历、嵌套路径、反斜杠、查询、片段以及不允许的字符。
core/services/weather/china_weather_reconciliation.py
将天气解析器的去重扩展为与 HTTP 对账共享的有界 TTL 集合,同时保持现有 china_weather_fanstudio 的解析行为。
  • 用配置为 24 小时 TTL 和最多 4096 条目的 BoundedTTLSet 替换 WeatherAlarmParser 基于 deque 的缓存。
  • 使用新缓存的添加和成员语义,过滤 FAN WebSocket 与 HTTP 对账流中的重复事件 ID。
  • 更新行内注释以反映缓存语义(从队列到缓存)。
core/parsers/weather_parser.py
通过天气服务包暴露对账原语,以便运行时和解析器复用。
  • 添加新的 core.services.weather 包,并在其 __init__ 中导出 BoundedTTLSet、ChinaWeatherReconciler、WeatherFallbackConfig 及相关辅助函数。
  • 调整运行时和解析器中的导入,从 core.services.weather 中消费类型,而不是本地定义。
core/services/weather/__init__.py
core/app/runtime/disaster_service_runtime.py
core/parsers/weather_parser.py
在 README 和 changelog 中记录可选的 China Weather 回退数据源及其配置。
  • 更新 README 中的数据源表,提及针对 CMA 预警的可选 China Weather 对账。
  • 添加新的小节描述 weather_alarm_fallback 的语义,包括启用条件、基线行为、轮询间隔、超时时间、并发度以及带有 JSON 配置示例的去重策略。
  • 在启用可选对账数据源时,澄清对 CMA 延迟的预期。
  • 在 CHANGELOG 中添加“Unreleased”部分,突出新的回退特性和去重缓存扩展及相关测试。
README.md
CHANGELOG.md
为 China Weather 对账逻辑、运行时集成以及去重行为添加全面的单元测试。
  • 为回退配置默认值与钳制逻辑、天气解析器缓存契约以及去重保留行为添加测试。
  • 为索引解析添加测试,包括格式错误行、包装校验与空快照;为详情解析添加测试,包括包装检查、尾随数据、代码、标识符匹配和事件 ID 重建。
  • 测试 WarningSnapshotTracker 的预热语义和有界快照行为,以及 BoundedTTLSet 的过期/容量逻辑。
  • 测试 ChinaWeatherReconciler 在基线场景、新预警分发、详情失败隔离与重试、当分发抛出异常或返回 None 时的“至多一次”消费、无效索引处理以及不安全详情路径拒绝等异步行为。
  • 添加运行时级别的异步测试,覆盖轮询循环的 aiohttp 契约、取消传播、当 parse_event 返回 None 时的解析/分发行为,以及在回退启用/禁用和现有 Wolfx 任务存在时的计划任务选择。
  • 通过测试验证 China Weather 客户端的 HTTP 头/常量。
tests/test_china_weather_reconciliation.py

Assessment against linked issues

Issue Objective Addressed Explanation
#143 实现一个可选的全国范围 China Weather 活动预警对账任务,周期性读取公共紧凑索引,以第一次成功快照作为基线,只为新出现的官方 ID 获取详情,重建与 FAN 兼容的事件 ID,复用现有的 china_weather_fanstudio 解析和发送流水线,避免 FAN WebSocket 与 HTTP 之间的重复推送,在不影响 WebSocket 的情况下处理 HTTP 错误,并且不引入新的第三方依赖或城市级逻辑。
#143 扩展天气预警事件 ID 去重机制,使用具有足够容量的有界 TTL 缓存(例如 24 小时 TTL、最多 4096 条目),以便 FAN 和 HTTP 补偿共享相同的逻辑事件 ID,并可跨传输进行去重。
#143 更新文档并添加测试,用于描述和验证新的全国天气预警对账特性、其配置边界、失败处理、URL 安全性、运行时集成以及去重行为。

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: 在 pull request 上评论 @sourcery-ai review
  • Continue discussions: 直接回复 Sourcery 的评审评论继续讨论。
  • Generate a GitHub issue from a review comment: 通过回复评审评论让 Sourcery 从该评论创建一个 issue。你也可以在评审评论中回复 @sourcery-ai issue 来创建对应的 issue。
  • Generate a pull request title: 在 pull request 标题中的任何位置写上 @sourcery-ai,即可随时生成标题。你也可以在 pull request 上评论 @sourcery-ai title 来(重新)生成标题。
  • Generate a pull request summary: 在 pull request 正文中的任何位置写上 @sourcery-ai summary,即可在你希望的位置生成 PR 摘要。你也可以在 pull request 上评论 @sourcery-ai summary 来随时(重新)生成摘要。
  • Generate reviewer's guide: 在 pull request 上评论 @sourcery-ai guide,即可随时(重新)生成评审指南。
  • Resolve all Sourcery comments: 在 pull request 上评论 @sourcery-ai resolve,即可标记所有 Sourcery 评论为已解决。如果你已经处理完所有评论且不想再看到它们,这很有用。
  • Dismiss all Sourcery reviews: 在 pull request 上评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 评审。若你希望从一次新的评审开始,尤其有用——不要忘记再评论 @sourcery-ai review 来触发新评审!

Customizing Your Experience

访问你的 dashboard 来:

  • 启用或禁用评审特性,例如 Sourcery 生成的 pull request 摘要、评审指南等。
  • 更改评审语言。
  • 添加、删除或编辑自定义评审说明。
  • 调整其他评审设置。

Getting Help

Original review guide in English

Reviewer's Guide

Add an optional nationwide China Weather reconciliation pipeline that polls a compact warning index, normalizes detail payloads into FAN-compatible weather events, and feeds them into the existing china_weather_fanstudio flow with robust deduplication and safety checks.

Sequence diagram for China Weather reconciliation polling and dispatch

sequenceDiagram
    participant Runtime as DisasterServiceRuntimeService
    participant Reconciler as ChinaWeatherReconciler
    participant HTTP as aiohttp_ClientSession
    participant Parser as WeatherAlarmParser
    participant Pipeline as DisasterEventPipeline

    Runtime->>Runtime: start_scheduled_http_fetch()
    Runtime->>Runtime: _run_china_weather_loop(fallback_config)
    Runtime->>HTTP: ClientSession(timeout, headers)
    loop every poll_interval_seconds while service.running
        Runtime->>HTTP: fetch_text(_CHINA_WEATHER_INDEX_URL)
        HTTP-->>Runtime: index_script
        Runtime->>Reconciler: reconcile(index_script, fetch_detail, _dispatch_china_weather_payload)
        Reconciler->>HTTP: fetch_detail(detail_path)
        HTTP-->>Reconciler: detail_script
        Reconciler->>Reconciler: parse_warning_detail(detail_script, reference)
        Reconciler->>Runtime: _dispatch_china_weather_payload(payload)
        Runtime->>Parser: parse_event("china_weather_fanstudio", json.dumps(payload))
        Parser-->>Runtime: event
        Runtime->>Pipeline: _handle_disaster_event(event)
    end
Loading

File-Level Changes

Change Details Files
Wire an optional China Weather reconciliation polling loop into the disaster runtime, gated by configuration and existing source enablement.
  • Import aiohttp and new China Weather reconciliation primitives into the disaster runtime service.
  • Resolve WeatherFallbackConfig from the top-level service config with bounded poll interval, timeout, and concurrency.
  • Start a named China Weather HTTP task only when the fallback is enabled and the china_weather_fanstudio source is active.
  • Implement _run_china_weather_loop to maintain an aiohttp session, poll the public China Weather index at configured intervals, and invoke the reconciler with index script, detail fetcher, and dispatch callback.
  • Add _dispatch_china_weather_payload to parse reconciled payloads via the china_weather_fanstudio parser and feed them once into the existing disaster event pipeline.
  • Define constants for the China Weather index URL, detail base URL, and required HTTP headers (User-Agent and Referer).
core/app/runtime/disaster_service_runtime.py
Introduce pure China Weather reconciliation services with index/detail parsing, event ID reconstruction, deduplication, and safe detail-path validation.
  • Create WeatherFallbackConfig, WarningReference, WarningSnapshotTracker, BoundedTTLSet, ReconciliationCycleResult, and ChinaWeatherReconciler in a new china_weather_reconciliation module.
  • Implement resolve_fallback_config to read weather_alarm_fallback, clamp numeric bounds, and expose an immutable config dataclass.
  • Parse compact index scripts into WarningReference lists, rejecting malformed payloads or rows and supporting empty snapshots.
  • Parse detail scripts into FAN-compatible payloads, including type/level code normalization, severity color mapping, headline/title/content extraction, coordinates, and transport metadata.
  • Validate and normalize warning identifiers to FAN-style event IDs, enforcing timestamp shape and basic sanity checks.
  • Implement WarningSnapshotTracker to warm on a valid index and subsequently emit only new identifiers while bounding stored snapshot size.
  • Implement BoundedTTLSet to track processed event IDs with TTL-based expiry and capacity enforcement.
  • Implement ChinaWeatherReconciler.reconcile to identify new references, fetch/parse details with bounded concurrency, call the downstream dispatch once per reference, and report new/consumed/failed identifiers, treating detail failures as retryable and dispatch returns/exceptions as at-most-once consumption.
  • Implement validate_detail_path to strictly accept only safe, unencoded relative file names and reject URLs, traversal, nested paths, backslashes, queries, fragments, and disallowed characters.
core/services/weather/china_weather_reconciliation.py
Extend the weather parser’s deduplication to a bounded TTL set shared with HTTP reconciliation, keeping existing china_weather_fanstudio parsing behavior.
  • Replace the WeatherAlarmParser deque-based cache with BoundedTTLSet configured for 24h TTL and 4096 max entries.
  • Use the new cache’s add and membership semantics to filter duplicate event IDs across both FAN WebSocket and HTTP reconciliation streams.
  • Update inline comments to reflect cache semantics (from queue to cache).
core/parsers/weather_parser.py
Expose the reconciliation primitives via a weather services package for reuse by runtime and parser.
  • Add a new core.services.weather package with an init exporting BoundedTTLSet, ChinaWeatherReconciler, WeatherFallbackConfig and related helpers.
  • Adjust imports in runtime and parser to consume types from core.services.weather instead of local definitions.
core/services/weather/__init__.py
core/app/runtime/disaster_service_runtime.py
core/parsers/weather_parser.py
Document the optional China Weather fallback source and configuration in README and changelog.
  • Update README data-source table to mention the optional China Weather reconciliation for CMA warnings.
  • Add a new subsection describing weather_alarm_fallback semantics, including enablement conditions, baseline behavior, polling interval, timeout, concurrency, and deduplication strategy with a JSON config example.
  • Clarify CMA latency expectations when the optional reconciliation source is enabled.
  • Add an Unreleased section to CHANGELOG highlighting the new fallback feature and dedup cache expansion plus related tests.
README.md
CHANGELOG.md
Add comprehensive unit tests for China Weather reconciliation logic, runtime integration, and dedup behavior.
  • Introduce tests for fallback config defaulting and clamping, weather parser cache contract, and dedup retention behavior.
  • Test index parsing for malformed rows, wrapper validation, and empty snapshots; detail parsing for wrapper checks, trailing data, codes, identifier matching, and event ID reconstruction.
  • Test WarningSnapshotTracker warm-start semantics and bounded snapshot behavior, and BoundedTTLSet expiry/cap logic.
  • Test ChinaWeatherReconciler async behavior across baseline, new warning dispatch, detail failure isolation and retry, at-most-once consumption when dispatch raises or returns None, invalid index handling, and unsafe detail-path rejection.
  • Add runtime-level async tests that exercise the polling loop’s aiohttp contract, cancellation propagation, parse/dispatch behavior when parse_event returns None, and scheduled task selection with enabled/disabled fallback and existing Wolfx tasks.
  • Verify HTTP headers/constants for the China Weather client via tests.
tests/test_china_weather_reconciliation.py

Assessment against linked issues

Issue Objective Addressed Explanation
#143 Implement an optional nationwide China Weather activity warning reconciliation task that periodically reads the public compact index, uses the first successful snapshot as a baseline, only fetches details for newly appeared official IDs, reconstructs FAN-compatible event IDs, reuses the existing china_weather_fanstudio parsing and sending pipeline, avoids duplicate pushes between FAN WebSocket and HTTP, handles HTTP errors without impacting WebSocket, and introduces no new third-party dependencies or city-specific logic.
#143 Extend the weather warning event ID de-duplication mechanism to use a bounded TTL cache with sufficient capacity (e.g., 24h TTL, up to 4096 entries) so FAN and HTTP compensation share the same logical event IDs and can be cross-transport de-duplicated.
#143 Update documentation and add tests to describe and validate the new nationwide weather alarm reconciliation feature, its configuration bounds, failure handling, URL safety, runtime integration, and de-duplication behavior.

Possibly linked issues


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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an optional, low-frequency China Weather national active warning reconciliation fallback (weather_alarm_fallback) to supplement the real-time FAN Studio stream. It adds the configuration schema, implements the core reconciliation and parsing logic with a bounded TTL cache for deduplication, integrates the polling loop into the disaster service runtime, and includes comprehensive unit tests. The review feedback highlights two important optimization opportunities: first, removing the detail semaphore restriction around the downstream dispatch call to prevent performance bottlenecks, and second, optimizing the BoundedTTLSet._purge_expired method to break early from the ordered dictionary traversal once a non-expired entry is encountered.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread core/services/weather/china_weather_reconciliation.py
Comment thread core/services/weather/china_weather_reconciliation.py Outdated

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - 我发现了 1 个问题,并留下了一些整体性的反馈:

  • ChinaWeatherReconciler._process_reference 中,同一个 detail_semaphore 被用来同时保护网络请求和后续的下游分发;如果你的意图只是限制 HTTP 并发数量,建议不要在分发阶段也使用这个信号量包裹,这样就不会不必要地把事件管线串行化。
  • 对账测试通过 importlib.util.spec_from_file_location 和一些合成包来构建自定义的模块导入图;这相当复杂,而且在未来目录结构变化时可能比较脆弱——建议重构为直接通过公共包 API 进行测试,或者尽可能使用更简单的假对象 / stub。
给 AI Agent 的提示
Please address the comments from this code review:

## Overall Comments
- In `ChinaWeatherReconciler._process_reference`, the same `detail_semaphore` is used to guard both network fetch and downstream dispatch; if the intent is only to cap HTTP concurrency, consider not wrapping the dispatch in the semaphore so you don’t unnecessarily serialize the event pipeline.
- The reconciliation tests build a custom module import graph using `importlib.util.spec_from_file_location` and synthetic packages; this is quite intricate and may be brittle against future layout changes—consider refactoring to exercise the public package API directly or using simpler fakes/stubs where possible.

## Individual Comments

### Comment 1
<location path="tests/test_china_weather_reconciliation.py" line_range="631-271" />
<code_context>
+    async def test_unsafe_detail_paths_are_rejected_before_fetch(self) -> None:
</code_context>
<issue_to_address>
**suggestion (testing):** Add direct unit tests for validate_detail_path to cover all path validation rules.

The async reconciler test verifies that obviously unsafe paths are blocked, but `validate_detail_path` enforces additional rules that aren’t directly tested:
- Rejecting leading/trailing whitespace
- Handling URL-encoded components (e.g. `%2e%2e%2fencoded.html`)
- Empty string and non-string inputs
- Single-dot and double-dot names (`"."`, "..")

Because `validate_detail_path` is exported from `core.services.weather` and acts as a security-critical guard, please add targeted unit tests that call it directly and assert both allowed and rejected cases, so future changes to the path rules are captured explicitly rather than inferred via reconciler behavior.

Suggested implementation:

```python
    async def test_unsafe_detail_paths_are_rejected_before_fetch(self) -> None:

    def test_validate_detail_path_accepts_safe_paths(self) -> None:
        safe_paths = (
            "a.html",
            "b.json",
            "index.html",
        )
        for path in safe_paths:
            # Should not raise for safe, normalized paths
            validate_detail_path(path)

    def test_validate_detail_path_rejects_unsafe_and_malformed_paths(self) -> None:
        unsafe_paths = (
            # Existing unsafe patterns
            "https://evil.example/a.html",
            "//evil.example/a.html",
            "/absolute.html",
            "../traversal.html",
            "nested/a.html",
            "nested\\a.html",
            "a.html?query=1",
            # Leading/trailing whitespace
            " leading.html",
            "trailing.html ",
            "\ta.html",
            "\na.html",
            # URL-encoded components
            "%2e%2e%2fencoded.html",  # "../encoded.html"
            "%2E%2E%2Fencoded.html",
            # Empty and non-path-ish inputs
            "",
            " ",
            # Single-dot and double-dot names
            ".",
            "..",
        )
        for path in unsafe_paths:
            with self.assertRaises(ValueError):
                validate_detail_path(path)

```

1. Ensure `validate_detail_path` is imported at the top of `tests/test_china_weather_reconciliation.py`, e.g.:
   `from core.services.weather import validate_detail_path`.
2. If `validate_detail_path` signals invalid paths using a different exception type (e.g. `RuntimeError` or a custom exception) or by returning a boolean instead of raising, adjust the `assertRaises(ValueError)` block accordingly:
   - If it returns `False` for invalid paths, change the loop to `self.assertFalse(validate_detail_path(path))`.
   - If it returns the normalized path for valid inputs, you may want to assert equality for some of the safe cases, e.g. `self.assertEqual(path, validate_detail_path(path))`.
3. If your test class uses any specific mixins or helpers for validation-related tests, you can move these new test methods into that class or adapt naming/structure to match existing conventions.
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续评审。
Original comment in English

Hey - I've found 1 issue, and left some high level feedback:

  • In ChinaWeatherReconciler._process_reference, the same detail_semaphore is used to guard both network fetch and downstream dispatch; if the intent is only to cap HTTP concurrency, consider not wrapping the dispatch in the semaphore so you don’t unnecessarily serialize the event pipeline.
  • The reconciliation tests build a custom module import graph using importlib.util.spec_from_file_location and synthetic packages; this is quite intricate and may be brittle against future layout changes—consider refactoring to exercise the public package API directly or using simpler fakes/stubs where possible.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `ChinaWeatherReconciler._process_reference`, the same `detail_semaphore` is used to guard both network fetch and downstream dispatch; if the intent is only to cap HTTP concurrency, consider not wrapping the dispatch in the semaphore so you don’t unnecessarily serialize the event pipeline.
- The reconciliation tests build a custom module import graph using `importlib.util.spec_from_file_location` and synthetic packages; this is quite intricate and may be brittle against future layout changes—consider refactoring to exercise the public package API directly or using simpler fakes/stubs where possible.

## Individual Comments

### Comment 1
<location path="tests/test_china_weather_reconciliation.py" line_range="631-271" />
<code_context>
+    async def test_unsafe_detail_paths_are_rejected_before_fetch(self) -> None:
</code_context>
<issue_to_address>
**suggestion (testing):** Add direct unit tests for validate_detail_path to cover all path validation rules.

The async reconciler test verifies that obviously unsafe paths are blocked, but `validate_detail_path` enforces additional rules that aren’t directly tested:
- Rejecting leading/trailing whitespace
- Handling URL-encoded components (e.g. `%2e%2e%2fencoded.html`)
- Empty string and non-string inputs
- Single-dot and double-dot names (`"."`, "..")

Because `validate_detail_path` is exported from `core.services.weather` and acts as a security-critical guard, please add targeted unit tests that call it directly and assert both allowed and rejected cases, so future changes to the path rules are captured explicitly rather than inferred via reconciler behavior.

Suggested implementation:

```python
    async def test_unsafe_detail_paths_are_rejected_before_fetch(self) -> None:

    def test_validate_detail_path_accepts_safe_paths(self) -> None:
        safe_paths = (
            "a.html",
            "b.json",
            "index.html",
        )
        for path in safe_paths:
            # Should not raise for safe, normalized paths
            validate_detail_path(path)

    def test_validate_detail_path_rejects_unsafe_and_malformed_paths(self) -> None:
        unsafe_paths = (
            # Existing unsafe patterns
            "https://evil.example/a.html",
            "//evil.example/a.html",
            "/absolute.html",
            "../traversal.html",
            "nested/a.html",
            "nested\\a.html",
            "a.html?query=1",
            # Leading/trailing whitespace
            " leading.html",
            "trailing.html ",
            "\ta.html",
            "\na.html",
            # URL-encoded components
            "%2e%2e%2fencoded.html",  # "../encoded.html"
            "%2E%2E%2Fencoded.html",
            # Empty and non-path-ish inputs
            "",
            " ",
            # Single-dot and double-dot names
            ".",
            "..",
        )
        for path in unsafe_paths:
            with self.assertRaises(ValueError):
                validate_detail_path(path)

```

1. Ensure `validate_detail_path` is imported at the top of `tests/test_china_weather_reconciliation.py`, e.g.:
   `from core.services.weather import validate_detail_path`.
2. If `validate_detail_path` signals invalid paths using a different exception type (e.g. `RuntimeError` or a custom exception) or by returning a boolean instead of raising, adjust the `assertRaises(ValueError)` block accordingly:
   - If it returns `False` for invalid paths, change the loop to `self.assertFalse(validate_detail_path(path))`.
   - If it returns the normalized path for valid inputs, you may want to assert equality for some of the safe cases, e.g. `self.assertEqual(path, validate_detail_path(path))`.
3. If your test class uses any specific mixins or helpers for validation-related tests, you can move these new test methods into that class or adapt naming/structure to match existing conventions.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread tests/test_china_weather_reconciliation.py
@SunmiJJW

Copy link
Copy Markdown
Author

已在提交 5914ba9 处理本轮 AI 审核:

  • 详情 HTTP 信号量不再包裹下游分发;
  • TTL 清理利用 OrderedDict 顺序提前停止;
  • validate_detail_path 增加安全/不安全输入的直接单测。

全量测试从 34 增至 36,unittest discover、Ruff、compileall、Schema JSON 和 git diff --check 均通过。三个行级线程已逐条回复并解决。

关于测试中的合成包导入:当前仓库模块会经包初始化间接依赖 AstrBot,而独立单测环境没有安装 AstrBot,因此保留最小 stub 以隔离纯逻辑;PR 前已另用真实 AstrBot 环境执行公共包导入烟测,生产导入路径没有被弱化。

@SunmiJJW

Copy link
Copy Markdown
Author

补充修复了实网发现的气象预警图标错配:上游实时流可能把 CMA 紧凑 TYPECODE 放进 11B 前缀中,例如高温事件携带 11B07,而 FAN 图标接口按国家标准将 11B07 解释为沙尘暴。现在解析边界会按已知预警语义规范化为标准 11B 图标码,复合灾种采用最长匹配,未知语义保持原码。新增高温实案、常见 14 类、复合灾种和未知类型回归测试;本分支全量 40/40 通过,Ruff、format、compileall 与 diff-check 均通过。

@codacy-production

codacy-production Bot commented Jul 16, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 247 complexity · 0 duplication

Metric Results
Complexity 247
Duplication 0

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

@codacy-production codacy-production 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.

Pull Request Overview

The pull request is currently not up to standards according to Codacy analysis. The most significant concern is a potential logic flaw in the weather parser's deduplication mechanism, where a mismatch between internal IDs and payload IDs could cause redundant alerts.

Additionally, several files exhibit high complexity or excessive length, notably in the runtime loop and the weather warning parser. While the feature implementation aligns with the requirement to provide an optional, bounded reconciliation service for China Weather alerts, refactoring is recommended for the main polling loop and the data parsing logic to ensure long-term maintainability.

Test suggestions

  • Verify that the first reconciliation cycle establishes a baseline and does not trigger alerts.
  • Verify that the BoundedTTLSet correctly expires old entries and respects the entry limit.
  • Verify that validate_detail_path rejects absolute paths, directory traversal (../), and URL parameters.
  • Verify that normalize_weather_warning_code corrects conflicting codes based on semantic text analysis.
  • Verify that the fallback configuration correctly clamps out-of-bounds numeric values for interval, timeout, and concurrency.
  • Verify that detail fetch failures are retried in the next cycle while dispatch failures follow 'at-most-once' semantics.

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

Comment thread core/parsers/weather_parser.py
Comment thread core/parsers/weather_parser.py Outdated
Comment thread core/app/runtime/disaster_service_runtime.py
Comment thread core/services/weather/china_weather_reconciliation.py Outdated
Comment thread tests/test_china_weather_reconciliation.py Outdated
@repowise-bot

repowise-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

✅ Health: 8.1 (unchanged)

📋 At a glance
2 files changed health · 2 hotspots touched · 11 new findings introduced. Scoped to core.

🚨 Change risk: high (riskier than 99% of this repo's commits)
This change's risk is driven by:

  • more lines added than baseline
  • more scattered than baseline
File Score Δ Why
.../runtime/disaster_service_runtime.py 9.5 → 9.1 ▼ -0.4 🔻 introduced large method, error handling
core/parsers/weather_parser.py 5.3 → 6.0 ▲ +0.7 ✅ resolved dry violation
🔎 More signals (1)

🔥 Hotspots touched (2)

  • .../runtime/disaster_service_runtime.py — 3 commits/90d, 1 dependents · primary owner: DBJD-CR (100%)
  • core/parsers/weather_parser.py — 3 commits/90d, 1 dependents · primary owner: DBJD-CR (100%)

👀 Suggested reviewers @DBJD-CR


📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-07-17 11:32 UTC
Silence on a single PR with [skip repowise] in the title · Per-repo toggle on repowise.dev/settings?tab=bot

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ac9fab4e-1c4a-4cad-809d-5cfbba74d297

📥 Commits

Reviewing files that changed from the base of the PR and between 33dce0d and 51e78ad.

📒 Files selected for processing (5)
  • README.md
  • core/parsers/weather_parser.py
  • core/services/weather/china_weather_reconciliation.py
  • tests/test_china_weather_reconciler.py
  • tests/test_china_weather_reconciliation.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • README.md
  • core/parsers/weather_parser.py
  • core/services/weather/china_weather_reconciliation.py
  • tests/test_china_weather_reconciliation.py
📜 Recent review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (1)
tests/test_china_weather_reconciler.py (1)

5-5: LGTM!

Also applies to: 20-243, 246-247


📝 Walkthrough

Walkthrough

新增 China Weather 全国气象预警对账补偿能力,包含配置、索引与详情解析、快照去重、事件分发、运行时轮询、告警编码规范化及相关测试和文档。

Changes

气象预警对账补偿

Layer / File(s) Summary
配置与告警解析契约
_conf_schema.json, core/services/weather/*
新增回退配置、China Weather 索引/详情解析、事件 ID 构建、路径安全校验及告警编码规范化导出。
快照重调谐与去重分发
core/services/weather/china_weather_reconciliation.py, tests/test_china_weather_reconciliation.py, tests/test_china_weather_reconciler.py
实现首次基线、后续新增告警处理、详情并发、失败重试、TTL 有界去重和至多一次消费,并覆盖相关边界。
现有气象解析器接入
core/parsers/weather_parser.py, core/services/weather/warning_code_normalization.py
使用事件 ID TTL 缓存、统一发布时间提取,并按告警语义规范化天气编码。
运行时调度与配置说明
core/app/runtime/disaster_service_runtime.py, tests/test_disaster_service_runtime.py, README.md, CHANGELOG.md
新增 China Weather 轮询任务、请求头和事件投递流程,补充运行时测试、配置文档及未发布变更记录。

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RuntimeScheduler
  participant ChinaWeatherReconciler
  participant ChinaWeather
  participant DisasterEventHandler
  RuntimeScheduler->>ChinaWeatherReconciler: 启动轮询周期
  ChinaWeatherReconciler->>ChinaWeather: 请求活动预警索引
  ChinaWeather-->>ChinaWeatherReconciler: 返回新告警引用
  ChinaWeatherReconciler->>ChinaWeather: 请求新增告警详情
  ChinaWeather-->>ChinaWeatherReconciler: 返回详情载荷
  ChinaWeatherReconciler->>DisasterEventHandler: 投递 FAN 兼容事件
Loading

Suggested labels: type/feat, type/fix

Suggested reviewers: dbjd-cr

Poem

我是小兔,抱来新预警,
索引排队,详情亮晶晶。
首轮只记不乱跳,
新闻才往风里飘。
去重缓存守夜岗,
让每条告警稳稳到达。

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题简洁且准确概括了本次新增全国气象预警对账补偿的主要变更。
Linked Issues check ✅ Passed 实现覆盖了定期对账、首次基线、后续增量、ID 重建、缓存去重、失败隔离、默认关闭和无新增依赖等要求。
Out of Scope Changes check ✅ Passed 未见明显与 #143 目标无关的改动,新增的规范化和测试也都服务于同一预警对账能力。

Comment @coderabbitai help to get the list of available commands.

@coderabbitai
coderabbitai Bot requested a review from DBJD-CR July 17, 2026 11:21
@coderabbitai coderabbitai Bot added type/feat ✨ 新功能 / New Feature type/fix 🐛 Bug 修复 labels Jul 17, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/parsers/weather_parser.py`:
- Around line 20-40: 更新 _extract_issue_time,使用严格正则从事件 ID 中解析官方下划线格式和 FAN
连字符格式的时间段(如 310000-20260713100000-11B0102)。仅接受完整有效的时间字段,解析失败或格式不匹配时继续返回
effective_time,确保缺失 effective 时仍能使用 ID 中的发布时间。

In `@core/services/weather/china_weather_reconciliation.py`:
- Around line 290-295: 限制新增记录的处理规模,避免在 asyncio.gather 中为 new_references
的每条记录一次性创建任务。更新包含 _process_reference 的处理流程,使用固定数量 worker
或有界队列(或在进入处理前拒绝超过容量的快照),确保并发与待处理任务数量有明确上限,而不要仅依赖 detail_concurrency 或
max_entries。

In `@README.md`:
- Around line 557-564: 将 README.md 中 weather_alarm_fallback 配置示例包装在最外层 JSON
对象的大括号内,使用户复制整个代码块时得到有效 JSON;保留现有配置键和值不变。

In `@tests/test_china_weather_reconciliation.py`:
- Around line 475-482: Update the missing_type_code and unsupported_level_code
payloads in test_parse_warning_detail_rejects_missing_or_unsupported_codes to
include the matching identifier expected by REF_A, while preserving each
payload’s intended invalid condition so the tests reach the missing TYPECODE and
unsupported LEVELCODE branches respectively.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 904c10e3-e307-46b5-99f2-2cef2d18ad76

📥 Commits

Reviewing files that changed from the base of the PR and between 564c330 and 87836bd.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • README.md
  • _conf_schema.json
  • core/app/runtime/disaster_service_runtime.py
  • core/parsers/weather_parser.py
  • core/services/weather/__init__.py
  • core/services/weather/china_weather_reconciliation.py
  • core/services/weather/warning_code_normalization.py
  • tests/test_china_weather_reconciliation.py
  • tests/test_disaster_service_runtime.py
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Codacy Static Code Analysis
🧰 Additional context used
🪛 ast-grep (0.44.1)
core/app/runtime/disaster_service_runtime.py

[warning] 29-29: Do not make http calls without encryption
Context: "http://www.weather.com.cn/alarm/"
Note: [CWE-319] Cleartext Transmission of Sensitive Information.

(requests-http)


[info] 271-271: use jsonify instead of json.dumps for JSON output
Context: json.dumps(payload, ensure_ascii=False)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

tests/test_china_weather_reconciliation.py

[info] 136-136: use jsonify instead of json.dumps for JSON output
Context: json.dumps({'count': str(len(rows)), 'data': rows})
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 140-149: use jsonify instead of json.dumps for JSON output
Context: json.dumps(
{
"ISSUETIME": "2026-07-13 10:10:00",
"head": reference.title,
"ISSUECONTENT": "Expect severe weather.",
"TYPECODE": "01",
"LEVELCODE": "02",
"identifier": reference.identifier,
}
)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

tests/test_disaster_service_runtime.py

[warning] 188-188: Do not make http calls without encryption
Context: "http://www.weather.com.cn/alarm/"
Note: [CWE-319] Cleartext Transmission of Sensitive Information.

(requests-http)


[warning] 276-276: Do not make http calls without encryption
Context: "http://www.weather.com.cn/alarm/"
Note: [CWE-319] Cleartext Transmission of Sensitive Information.

(requests-http)

🪛 GitHub Check: Codacy Static Code Analysis
tests/test_china_weather_reconciliation.py

[warning] 1-1: tests/test_china_weather_reconciliation.py#L1
File tests/test_china_weather_reconciliation.py has 618 non-comment lines of code


[failure] 214-214: tests/test_china_weather_reconciliation.py#L214
resolver is not callable


[failure] 228-228: tests/test_china_weather_reconciliation.py#L228
resolver is not callable


[failure] 238-238: tests/test_china_weather_reconciliation.py#L238
resolver is not callable


[failure] 564-564: tests/test_china_weather_reconciliation.py#L564
reconciler_type is not callable

tests/test_disaster_service_runtime.py

[failure] 169-169: tests/test_disaster_service_runtime.py#L169
resolver is not callable


[failure] 210-210: tests/test_disaster_service_runtime.py#L210
resolver is not callable

🪛 LanguageTool
CHANGELOG.md

[uncategorized] ~12-~12: 您的意思是“"不"齐”?
Context: ...中国天气网全国活动预警对账补偿,可在不替换 FAN Studio 实时流的前提下补齐可能遗漏的中间气象预警。 - 气象预警事件 ID 去重缓存扩展为 24 小时、...

(BU)

🔇 Additional comments (10)
_conf_schema.json (1)

190-235: LGTM!

Also applies to: 968-968

core/services/weather/china_weather_reconciliation.py (1)

1-289: LGTM!

Also applies to: 296-461

core/services/weather/warning_code_normalization.py (1)

1-116: LGTM!

core/services/weather/__init__.py (1)

1-32: LGTM!

tests/test_china_weather_reconciliation.py (1)

1-474: LGTM!

Also applies to: 483-752

core/parsers/weather_parser.py (1)

15-19: LGTM!

Also applies to: 41-52, 92-92, 109-129, 194-196

core/app/runtime/disaster_service_runtime.py (1)

12-31: LGTM!

Also applies to: 106-107, 185-276

tests/test_disaster_service_runtime.py (1)

1-326: LGTM!

README.md (1)

120-120: LGTM!

Also applies to: 422-422, 444-444, 545-556, 565-565

CHANGELOG.md (1)

8-22: LGTM!

Comment thread core/parsers/weather_parser.py Outdated
Comment thread core/services/weather/china_weather_reconciliation.py Outdated
Comment thread README.md
Comment thread tests/test_china_weather_reconciliation.py
@coderabbitai coderabbitai Bot removed the type/fix 🐛 Bug 修复 label Jul 17, 2026
@coderabbitai coderabbitai Bot added the type/fix 🐛 Bug 修复 label Jul 17, 2026
@DBJD-CR

DBJD-CR commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

感觉只拿来做预警对账源的话有点可惜?如果你能从中国天气网上抓取到完整的一个不漏的气象预警信息,其实我更推荐你把它单独做成一个独立的数据源。而且现在Fan的气象预警确实推送频率降低了不少,好像每15/30分钟才推一条。

另外由此可能产生的大量推送,你可以参考一下 #109 中提到的合并转发,设计一个合并转发的机制(暂时可以先只适配该数据源)。如果是其他平台,可能需要设计一些熔断机制,不过问题不大,可以之后再补上。

@DBJD-CR
DBJD-CR requested a review from Aloys233 July 19, 2026 08:17
@DBJD-CR DBJD-CR removed the type/fix 🐛 Bug 修复 label Jul 19, 2026
@SunmiJJW

Copy link
Copy Markdown
Author

哈哈是的,会刷屏的问题存在。我之前<关键词白名单>里填的“上海”,被群友说一直刷太烦,于是改成具体区名了。

独立数据源方向我研究下看看可靠不

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

Labels

size:XL 修改了 500-999 行代码 (忽略生成文件) type/feat ✨ 新功能 / New Feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 为 FAN 气象预警增加全国活动预警对账补偿

2 participants