Skip to content

Release v2.0.3#76

Merged
FlanChanXwO merged 10 commits into
masterfrom
dev
May 31, 2026
Merged

Release v2.0.3#76
FlanChanXwO merged 10 commits into
masterfrom
dev

Conversation

@FlanChanXwO
Copy link
Copy Markdown
Owner

@FlanChanXwO FlanChanXwO commented May 31, 2026

Closes #58
Closes #70

发布 v2.0.3:将 dev 累积的修复与增强合入 master 发版。

本次发布汇集自 v2.0.2 以来合并到 dev 的 10 个 PR(#62#64#65#66#67#68#69#71#74#75),完整条目见 CHANGELOG.md[2.0.3] 段。

Modifications / 改动点

主要面向用户的变化:

  • 新增 http_config:统一 RSS 拉取、媒体预下载与 FFmpeg m3u8/HLS 下载的代理与超时(媒体超时上限提升到 1800 秒);旧代理/超时配置启动时自动迁移。

  • Plugin Pages 增强:推送历史支持单条重试、删除用户/Feed/订阅时可选清理推送历史、订阅列表支持按 Feed URL 精确筛选、数据自愈。

  • AI 工具rss_subscribe 支持一次订阅多个目标,rss_push_xml_entry 支持临时排版参数。

  • 媒体发送稳定性:OneBot 优先使用本地预下载视频、NapCat 流式上传、媒体缓存与 m3u8/HLS 合并完整性校验、多平台降级策略收口为内置常量。

  • 内置 Noto Sans SC 字体改为运行时按需下载,并改为后台预取,不阻塞插件加载。

  • 修复 issue Bug: /sub功能异常 #70:同一用户可在不同群聊订阅同一 RSS 源(查重按 (user_id, feed_id, target_session) 隔离);并修复旧库 link_preview NOT NULL 导致 /sub 报错。

  • 配置/代码清理telegraph_proxy 归位 Telegram 策略并接通、移除无效 GreedyStr 兼容层、CHANGELOG 与 usage 文档整理、新增仓库体积与 docstring 开发规范。

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

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

dev 分支上各 PR 合并前均通过验证;当前发布分支状态:

$ python tests/run_tests.py --category unit         # Results: 17 passed, 0 failed
$ python tests/run_tests.py --category integration  # Results: 4 passed, 0 failed
$ uv run ruff format <plugin>   # all files unchanged
$ uv run ruff check  <plugin>   # All checks passed!

Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed them with the authors through issues/emails, etc. / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。
  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above. / 我的更改经过了良好的测试,并已在上方提供了"验证步骤"和"运行截图"
  • 🤓 I have ensured that no new dependencies are introduced. / 我确保没有引入新依赖库。
  • 😮 My changes do not introduce malicious code. / 我的更改没有引入恶意代码。

FlanChanXwO and others added 10 commits May 27, 2026 01:22
* fix(media): harden predownload and config handling

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* docs: refresh help image and project docs

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* docs: update pull request template

* ci: remove unused knowledgebase script

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* fix(media): improve media detection and platform sending

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix(media): address platform review feedback

* fix(media): address review feedback

* refactor(media): add table rendering pipeline

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* feat(pages): add push retry and data self-healing

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix(pages): address web api review feedback

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* refactor(pages): split dashboard modules

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* fix(pages): improve multi-select filters

* fix(pages): address filter review comments
* fix(kb): reconcile route knowledge manifest

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix(kb): address manifest review feedback

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
… upload (#74)

* fix(db): drop legacy link_preview column and add napcat stream upload

修复 Issue #58:旧库残留的 link_preview NOT NULL 列导致 /sub 创建订阅失败。
新增 V2 迁移在启动时安全删除该列(幂等)。

同时把 OneBot 的 prefer_local_video 配置替换为 napcat_stream_mode
(disabled/fallback/always):媒体已统一预下载,发送统一使用本地文件;
新增 NapCat 流式上传模块,支持发送前预上传或失败后流式重试,避免大文件 OOM。
主动推送场景通过 platform_manager 解析 bot 客户端,旧 prefer_local_video
配置在启动自愈时迁移为对应 napcat_stream_mode。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix(config): replace stale FFmpegSettings export with MediaRuntimeSettings

FFmpegSettings was renamed to MediaRuntimeSettings in the napcat_stream
refactor but the __init__.py re-exports in config/ and models/ still
referenced the old name, causing ImportError at runtime.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* feat: bundle Noto Sans SC font and remove hardcoded system font paths

Ship NotoSansSC-subset.otf (~14 MB) in assets/fonts/ so the table
image renderer works out-of-the-box with CJK text on any OS. Remove
the six hardcoded absolute system font paths from _iter_font_candidates()
to eliminate platform-dependent font probing.

- Add assets/fonts/NotoSansSC-subset.otf (Noto Sans SC Subset Variable OTF)
- Add assets/fonts/OFL.txt (SIL Open Font License 1.1)
- Remove hardcoded macOS/Linux system font paths from table_image_renderer.py
- Update font type annotations to support FreeTypeFont | ImageFont union
- Add tests for bundled font discovery and system path verification
- Update docs/project/formatting.md to reflect bundled font

Font search priority: env vars > assets/fonts/ > Pillow default fallback

* feat: runtime font download instead of bundled CJK font

Replace the 14 MB bundled NotoSansSC-subset.otf with runtime download
from jsDelivr CDN. Font is downloaded at plugin startup, verified with
SHA256 + size checks, and atomically written to persistent data dir.

When no CJK font is available (download failed or offline), tables
fall back to plain text (A | B | C) instead of using Pillow default
font, preventing broken CJK rendering.

- Add font_manager.py with async download, double-check lock, atomic write
- Remove ImageFont.load_default() fallback from table_image_renderer
- Add _warned_no_font + early return None when no font
- Add get_runtime_font_dir() to font candidate priority list
- Wire await ensure_table_font() in bootstrap startup flow
- Add 8 font_manager tests + update table_renderer tests
- Fix conftest.py namespace package conflict across feature branches
- Update formatting.md docs

Closes #71

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* perf(rendering): 字体改为后台预取+按需加载,不再阻塞插件启动

启用表格转图时,字体下载在 bootstrap 中由同步 await 改为后台
asyncio.create_task 预取,首次表格渲染前再按需等待就绪(未配置下载的
环境直接回退纯文本,不发起网络请求)。同时补全缺失的表格转图总开关
EntryTextFormatter.configure_table_to_image,修复其原本不存在却被
bootstrap 调用导致的启动 AttributeError。

* refactor(interfaces): 移除无效的 GreedyStr 兼容层 astrbot_compat

命令处理器参数均带默认值(args: GreedyStr = ""),框架解析时只读默认值
不读注解,greedy 合并分支恒不触发——该注解功能上是惰性的,等价于 str。
故将注解统一改为 str,文件上传监听改用框架原生
filter.event_message_type(filter.EventMessageType.ALL),删除整个
astrbot_compat 兼容层并同步重写相关回归测试。

* refactor(config): telegraph_proxy 归位 Telegram 策略并接通

将 telegraph_proxy 从顶层 media 配置移入 telegram_strategy 模板,与
enable_telegraph/telegraph_token 同源。发送时由 TelegramSender 从策略
解析并传入 TelegraphClient(留空即直连,不再继承通用 HTTP 代理),修复
此前 _get_telegraph_proxy 定义却从未被调用的死配置问题,并移除相关死链路。
启动配置自愈新增迁移:旧 media.telegraph_proxy 会自动写入首个 telegram
策略模板项。

* docs: 整理 usage 文档与 README,精简 CHANGELOG 2.0.3

新增/完善 docs/usage 下的命令、配置、AI 工具、Plugin Pages 与兼容性文档;
commands.md 补 sub_stop 的 rss_stop 别名并修正 rsshelp 别名,configuration.md
随 telegraph_proxy 归位 Telegram 策略同步调整。CHANGELOG 2.0.3 由 22 条精简为
面向用户的高层要点。一并清理已内置字体后多余的 assets/fonts/OFL.txt,并在
metadata.yaml 声明最低 AstrBot 版本 >=4.24.0。

* fix(messaging): 用 TYPE_CHECKING 块消除 __all__ 懒加载告警

messaging 包通过 __getattr__ 懒加载所有导出,导致 __all__ 中 31 个名字在
类型检查器看来「未定义」(reportUnsupportedDunderAll)。新增 if TYPE_CHECKING
块真实导入这些符号:类型检查时静态可见、告警清零,运行时该块不执行,原有
懒加载行为完全保留。

* fix(subscription): 查重按会话隔离,允许多群订阅同一源 (#70)

订阅查重原先用 (user_id, feed_id) 忽略 target_session,导致同一用户在不同
群聊订阅同一 Feed 被误判为「您已经订阅了此源」。将仓储方法
get_by_user_and_feed 收紧为 get_by_user_feed_session(user_id, feed_id,
target_session),/sub 与导入两处查重均带上会话;同时避免多会话行存在时
scalar_one_or_none 误抛。新增回归测试覆盖「不同会话各自成功、相同会话仍拒绝」。

* docs(changelog): 2.0.3 恢复 Added/Changed/Removed/Fixed 分节结构

将此前压缩成扁平要点的 2.0.3 条目还原为 Keep a Changelog 分节格式,并把
「媒体缓存 GC / 完整性阈值 / 平台降级策略不再作为用户配置项暴露」从 Changed
提取为独立的 Removed 段。

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* docs(dev): 新增仓库体积上限与函数中文 docstring 规范

- maintenance.md 新增「仓库体积」章节:插件仓库总大小严格不得超过 16 MB,
  大体积资源应按需下载而非纳入仓库。
- engineering-principles.md 代码组织新增:每个函数/方法必须有确切的中文
  docstring,并与实现保持一致。

* fix: 缓存字体校验结果并防御订阅查重重复行

- font_manager: ensure_table_font_runtime 引入模块级缓存 _cached_verified_font
  + _verify_lock,首次校验后命中缓存,避免按 <table> 反复跑 15MB 全量 SHA256
  阻塞事件循环;ensure_table_font 在校验/下载成功后同步更新缓存。
- subscription_repository_impl: get_by_user_feed_session 改用 limit(1) +
  scalars().first(),(user_id, feed_id, target_session) 无唯一约束时若存在
  重复行不再抛 MultipleResultsFound。
- 补 font_manager 缓存回归测试与缓存重置 fixture。

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 31, 2026 22:54
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Sorry, we are unable to review this pull request

The GitHub API does not allow us to fetch diffs exceeding 20000 lines

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 31, 2026

Important

Review skipped

Too many files!

This PR contains 176 files, which is 26 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d58cdda7-7339-4ce0-aa80-59e1ddfd1932

📥 Commits

Reviewing files that changed from the base of the PR and between 2c59bdc and 89fb3e2.

⛔ Files ignored due to path filters (5)
  • assets/help/rsshelp.png is excluded by !**/*.png
  • assets/help/rsshelp_dark.png is excluded by !**/*.png
  • assets/help/rsshelp_light.png is excluded by !**/*.png
  • scripts/resources/GitHub.svg is excluded by !**/*.svg
  • scripts/resources/RssHub.svg is excluded by !**/*.svg
📒 Files selected for processing (176)
  • .github/PULL_REQUEST_TEMPLATE.md
  • .github/scripts/generate_knowledgebase.py
  • AGENTS.md
  • CHANGELOG.md
  • CLAUDE.md
  • README.md
  • _conf_schema.json
  • assets/help/rsshelp.html
  • assets/help/rsshelp_template.html
  • bootstrap.py
  • docs/PLAN.md
  • docs/README.md
  • docs/dev/README.md
  • docs/dev/contributing.md
  • docs/dev/engineering-principles.md
  • docs/dev/maintenance.md
  • docs/dev/setup.md
  • docs/dev/testing.md
  • docs/project/README.md
  • docs/project/application.md
  • docs/project/architecture.md
  • docs/project/dispatch.md
  • docs/project/domain-model.md
  • docs/project/formatting.md
  • docs/project/handlers.md
  • docs/project/knowledge.md
  • docs/project/overview.md
  • docs/project/platforms.md
  • docs/project/polling.md
  • docs/project/repositories.md
  • docs/project/roadmap.md
  • docs/project/sender.md
  • docs/project/web_api.md
  • docs/usage/README.md
  • docs/usage/ai-tools.md
  • docs/usage/commands.md
  • docs/usage/compatibility.md
  • docs/usage/configuration.md
  • docs/usage/plugin-pages.md
  • main.py
  • metadata.yaml
  • pages/dashboard/app.js
  • pages/dashboard/components/dashboard-template.js
  • pages/dashboard/components/overlays/dialogs.js
  • pages/dashboard/components/overlays/feed-panel.js
  • pages/dashboard/components/overlays/main-panel.js
  • pages/dashboard/components/overlays/user-panel.js
  • pages/dashboard/components/pages/data-management.js
  • pages/dashboard/components/pages/feeds.js
  • pages/dashboard/components/pages/handlers.js
  • pages/dashboard/components/pages/push-history.js
  • pages/dashboard/components/pages/route-kb.js
  • pages/dashboard/components/pages/settings.js
  • pages/dashboard/components/pages/subscriptions.js
  • pages/dashboard/components/pages/users.js
  • pages/dashboard/components/shared/filters.js
  • pages/dashboard/css/dark-theme.css
  • pages/dashboard/css/dashboard.css
  • pages/dashboard/css/notifications.css
  • pages/dashboard/index.html
  • pages/dashboard/js/api.js
  • pages/dashboard/js/autocomplete.js
  • pages/dashboard/store/helpers.js
  • pages/dashboard/store/index.js
  • pages/dashboard/store/modules/data-management.js
  • pages/dashboard/store/modules/feeds.js
  • pages/dashboard/store/modules/filters.js
  • pages/dashboard/store/modules/handlers.js
  • pages/dashboard/store/modules/lifecycle.js
  • pages/dashboard/store/modules/overlays.js
  • pages/dashboard/store/modules/panels.js
  • pages/dashboard/store/modules/pending.js
  • pages/dashboard/store/modules/push-history.js
  • pages/dashboard/store/modules/route-kb.js
  • pages/dashboard/store/modules/settings.js
  • pages/dashboard/store/modules/subscriptions.js
  • pages/dashboard/store/modules/users.js
  • pages/dashboard/store/state.js
  • requirements.txt
  • scripts/gen_rsshelp.ps1
  • scripts/gen_rsshelp.sh
  • scripts/generate_rsshelp_image.py
  • scripts/template/dark_theme.css
  • scripts/template/light_theme.css
  • scripts/template/rsshelp_template.html
  • scripts/template/rsshelp_template_style.css
  • src/application/commands/__init__.py
  • src/application/commands/help_image_cmd.py
  • src/application/commands/import_subscriptions_cmd.py
  • src/application/commands/subscribe_feed_cmd.py
  • src/application/llmtools.py
  • src/application/services/agent_xml_push_service.py
  • src/application/services/html_parser.py
  • src/application/services/notification_dispatcher.py
  • src/application/services/route_knowledge_service.py
  • src/domain/entities/__init__.py
  • src/domain/entities/content_types.py
  • src/domain/repositories/feed_repository.py
  • src/domain/repositories/push_history_repository.py
  • src/domain/repositories/subscription_repository.py
  • src/infrastructure/config/__init__.py
  • src/infrastructure/config/config_loader.py
  • src/infrastructure/config/datamodels.py
  • src/infrastructure/config/legacy_migration.py
  • src/infrastructure/config/models/__init__.py
  • src/infrastructure/config/models/plugin_config_models.py
  • src/infrastructure/config/models/runtime_settings.py
  • src/infrastructure/config/models/sender_strategy_models.py
  • src/infrastructure/config/schema_healer.py
  • src/infrastructure/config/settings_builder.py
  • src/infrastructure/media/__init__.py
  • src/infrastructure/media/media_downloader.py
  • src/infrastructure/messaging/__init__.py
  • src/infrastructure/messaging/media_send_planner.py
  • src/infrastructure/messaging/napcat_stream.py
  • src/infrastructure/messaging/senders/__init__.py
  • src/infrastructure/messaging/senders/base_sender.py
  • src/infrastructure/messaging/senders/onebot_sender.py
  • src/infrastructure/messaging/senders/provider.py
  • src/infrastructure/messaging/senders/qq_official_sender.py
  • src/infrastructure/messaging/senders/telegram_sender.py
  • src/infrastructure/messaging/senders/telegraph_client.py
  • src/infrastructure/messaging/senders/types.py
  • src/infrastructure/messaging/senders/weixin_oc_sender.py
  • src/infrastructure/persistence/database.py
  • src/infrastructure/persistence/feed_repository_impl.py
  • src/infrastructure/persistence/migrations/V2_drop_link_preview.py
  • src/infrastructure/persistence/migrations/__init__.py
  • src/infrastructure/persistence/migrations/migration_runner.py
  • src/infrastructure/persistence/push_history_repository_impl.py
  • src/infrastructure/persistence/subscription_repository_impl.py
  • src/infrastructure/pipeline/__init__.py
  • src/infrastructure/pipeline/components.py
  • src/infrastructure/pipeline/entry_formatter.py
  • src/infrastructure/pipeline/formatter.py
  • src/infrastructure/rendering/__init__.py
  • src/infrastructure/rendering/font_manager.py
  • src/infrastructure/rendering/table_image_renderer.py
  • src/infrastructure/utils/__init__.py
  • src/infrastructure/utils/media_dispatch.py
  • src/infrastructure/utils/media_integrity.py
  • src/infrastructure/utils/media_type_detector.py
  • src/interfaces/handlers/route_knowledge.py
  • src/interfaces/web_api.py
  • src/shared/constants.py
  • tests/README.md
  • tests/conftest.py
  • tests/integration/test_plugin_integration.py
  • tests/run_tests.py
  • tests/run_tests.sh
  • tests/unit/application/test_agent_xml_push_service.py
  • tests/unit/application/test_commands.py
  • tests/unit/application/test_import_export.py
  • tests/unit/application/test_llmtools.py
  • tests/unit/application/test_notification_dispatcher.py
  • tests/unit/application/test_route_knowledge_service.py
  • tests/unit/application/test_settings.py
  • tests/unit/infrastructure/test_base_sender_ffmpeg.py
  • tests/unit/infrastructure/test_database_manager.py
  • tests/unit/infrastructure/test_feed_repository_impl.py
  • tests/unit/infrastructure/test_font_manager.py
  • tests/unit/infrastructure/test_media_dispatch.py
  • tests/unit/infrastructure/test_media_downloader.py
  • tests/unit/infrastructure/test_media_send_planner.py
  • tests/unit/infrastructure/test_media_type_detector.py
  • tests/unit/infrastructure/test_message_formatter.py
  • tests/unit/infrastructure/test_onebot_sender.py
  • tests/unit/infrastructure/test_platform_sequence_senders.py
  • tests/unit/infrastructure/test_push_history_repository_impl.py
  • tests/unit/infrastructure/test_subscription_repository_impl.py
  • tests/unit/infrastructure/test_table_image_renderer.py
  • tests/unit/infrastructure/test_telegraph_client.py
  • tests/unit/interfaces/test_web_api.py
  • tests/unit/test_bootstrap_runtime.py
  • tests/unit/test_command_handlers_regression.py
  • tests/unit/test_conf_schema.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@github-actions github-actions Bot added area: docs Documentation changes area: frontend Plugin Pages or frontend changes area: backend Backend or core runtime changes area: tests Test changes area: github-actions GitHub workflow or repository automation changes release Release metadata or changelog changes labels May 31, 2026
@FlanChanXwO FlanChanXwO mentioned this pull request May 31, 2026
@FlanChanXwO FlanChanXwO merged commit bbeb435 into master May 31, 2026
3 of 4 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in astrbot_plugin_rsshub May 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: backend Backend or core runtime changes area: docs Documentation changes area: frontend Plugin Pages or frontend changes area: github-actions GitHub workflow or repository automation changes area: tests Test changes release Release metadata or changelog changes

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Bug: /sub功能异常 Bug: 更新2.0.1后m3u8视频推送再次异常

2 participants