Skip to content

Release v2.1.0 - #28

Merged
FlanChanXwO merged 7 commits into
masterfrom
codex/release-v2.1.0
Jun 14, 2026
Merged

Release v2.1.0#28
FlanChanXwO merged 7 commits into
masterfrom
codex/release-v2.1.0

Conversation

@FlanChanXwO

@FlanChanXwO FlanChanXwO commented Jun 14, 2026

Copy link
Copy Markdown
Member

提升 Setu 在 NapCat / OneBot 场景下的大图发送可靠性,并补齐自动撤回范围、SexNyan 配置、Plugin Pages iframe 加载、访问控制页面可用性和 2.1.0 发布说明。

Modifications / 改动点

  • 新增 NapCat 平台传输模板,支持 stream 分块大小、本地 file:// 直通模式与额外共享目录配置。

  • 新增可信本地文件直通、发送前压缩和自动分批,降低大图与多图触发 base64 / WebSocket 限制的概率。

  • 将自动撤回升级为 none / sfw / r18 / all 范围枚举,并补齐旧全局配置与旧会话覆盖迁移。

  • 新增撤回调度器,在 direct、stream、file://、HTML fallback、forward、R18 Docx 等可拿到 message_id 的发送路径中调度撤回。

  • 补齐 SexNyan provider 模板与 proxy / uid / keyword 参数传递。

  • 修复 Dashboard Plugin Pages bridge 注入竞态,确保 iframe 场景下能正常加载。

  • 将访问控制新增/编辑记录表单改为 modal,对主视图保留模式设置、筛选和记录表格,减少页面拥挤。

  • 处理 release review findings:修正 message_id 归一化、部分批次失败聚合、配置消息解析、legacy bool 迁移一致性、stream 分块风险提示和 {r18} 占位符格式。

  • 更新 README、配置文档、命令文档、Plugin Pages 文档、测试文档、发送限制文档、changelog,并将 metadata.yaml 提升到 v2.1.0

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

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

/Users/flanchan/.local/bin/pre-commit run
# trim trailing whitespace, end-of-file-fixer, check-yaml, ruff, ruff-format: Passed

git diff --cached --check
# Passed

/Users/flanchan/.local/bin/ruff check .
# All checks passed!

/Users/flanchan/Development/SourceCode/GithubProjects/astrbot-plugin-dev/.venv/bin/python -m pytest
# 177 passed

/Users/flanchan/Development/SourceCode/GithubProjects/astrbot-plugin-dev/.venv/bin/python -m compileall main.py src tests
# Passed

node --check pages/dashboard/app.js
# Passed

浏览器验证:

  • Playwright MCP + mock Plugin Pages bridge 打开 http://127.0.0.1:8787/pages/dashboard/index.html
  • 切换到访问控制页,点击“新增记录”后 modal 可见,标题为“新增记录”,焦点进入 field-target-id,按 Escape 可关闭。
  • 点击表格首条“编辑”后 modal 可见,标题为“编辑记录”,表单带入 target_id=10001,点击“取消”可关闭。

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, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txt 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

Summary by CodeRabbit

发布说明 v2.1.0

  • New Features

    • 撤回范围扩展为四级(无/SFW/R18/全部)自动撤回。
    • 新增 platform_transports:支持 NapCat/OneBot 流式分块上传与本地 file:// 直通能力配置。
    • 发送前自动压缩大图并支持体积上限。
    • 增强 SexNyan 图源模板配置。
    • 配置自动迁移与校验“治愈”。
  • Changed

    • 默认发送模式改为自动选择。
    • 消息通知与模板覆盖默认不启用/不发送,新增定时撤回文案项。
    • Dashboard 桥接加载与访问控制新增弹窗交互;图片尺寸默认变更为 regular。
  • Documentation

    • 新增发送限制说明,更新配置/命令/测试文档以匹配新语义。

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

Sorry @FlanChanXwO, your pull request is larger than the review limit of 150000 diff characters

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@FlanChanXwO, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 31 minutes and 20 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6524d4c2-2b3f-49a6-9b69-ba3daf93d57c

📥 Commits

Reviewing files that changed from the base of the PR and between 2d3f07a and fc1e939.

📒 Files selected for processing (5)
  • pages/dashboard/css/components.css
  • pages/dashboard/css/dashboard.css
  • pages/dashboard/css/nav.css
  • pages/dashboard/index.html
  • tests/test_main_config_source.py
📝 Walkthrough

Walkthrough

本 PR 将插件版本升至 v2.1.0,核心变更包括:将自动撤回从布尔 R18 开关扩展为 none/sfw/r18/all 范围枚举,新增 NapCat 平台传输模板(本地 file:// 直通与可配置流式分块),引入图片批次分割、发送前压缩与 asyncio 撤回调度器,实现基于 schema 的配置自愈与旧键迁移,补齐 SexNyan provider 参数化,修复 Dashboard bridge 加载时序与访问控制弹窗 UI,并全面更新文档与测试覆盖。

Changes

v2.1.0 功能升级主干

Layer / File(s) Summary
撤回范围枚举与 delivery 配置模型重构
src/shared/config/models.py, src/shared/config/__init__.py, src/application/settings.py
新增 AutoRevokeScopeStrnone/sfw/r18/all)、should_auto_revoke() 判定函数、NapcatLocalFileModeStrPlatformTransportConfig;重构 DeliveryConfigsend_mode 默认改为 AUTO,引入 auto_revoke_scope/auto_revoke_delay/platform_transports/compress_* 字段);调整消息提示 enabled 默认关闭;新增 revoke_scheduled 文案配置;SetuPluginConfig NapCat 属性读取优先走平台模板。
会话配置键更名与 legacy 迁移体系
src/application/session_config/keys.py, src/infrastructure/config/legacy_migration.py, src/infrastructure/config/schema_healer.py, src/infrastructure/persistence/session_config_json_repository.py, main.py
setu.auto_revoke 替换为枚举键 setu.auto_revoke_scope;新增 legacy_migration.py 执行配置迁移(delivery/session_configs 中 auto_revoke_r18auto_revoke_scope);新增 schema_healer.py 实现递归配置自愈与规范化;JsonSessionConfigRepository 加载时检测迁移标记并自动落盘;main.py initialize() 与 terminate() 引入运行时自愈与撤回调度器清理。
发送 DTO、批次分割与图片压缩模块
src/infrastructure/sending/dto.py, src/infrastructure/sending/send_batching.py, src/infrastructure/sending/image_compressor.py
SendOptions 新增 auto_revoke_scope、NapCat stream/local-file、compress 字段;SendAttemptResult 新增 message_ids 字段与方法签名更新;新增 send_batching.pyestimate_base64_bytessplit_send_batches 贪心分批);新增 image_compressor.py(质量阶梯+尺寸阶梯压缩,Pillow 不可用时优雅降级)。
撤回调度器实现
src/infrastructure/sending/revoke_scheduler.py
新增 RevokeScheduler 类与进程级单例;校验 OneBot 平台与 delete_msg 能力后创建 asyncio 延迟删除任务;cancel_all 在插件关闭时统一取消;一组辅助函数用于平台名/bot_client 读取与能力检测。
ImageSender 批次发送与本地文件直通
src/infrastructure/sending/image_sender.py
send_images 改为压缩→估算→分批→逐批发送架构;_send_one_batch 封装本地直通/默认/NapCat local fallback/stream fallback/HTML card fallback 回退链;严格校验本地文件路径与符号链接逃逸;_stream_upload_chain 支持配置分块大小;新增 _schedule_revoke_for_result_send_post_delivery_messages 统一撤回调度与发送后通知。
SendStrategies OneBot 直发/转发与 message_id 提取
src/infrastructure/sending/send_strategies.py
新增 extract_message_ids 等 OneBot 工具函数;DirectSendStrategy 新增 allow_file_uri_passthrough 参数并感知 auto_revokeForwardSendStrategy 新增 _send_nodes_raw 提取转发 message_id;resolve_send_mode auto 条件细化。
SexNyan provider 参数化
src/infrastructure/providers/sexnyan.py, src/infrastructure/providers/__init__.py
SexNyanRunProvider 新增 proxy/uid/keyword 构造参数;fetch_image_urls 改用 httpx params 列表并应用 proxy 替换;provider 初始化链路补充 sexnyan_config 注入。
命令层空文案保护
src/infrastructure/astrbot/commands/fortune.py, src/infrastructure/astrbot/commands/setu.py
全部 yield event.plain_result(...) 路径改为通过新增 _plain(event, text) 辅助方法条件产出,文案为空时不产生空消息。
Dashboard bridge 加载时序修复与访问控制 UI 重构
pages/dashboard/index.html, pages/dashboard/app.js, pages/dashboard/css/components.css, pages/dashboard/css/dashboard.css
index.html 新增 bridge-sdk.js 脚本标签(位于 app.js 之前);app.js bridge 初始化改为轮询等待注入,超时显式报错;访问控制新增弹窗模态框承载新增/编辑记录表单;新增弹窗状态管理与错误提示样式。
配置 schema 重构
_conf_schema.json
移除旧 delivery 结构,重构为 auto_revoke_scope/platform_transports/compress 配置;新增 sexnyan provider 模板;provider image_size 默认改为 regularmessage_overrides.enabled 默认改为 false 并新增 revoke_scheduled 选项。
测试套件
tests/conftest.py, tests/infrastructure/test_image_sender.py, tests/infrastructure/test_image_compressor.py, tests/infrastructure/test_send_batching.py, tests/infrastructure/test_sexnyan_provider.py, tests/infrastructure/test_provider_init_from_config.py, tests/infrastructure/test_session_config_repo.py, tests/shared/test_config_models.py, tests/test_main_config_source.py, tests/domain/test_value_objects.py
全面新增/更新测试:本地直通信任校验、流式分块配置、撤回范围参数化、raw message_id 提取、调度器到期执行、配置迁移落盘、schema 暴露断言、Dashboard 加载顺序。
文档、CHANGELOG 与元数据
metadata.yaml, CHANGELOG.md, README.md, docs/usage/configuration.md, docs/usage/commands.md, docs/usage/plugin-pages.md, docs/project/architecture.md, docs/project/sending-limits.md, docs/dev/testing.md, skills/get-setu/SKILL.md, src/shared/logging.py, .github/PULL_REQUEST_TEMPLATE.md
版本升至 v2.1.0;新增 sending-limits.md 记录发送链路实测与约束;全量文档同步更新配置键、默认值、行为说明与 NapCat 直通机制;日志前缀更新;PR 模板简化依赖检查。

Sequence Diagram(s)

sequenceDiagram
  participant SetuPlugin as SetuPlugin.initialize
  participant heal_astrbot_plugin_config
  participant ImageSender
  participant split_send_batches
  participant _send_one_batch
  participant RevokeScheduler
  participant OneBot as OneBot bot_client

  SetuPlugin->>heal_astrbot_plugin_config: raw_config (含旧键迁移)
  heal_astrbot_plugin_config-->>SetuPlugin: healed_config

  rect rgba(100, 149, 237, 0.5)
    Note over ImageSender,split_send_batches: 发送流程
    ImageSender->>ImageSender: _compress_chain (可选)
    ImageSender->>split_send_batches: base64_sizes, mode
    split_send_batches-->>ImageSender: batches[]
  end

  rect rgba(144, 238, 144, 0.5)
    Note over ImageSender,OneBot: 逐批发送与回退
    loop 每批
      ImageSender->>_send_one_batch: batch_chain, options
      _send_one_batch->>OneBot: send_group_msg (本地/流式/直发)
      OneBot-->>_send_one_batch: send_result (含 message_ids)
    end
  end

  rect rgba(255, 165, 0, 0.5)
    Note over ImageSender,RevokeScheduler: 撤回调度
    ImageSender->>RevokeScheduler: schedule_revoke(event, message_id, delay)
    RevokeScheduler->>OneBot: delay 秒后 delete_msg(message_id)
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 小兔子写代码,撤回范围更细了,
none sfw r18 all,四个选项真不少!
本地文件直通快,批次分割不超载,
bridge 等等再就绪,空文案也不乱发。
版本升到 2.1.0,兔子拍拍爪子跑~ 🎉

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/infrastructure/astrbot/commands/setu.py (1)

109-111: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

将“配置未加载”统一改为配置消息解析路径。

这里仍直接 yield event.plain_result("配置未加载"),会绕过消息配置与覆写机制。建议改为与其他分支一致,使用 _message("config_not_loaded") + _plain(...)

💡 建议修复
         config = get_config()
         if not config:
-            yield event.plain_result("配置未加载")
+            if result := self._plain(event, self._message("config_not_loaded")):
+                yield result
             return
@@
         config = get_config()
         if not config:
-            yield event.plain_result("配置未加载")
+            if result := self._plain(event, self._message("config_not_loaded")):
+                yield result
             return

As per coding guidelines, "All user-visible prompts and messages must be retrieved through MessagesConfig / resolve_message() function, do not hardcode message text in handler code".

Also applies to: 183-186

🤖 Prompt for 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.

In `@src/infrastructure/astrbot/commands/setu.py` around lines 109 - 111, The
hardcoded message string "配置未加载" in the yield statement at lines 109-111
violates the coding guideline that all user-visible messages must be retrieved
through the MessagesConfig/resolve_message() function. Replace the hardcoded
string with a call to _message("config_not_loaded") combined with _plain(...) to
ensure the message is resolved through the configuration system. This same issue
also appears at lines 183-186 in the same file where another hardcoded message
is used instead of the message configuration system. Apply the same fix pattern
to both locations to maintain consistency with the codebase guidelines.

Source: Coding guidelines

src/infrastructure/sending/image_sender.py (1)

867-889: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

用户可见文案仍有硬编码,违反消息配置约束

Line [881]-Line [882] 与 Line [888] 直接返回硬编码中文文案。按仓库规范,这类用户可见消息应统一走 MessagesConfig / resolve_message(),避免多语言与配置覆盖失效。

建议修复(示例)
     def _format_found_message(
@@
         if config and hasattr(config, "format_found_message"):
             return config.format_found_message(count, revoke_delay, scope, r18)
-        if revoke_delay and revoke_delay > 0:
-            return f"找到 {count} 张图,将在 {revoke_delay} 秒后撤回"
-        return f"找到 {count} 张图"
+        return self._resolve_message(
+            "found",
+            count=count,
+            revoke_delay=revoke_delay,
+            scope=scope,
+            r18=r18,
+        )

     def _send_failed_message(self) -> str | None:
         config = self._config
         if config and hasattr(config, "resolve_message"):
             return config.resolve_message("send_failed")
-        return "图片发送失败,请稍后再试。"
+        return self._resolve_message("send_failed")

As per coding guidelines, “All user-visible prompts and messages must be retrieved through MessagesConfig / resolve_message() function, do not hardcode message text in handler code”; if message keys/placeholders change, also update src/shared/config/models.py.

🤖 Prompt for 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.

In `@src/infrastructure/sending/image_sender.py` around lines 867 - 889, The
_format_found_message method contains hardcoded Chinese user-visible messages on
lines 881-882 and 888 that violate the coding guideline requiring all
user-visible messages to be retrieved through MessagesConfig resolve_message()
function. Replace the hardcoded return statements with calls to
config.resolve_message() similar to how _send_failed_message handles its message
retrieval, passing appropriate message keys that correspond to the different
scenarios (with revoke_delay versus default). Also update
src/shared/config/models.py to define the message keys needed for these resolved
messages.

Source: Coding guidelines

🧹 Nitpick comments (3)
_conf_schema.json (1)

282-287: 💤 Low value

stream_chunk_kb slider 上限 4096 KiB 可能过大。

NapCat upload_file_streamchunk_data 字段传输 base64 字符串,4096 KiB 原始数据对应约 5.5 MiB base64,可能超过某些 WebSocket 实现的单帧限制。根据上下文,该功能本身是为了绕开大体积限制,建议将 slider max 调低至更保守的值(如 512 或 1024),或在 hint 中补充说明较大分块可能导致的风险。

🤖 Prompt for 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.

In `@_conf_schema.json` around lines 282 - 287, The stream_chunk_kb slider
configuration has a max value of 4096 KiB, which when base64-encoded for
transmission could exceed WebSocket frame limits (approximately 5.5 MiB). Either
reduce the slider max property in the stream_chunk_kb field to a more
conservative value such as 512 or 1024 KiB to prevent WebSocket transmission
issues, or enhance the hint property to warn users that larger chunk sizes may
cause transmission failures on certain WebSocket implementations.
src/shared/config/models.py (1)

857-874: 💤 Low value

r18 参数类型签名包含 bool | str,但传递给 resolve_message 时未做类型统一。

r18 参数声明为 bool | str = "",但在调用 resolve_message 时直接传递,当调用者传入 True/False 时占位符会变成 "True"/"False" 字符串。如果模板中需要基于此显示中文提示(如"是/否"),当前行为可能不符合预期。

建议明确该参数的预期用途:若仅用于调试/日志,当前实现可接受;若用于用户可见文案,考虑在此处统一转换。

🤖 Prompt for 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.

In `@src/shared/config/models.py` around lines 857 - 874, The `r18` parameter in
the `format_found_message` method is typed as `bool | str` but is passed
directly to `resolve_message` without type normalization. When callers pass
boolean values (True/False), they get stringified as "True"/"False" which may
not be appropriate for user-facing templates. Before passing the `r18` parameter
to the `resolve_message` call, add logic to convert boolean values to an
appropriate string representation (such as an empty string, a localized yes/no
value, or other suitable convention) while preserving string values as-is,
ensuring consistent placeholder substitution regardless of whether the parameter
is passed as a boolean or string.
src/infrastructure/config/legacy_migration.py (1)

8-8: 💤 Low value

_TRUE_VALUESkeys.py 中的 TRUE_VALUES 存在重复且不一致。

keys.py 中的 TRUE_VALUES 包含更多变体(如 "y", "yes", "enable", "enabled", "是"),而此处的 _TRUE_VALUES 缺少这些值。这可能导致迁移行为与运行时规范化行为不一致。

建议复用 keys.py 中的逻辑或常量,以保持一致性:

♻️ 建议修改
-from copy import deepcopy
+from copy import deepcopy
 from typing import Any

+from ...application.session_config.keys import TRUE_VALUES as _TRUE_VALUES
-_TRUE_VALUES = {"1", "true", "yes", "on", "enable", "enabled", "开", "开启", "启用"}

或者直接导入并调用 _normalize_bool

+from ...application.session_config.keys import _normalize_bool
+
+def _legacy_revoke_bool_to_scope(value: Any) -> str:
+    """Map the old bool-ish R18 revoke toggle to the new scope enum."""
+    try:
+        return "r18" if _normalize_bool(value) else "none"
+    except Exception:
+        return "none"
🤖 Prompt for 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.

In `@src/infrastructure/config/legacy_migration.py` at line 8, The `_TRUE_VALUES`
constant in legacy_migration.py is duplicated and inconsistent with the
`TRUE_VALUES` constant in keys.py, which contains additional boolean variants
like "y", "是", etc. This inconsistency causes migration behavior to differ from
runtime normalization behavior. Remove the duplicate `_TRUE_VALUES` definition
and instead import the `_normalize_bool` function from keys.py (or import
`TRUE_VALUES` directly from keys.py), then use it consistently throughout the
migration logic to ensure both migration and runtime normalization handle the
same set of boolean values.
🤖 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 `@src/infrastructure/sending/dto.py`:
- Around line 40-54: The current implementation of the `success` and
`pending_delivery` classmethods treats string message IDs as iterables, causing
"123" to be split into ["1", "2", "3"]. Fix this by normalizing the message_ids
parameter handling in both methods: check if message_ids is a string and treat
it as a single ID, otherwise iterate normally, and filter out any empty or
whitespace-only values. Apply this normalization logic consistently in both
classmethods before creating the tuple.

In `@src/infrastructure/sending/image_sender.py`:
- Around line 229-289: The batch aggregation logic only updates state variables
when send_result.accepted is True, meaning failed batches (when accepted is
False) are silently ignored. This causes the code to incorrectly report overall
success when some batches fail. Add a new variable to track failed batches
(e.g., any_failed) and set it to True whenever send_result.accepted is False in
the loop starting at line 229. Then update the aggregation logic after the loop
to handle the partial failure case: when any batches failed but not all failed
(both any_failed and not all_failed are true), log an appropriate warning and
yield a result that reflects the partial failure rather than reporting success
via the post-delivery messages at line 262 onwards.

---

Outside diff comments:
In `@src/infrastructure/astrbot/commands/setu.py`:
- Around line 109-111: The hardcoded message string "配置未加载" in the yield
statement at lines 109-111 violates the coding guideline that all user-visible
messages must be retrieved through the MessagesConfig/resolve_message()
function. Replace the hardcoded string with a call to
_message("config_not_loaded") combined with _plain(...) to ensure the message is
resolved through the configuration system. This same issue also appears at lines
183-186 in the same file where another hardcoded message is used instead of the
message configuration system. Apply the same fix pattern to both locations to
maintain consistency with the codebase guidelines.

In `@src/infrastructure/sending/image_sender.py`:
- Around line 867-889: The _format_found_message method contains hardcoded
Chinese user-visible messages on lines 881-882 and 888 that violate the coding
guideline requiring all user-visible messages to be retrieved through
MessagesConfig resolve_message() function. Replace the hardcoded return
statements with calls to config.resolve_message() similar to how
_send_failed_message handles its message retrieval, passing appropriate message
keys that correspond to the different scenarios (with revoke_delay versus
default). Also update src/shared/config/models.py to define the message keys
needed for these resolved messages.

---

Nitpick comments:
In `@_conf_schema.json`:
- Around line 282-287: The stream_chunk_kb slider configuration has a max value
of 4096 KiB, which when base64-encoded for transmission could exceed WebSocket
frame limits (approximately 5.5 MiB). Either reduce the slider max property in
the stream_chunk_kb field to a more conservative value such as 512 or 1024 KiB
to prevent WebSocket transmission issues, or enhance the hint property to warn
users that larger chunk sizes may cause transmission failures on certain
WebSocket implementations.

In `@src/infrastructure/config/legacy_migration.py`:
- Line 8: The `_TRUE_VALUES` constant in legacy_migration.py is duplicated and
inconsistent with the `TRUE_VALUES` constant in keys.py, which contains
additional boolean variants like "y", "是", etc. This inconsistency causes
migration behavior to differ from runtime normalization behavior. Remove the
duplicate `_TRUE_VALUES` definition and instead import the `_normalize_bool`
function from keys.py (or import `TRUE_VALUES` directly from keys.py), then use
it consistently throughout the migration logic to ensure both migration and
runtime normalization handle the same set of boolean values.

In `@src/shared/config/models.py`:
- Around line 857-874: The `r18` parameter in the `format_found_message` method
is typed as `bool | str` but is passed directly to `resolve_message` without
type normalization. When callers pass boolean values (True/False), they get
stringified as "True"/"False" which may not be appropriate for user-facing
templates. Before passing the `r18` parameter to the `resolve_message` call, add
logic to convert boolean values to an appropriate string representation (such as
an empty string, a localized yes/no value, or other suitable convention) while
preserving string values as-is, ensuring consistent placeholder substitution
regardless of whether the parameter is passed as a boolean or string.
🪄 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: 904278e5-7f3a-4e6d-abb7-e58c556501aa

📥 Commits

Reviewing files that changed from the base of the PR and between cd7f12a and df3f10b.

⛔ Files ignored due to path filters (5)
  • assets/img_ob_preview.png is excluded by !**/*.png
  • assets/jrys_preview.png is excluded by !**/*.png
  • assets/merge_send_preview.png is excluded by !**/*.png
  • assets/tag_search_preview.png is excluded by !**/*.png
  • logo.png is excluded by !**/*.png
📒 Files selected for processing (51)
  • .github/PULL_REQUEST_TEMPLATE.md
  • CHANGELOG.md
  • README.md
  • _conf_schema.json
  • assets/img_ob_preview.webp
  • assets/jrys_preview.webp
  • assets/merge_send_preview.webp
  • assets/tag_search_preview.webp
  • docs/dev/testing.md
  • docs/project/architecture.md
  • docs/project/sending-limits.md
  • docs/usage/commands.md
  • docs/usage/configuration.md
  • docs/usage/plugin-pages.md
  • main.py
  • metadata.yaml
  • pages/dashboard/app.js
  • pages/dashboard/index.html
  • skills/get-setu/SKILL.md
  • src/application/session_config/__init__.py
  • src/application/session_config/keys.py
  • src/application/session_config/service.py
  • src/application/settings.py
  • src/infrastructure/astrbot/commands/fortune.py
  • src/infrastructure/astrbot/commands/setu.py
  • src/infrastructure/config/__init__.py
  • src/infrastructure/config/legacy_migration.py
  • src/infrastructure/config/schema_healer.py
  • src/infrastructure/persistence/session_config_json_repository.py
  • src/infrastructure/providers/__init__.py
  • src/infrastructure/providers/sexnyan.py
  • src/infrastructure/sending/__init__.py
  • src/infrastructure/sending/dto.py
  • src/infrastructure/sending/image_compressor.py
  • src/infrastructure/sending/image_sender.py
  • src/infrastructure/sending/revoke_scheduler.py
  • src/infrastructure/sending/send_batching.py
  • src/infrastructure/sending/send_strategies.py
  • src/shared/config/__init__.py
  • src/shared/config/models.py
  • src/shared/logging.py
  • tests/conftest.py
  • tests/domain/test_value_objects.py
  • tests/infrastructure/test_image_compressor.py
  • tests/infrastructure/test_image_sender.py
  • tests/infrastructure/test_provider_init_from_config.py
  • tests/infrastructure/test_send_batching.py
  • tests/infrastructure/test_session_config_repo.py
  • tests/infrastructure/test_sexnyan_provider.py
  • tests/shared/test_config_models.py
  • tests/test_main_config_source.py

Comment thread src/infrastructure/sending/dto.py Outdated
Comment thread src/infrastructure/sending/image_sender.py

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

🧹 Nitpick comments (1)
src/infrastructure/sending/image_sender.py (1)

909-913: 💤 Low value

硬编码兜底消息与编码规范存在轻微冲突

根据编码规范,所有用户可见消息应通过 MessagesConfig / resolve_message() 获取。第 913 行的硬编码兜底文案 "图片发送失败,请稍后再试。" 严格来说违反此规范。

作为防御性编程这是可以理解的,但如果希望完全符合规范,可考虑返回 None 或空字符串,让调用方决定是否需要兜底。

🤖 Prompt for 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.

In `@src/infrastructure/sending/image_sender.py` around lines 909 - 913, The
_send_failed_message method in image_sender.py contains a hard-coded Chinese
fallback message that violates the coding standard requiring all user-visible
messages to come from MessagesConfig via resolve_message(). Remove the
hard-coded string "图片发送失败,请稍后再试。" and instead return None or an empty string as
the fallback value, allowing the calling code to handle the fallback behavior
appropriately rather than enforcing it at this layer.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In `@src/infrastructure/sending/image_sender.py`:
- Around line 909-913: The _send_failed_message method in image_sender.py
contains a hard-coded Chinese fallback message that violates the coding standard
requiring all user-visible messages to come from MessagesConfig via
resolve_message(). Remove the hard-coded string "图片发送失败,请稍后再试。" and instead
return None or an empty string as the fallback value, allowing the calling code
to handle the fallback behavior appropriately rather than enforcing it at this
layer.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 91274775-6f9f-4924-a064-d3c246b9e693

📥 Commits

Reviewing files that changed from the base of the PR and between df3f10b and 2d3f07a.

📒 Files selected for processing (16)
  • CHANGELOG.md
  • _conf_schema.json
  • docs/usage/plugin-pages.md
  • pages/dashboard/app.js
  • pages/dashboard/css/components.css
  • pages/dashboard/css/dashboard.css
  • pages/dashboard/index.html
  • src/infrastructure/astrbot/commands/setu.py
  • src/infrastructure/config/legacy_migration.py
  • src/infrastructure/sending/dto.py
  • src/infrastructure/sending/image_sender.py
  • src/shared/config/models.py
  • tests/domain/test_value_objects.py
  • tests/infrastructure/test_image_sender.py
  • tests/shared/test_config_models.py
  • tests/test_main_config_source.py
✅ Files skipped from review due to trivial changes (2)
  • CHANGELOG.md
  • docs/usage/plugin-pages.md
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/infrastructure/config/legacy_migration.py
  • tests/domain/test_value_objects.py
  • src/infrastructure/astrbot/commands/setu.py
  • _conf_schema.json
  • tests/infrastructure/test_image_sender.py
  • tests/shared/test_config_models.py
  • src/shared/config/models.py

@FlanChanXwO
FlanChanXwO merged commit af68f46 into master Jun 14, 2026
3 checks passed
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